From 06bf19544fbf1c80c97a1f6355491b1c8847134a Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Mon, 3 Jun 2024 15:05:14 +0800 Subject: [PATCH] feat: advanced resolver incremental compile. 1. Namer and Advanced Resolver support incremental compilation, clear cache by pkg and only update new pkg 2. Add gs cache in lsp state 3. Namer and Advanced Resolver modify gs in place(&mut) to reduce clone Signed-off-by: he1pa <18012015693@163.com> --- kclvm/api/src/service/service_impl.rs | 2 +- kclvm/loader/src/lib.rs | 8 +- kclvm/sema/src/advanced_resolver/mod.rs | 37 +++--- kclvm/sema/src/advanced_resolver/node.rs | 106 +++++++++++----- kclvm/sema/src/core/global_state.rs | 151 +++++++++++++++++------ kclvm/sema/src/core/package.rs | 8 ++ kclvm/sema/src/core/scope.rs | 31 ++++- kclvm/sema/src/core/symbol.rs | 105 +++++++++++++++- kclvm/sema/src/namer/mod.rs | 90 ++++++++------ kclvm/sema/src/namer/node.rs | 30 +++++ kclvm/sema/src/resolver/arg.rs | 1 + kclvm/sema/src/resolver/mod.rs | 12 +- kclvm/sema/src/resolver/node.rs | 22 +++- kclvm/sema/src/resolver/schema.rs | 3 + kclvm/sema/src/resolver/scope.rs | 11 +- kclvm/sema/src/resolver/ty.rs | 3 + kclvm/tools/src/LSP/src/find_refs.rs | 21 +--- kclvm/tools/src/LSP/src/quick_fix.rs | 1 + kclvm/tools/src/LSP/src/rename.rs | 10 +- kclvm/tools/src/LSP/src/request.rs | 6 - kclvm/tools/src/LSP/src/state.rs | 8 ++ kclvm/tools/src/LSP/src/tests.rs | 10 ++ kclvm/tools/src/LSP/src/util.rs | 40 ++++-- 23 files changed, 538 insertions(+), 178 deletions(-) diff --git a/kclvm/api/src/service/service_impl.rs b/kclvm/api/src/service/service_impl.rs index cce3184e5..f5a95ed8d 100644 --- a/kclvm/api/src/service/service_impl.rs +++ b/kclvm/api/src/service/service_impl.rs @@ -231,7 +231,7 @@ impl KclvmServiceImpl { }, module_cache, scope_cache, - GlobalState::default(), + &mut GlobalState::default(), )?; if args.with_ast_index { // Thread local options diff --git a/kclvm/loader/src/lib.rs b/kclvm/loader/src/lib.rs index a79a6dbcf..f418e6c5c 100644 --- a/kclvm/loader/src/lib.rs +++ b/kclvm/loader/src/lib.rs @@ -116,7 +116,7 @@ pub fn load_packages(opts: &LoadPackageOptions) -> Result { opts, KCLModuleCache::default(), KCLScopeCache::default(), - GlobalState::default(), + &mut GlobalState::default(), ) } @@ -126,7 +126,7 @@ pub fn load_packages_with_cache( opts: &LoadPackageOptions, module_cache: KCLModuleCache, scope_cache: KCLScopeCache, - gs: GlobalState, + gs: &mut GlobalState, ) -> Result { let sess = ParseSessionRef::default(); let paths: Vec<&str> = opts.paths.iter().map(|s| s.as_str()).collect(); @@ -149,8 +149,8 @@ pub fn load_packages_with_cache( Some(scope_cache), ); let node_ty_map = prog_scope.node_ty_map; - let gs = Namer::find_symbols(&program, gs); - let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map.clone())?; + Namer::find_symbols(&program, gs); + AdvancedResolver::resolve_program(&program, gs, node_ty_map.clone())?; (program, prog_scope.handler.diagnostics.clone(), gs) } else { (parse_result.program, IndexSet::default(), gs) diff --git a/kclvm/sema/src/advanced_resolver/mod.rs b/kclvm/sema/src/advanced_resolver/mod.rs index 3d647de96..e2cbd1a4f 100644 --- a/kclvm/sema/src/advanced_resolver/mod.rs +++ b/kclvm/sema/src/advanced_resolver/mod.rs @@ -34,6 +34,8 @@ └─────────────────────┘ */ +use std::{cell::RefCell, rc::Rc}; + use indexmap::IndexSet; use kclvm_error::Position; @@ -60,12 +62,12 @@ mod node; /// so that toolchain can query semantic information about the AST pub struct AdvancedResolver<'ctx> { pub(crate) ctx: Context<'ctx>, - pub(crate) gs: GlobalState, + pub(crate) gs: &'ctx mut GlobalState, } pub struct Context<'ctx> { pub program: &'ctx Program, - node_ty_map: NodeTyMap, + node_ty_map: Rc>, scopes: Vec, current_pkgpath: Option, current_filename: Option, @@ -93,9 +95,9 @@ impl<'ctx> Context<'ctx> { impl<'ctx> AdvancedResolver<'ctx> { pub fn resolve_program( program: &'ctx Program, - gs: GlobalState, - node_ty_map: NodeTyMap, - ) -> anyhow::Result { + gs: &'ctx mut GlobalState, + node_ty_map: Rc>, + ) -> anyhow::Result<()> { let mut advanced_resolver = Self { gs, ctx: Context { @@ -111,8 +113,10 @@ impl<'ctx> AdvancedResolver<'ctx> { maybe_def: false, }, }; - for (name, modules) in advanced_resolver.ctx.program.pkgs.iter() { + if !advanced_resolver.gs.new_or_invalidate_pkgs.contains(name) { + continue; + } advanced_resolver.ctx.current_pkgpath = Some(name.clone()); if let Some(pkg_info) = advanced_resolver.gs.get_packages().get_package_info(name) { if modules.is_empty() { @@ -135,7 +139,8 @@ impl<'ctx> AdvancedResolver<'ctx> { } advanced_resolver.gs.build_sema_db(); - Ok(advanced_resolver.gs) + advanced_resolver.gs.new_or_invalidate_pkgs.clear(); + Ok(()) } fn enter_root_scope( @@ -290,8 +295,8 @@ mod tests { let mut program = load_program(sess.clone(), &[&path], None, None) .unwrap() .program; - let gs = GlobalState::default(); - let gs = Namer::find_symbols(&program, gs); + let mut gs = GlobalState::default(); + Namer::find_symbols(&program, &mut gs); let node_ty_map = resolver::resolve_program_with_opts( &mut program, @@ -303,7 +308,7 @@ mod tests { None, ) .node_ty_map; - let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map).unwrap(); + AdvancedResolver::resolve_program(&program, &mut gs, node_ty_map).unwrap(); let base_path = Path::new(".").canonicalize().unwrap(); // print_symbols_info(&gs); let except_symbols = vec![ @@ -1229,10 +1234,10 @@ mod tests { let mut program = load_program(sess.clone(), &[&path], None, None) .unwrap() .program; - let gs = GlobalState::default(); - let gs = Namer::find_symbols(&program, gs); + let mut gs = GlobalState::default(); + Namer::find_symbols(&program, &mut gs); let node_ty_map = resolver::resolve_program(&mut program).node_ty_map; - let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map).unwrap(); + AdvancedResolver::resolve_program(&program, &mut gs, node_ty_map).unwrap(); let base_path = Path::new(".").canonicalize().unwrap(); let test_cases = vec![ @@ -1306,10 +1311,10 @@ mod tests { let mut program = load_program(sess.clone(), &[&path], None, None) .unwrap() .program; - let gs = GlobalState::default(); - let gs = Namer::find_symbols(&program, gs); + let mut gs = GlobalState::default(); + Namer::find_symbols(&program, &mut gs); let node_ty_map = resolver::resolve_program(&mut program).node_ty_map; - let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map).unwrap(); + AdvancedResolver::resolve_program(&program, &mut gs, node_ty_map).unwrap(); let base_path = Path::new(".").canonicalize().unwrap(); let scope_test_cases = vec![ diff --git a/kclvm/sema/src/advanced_resolver/node.rs b/kclvm/sema/src/advanced_resolver/node.rs index 8a475ac68..da2d82521 100644 --- a/kclvm/sema/src/advanced_resolver/node.rs +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -77,6 +77,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&type_alias_stmt.type_name.id)) .map(|ty| ty.clone()), doc: None, @@ -149,10 +150,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { None => return Ok(None), }; unresolved.def = Some(package_symbol); - let unresolved_ref = self - .gs - .get_symbols_mut() - .alloc_unresolved_symbol(unresolved, self.ctx.get_node_key(&ast_id)); + let unresolved_ref = self.gs.get_symbols_mut().alloc_unresolved_symbol( + unresolved, + self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), + ); self.gs .get_symbols_mut() .symbols_info @@ -170,8 +172,10 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let schema_ty = self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&schema_stmt.name.id)) - .ok_or(anyhow!("schema_ty not found"))?; + .ok_or(anyhow!("schema_ty not found"))? + .clone(); let schema_symbol = self .gs .get_symbols() @@ -204,6 +208,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let func_symbol_ref = self.gs.get_symbols_mut().alloc_value_symbol( func_value, self.ctx.get_node_key(&ast::AstIndex::default()), + self.ctx.current_pkgpath.clone().unwrap(), ); schema_builtin_member.insert(name.to_string(), func_symbol_ref); } @@ -277,12 +282,14 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let value = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(key_name.clone(), start, end, Some(schema_symbol), false), self.ctx.get_node_key(&index_signature.id), + self.ctx.current_pkgpath.clone().unwrap(), ); if let Some(symbol) = self.gs.get_symbols_mut().values.get_mut(value.get_id()) { symbol.sema_info = KCLSymbolSemanticInfo { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&index_signature.id)) .map(|ty| ty.clone()), doc: None, @@ -346,6 +353,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let rule_ty = self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&rule_stmt.name.id)) .ok_or(anyhow!("rule_ty not found"))? .clone(); @@ -364,6 +372,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&rule_stmt.name.id)) .map(|ty| ty.clone()), doc: rule_stmt.doc.as_ref().map(|doc| doc.node.clone()), @@ -419,6 +428,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let value = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(name.clone(), start_pos, end_pos, None, false), self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), ); self.gs .get_scopes_mut() @@ -428,6 +438,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(ast_id)) .map(|ty| ty.clone()), doc: None, @@ -478,6 +489,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&schema_attr.name.id)) .map(|ty| ty.clone()), doc, @@ -517,6 +529,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let mut parent_ty = match self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&selector_expr.value.id)) { Some(ty) => ty.clone(), @@ -536,16 +549,22 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let ast_id = name.id.clone(); let mut unresolved = UnresolvedSymbol::new(name.node.clone(), start_pos, end_pos, None); unresolved.def = Some(def_symbol_ref); - let unresolved_ref = self - .gs - .get_symbols_mut() - .alloc_unresolved_symbol(unresolved, self.ctx.get_node_key(&ast_id)); + let unresolved_ref = self.gs.get_symbols_mut().alloc_unresolved_symbol( + unresolved, + self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), + ); let cur_scope = *self.ctx.scopes.last().unwrap(); self.gs .get_scopes_mut() .add_ref_to_scope(cur_scope, unresolved_ref); - parent_ty = match self.ctx.node_ty_map.get(&self.ctx.get_node_key(&name.id)) { + parent_ty = match self + .ctx + .node_ty_map + .borrow() + .get(&self.ctx.get_node_key(&name.id)) + { Some(ty) => ty.clone(), None => return Ok(None), }; @@ -683,6 +702,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { let schema_ty = self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&schema_expr.name.id)) .ok_or(anyhow!("schema_ty not found"))? .clone(); @@ -804,10 +824,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { fn walk_comment(&mut self, comment: &'ctx ast::Comment) -> Self::Result { let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); let comment_symbol = CommentSymbol::new(start, end, comment.text.clone()); - Ok(self - .gs - .get_symbols_mut() - .alloc_comment_symbol(comment_symbol, self.ctx.get_node_key(&self.ctx.cur_node))) + Ok(self.gs.get_symbols_mut().alloc_comment_symbol( + comment_symbol, + self.ctx.get_node_key(&self.ctx.cur_node), + self.ctx.current_pkgpath.clone().unwrap(), + )) } fn walk_missing_expr(&mut self, _missing_expr: &'ctx ast::MissingExpr) -> Self::Result { @@ -832,7 +853,12 @@ impl<'ctx> AdvancedResolver<'ctx> { } self.ctx.cur_node = expr.id.clone(); - if let Some(expr_ty) = self.ctx.node_ty_map.get(&self.ctx.get_node_key(&expr.id)) { + if let Some(expr_ty) = self + .ctx + .node_ty_map + .borrow() + .get(&self.ctx.get_node_key(&expr.id)) + { match &expr_ty.kind { TypeKind::Schema(_) => { let schema_symbol = self @@ -852,7 +878,12 @@ impl<'ctx> AdvancedResolver<'ctx> { self.ctx.schema_symbol_stack.pop(); match expr_symbol { - Ok(None) => match self.ctx.node_ty_map.get(&self.ctx.get_node_key(&expr.id)) { + Ok(None) => match self + .ctx + .node_ty_map + .borrow() + .get(&self.ctx.get_node_key(&expr.id)) + { Some(ty) => { if let ast::Expr::Missing(_) = expr.node { return Ok(None); @@ -865,10 +896,11 @@ impl<'ctx> AdvancedResolver<'ctx> { None, ); expr_symbol.sema_info.ty = Some(ty.clone()); - Ok(self - .gs - .get_symbols_mut() - .alloc_expression_symbol(expr_symbol, self.ctx.get_node_key(&expr.id))) + Ok(self.gs.get_symbols_mut().alloc_expression_symbol( + expr_symbol, + self.ctx.get_node_key(&expr.id), + self.ctx.current_pkgpath.clone().unwrap(), + )) } None => Ok(None), }, @@ -921,6 +953,7 @@ impl<'ctx> AdvancedResolver<'ctx> { if let Some(ty) = self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&first_name.id)) { self.gs @@ -946,10 +979,11 @@ impl<'ctx> AdvancedResolver<'ctx> { let mut first_unresolved = UnresolvedSymbol::new(first_name.node.clone(), start_pos, end_pos, None); first_unresolved.def = Some(symbol_ref); - let first_unresolved_ref = self - .gs - .get_symbols_mut() - .alloc_unresolved_symbol(first_unresolved, self.ctx.get_node_key(&ast_id)); + let first_unresolved_ref = self.gs.get_symbols_mut().alloc_unresolved_symbol( + first_unresolved, + self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), + ); let cur_scope = *self.ctx.scopes.last().unwrap(); self.gs .get_scopes_mut() @@ -959,6 +993,7 @@ impl<'ctx> AdvancedResolver<'ctx> { let mut parent_ty = match self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&first_name.id)) { Some(ty) => ty.clone(), @@ -981,17 +1016,22 @@ impl<'ctx> AdvancedResolver<'ctx> { let mut unresolved = UnresolvedSymbol::new(name.node.clone(), start_pos, end_pos, None); unresolved.def = Some(def_symbol_ref); - let unresolved_ref = self - .gs - .get_symbols_mut() - .alloc_unresolved_symbol(unresolved, self.ctx.get_node_key(&ast_id)); + let unresolved_ref = self.gs.get_symbols_mut().alloc_unresolved_symbol( + unresolved, + self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), + ); let cur_scope = *self.ctx.scopes.last().unwrap(); self.gs .get_scopes_mut() .add_ref_to_scope(cur_scope, unresolved_ref); - parent_ty = match self.ctx.node_ty_map.get(&self.ctx.get_node_key(&name.id)) + parent_ty = match self + .ctx + .node_ty_map + .borrow() + .get(&self.ctx.get_node_key(&name.id)) { Some(ty) => ty.clone(), None => return Ok(None), @@ -1010,6 +1050,7 @@ impl<'ctx> AdvancedResolver<'ctx> { let first_value = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(first_name.node.clone(), start_pos, end_pos, None, false), self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), ); self.gs.get_scopes_mut().add_def_to_scope( cur_scope, @@ -1027,6 +1068,7 @@ impl<'ctx> AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&first_name.id)) .map(|ty| ty.clone()), doc: None, @@ -1040,6 +1082,7 @@ impl<'ctx> AdvancedResolver<'ctx> { let value = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(name.node.clone(), start_pos, end_pos, None, false), self.ctx.get_node_key(&ast_id), + self.ctx.current_pkgpath.clone().unwrap(), ); self.gs.get_scopes_mut().add_def_to_scope( @@ -1055,6 +1098,7 @@ impl<'ctx> AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&name.id)) .map(|ty| ty.clone()), doc: None, @@ -1098,6 +1142,7 @@ impl<'ctx> AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(id)) .map(|ty| ty.clone()), doc: None, @@ -1183,6 +1228,7 @@ impl<'ctx> AdvancedResolver<'ctx> { let value = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(kw.node.arg.node.get_name(), start_pos, end_pos, None, false), self.ctx.get_node_key(&kw.id), + self.ctx.current_pkgpath.clone().unwrap(), ); if let Some(value) = self.gs.get_symbols_mut().values.get_mut(value.get_id()) { @@ -1190,6 +1236,7 @@ impl<'ctx> AdvancedResolver<'ctx> { ty: self .ctx .node_ty_map + .borrow() .get(&self.ctx.get_node_key(&kw.id)) .map(|ty| ty.clone()), doc: None, @@ -1257,6 +1304,7 @@ impl<'ctx> AdvancedResolver<'ctx> { self.gs.get_symbols_mut().alloc_decorator_symbol( decorator_symbol, self.ctx.get_node_key(&self.ctx.cur_node), + self.ctx.current_pkgpath.clone().unwrap(), ); } } diff --git a/kclvm/sema/src/core/global_state.rs b/kclvm/sema/src/core/global_state.rs index b5ec23208..bd938c607 100644 --- a/kclvm/sema/src/core/global_state.rs +++ b/kclvm/sema/src/core/global_state.rs @@ -1,4 +1,6 @@ -use indexmap::IndexMap; +use std::collections::HashSet; + +use indexmap::{IndexMap, IndexSet}; use kclvm_error::Position; use super::{ @@ -19,6 +21,8 @@ pub struct GlobalState { packages: PackageDB, // store semantic information after analysis pub(crate) sema_db: SemanticDB, + // new and invalidate(changed and affected by changed) pkg from CachedScope::update() + pub new_or_invalidate_pkgs: HashSet, } impl GlobalState { @@ -49,6 +53,10 @@ impl GlobalState { pub fn get_sema_db(&self) -> &SemanticDB { &self.sema_db } + + pub fn get_sema_db_mut(&mut self) -> &mut SemanticDB { + &mut self.sema_db + } } impl GlobalState { @@ -288,18 +296,26 @@ impl GlobalState { } impl GlobalState { - fn build_sema_db_with_symbols(&self, file_sema_map: &mut IndexMap) { + fn build_sema_db_with_symbols( + &self, + file_sema_map_cache: &mut IndexMap, + ) { // put symbols + let mut file_sema_map: IndexMap = IndexMap::new(); + for (index, symbol) in self.symbols.schemas.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Schema, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -310,15 +326,18 @@ impl GlobalState { ); } for (index, symbol) in self.symbols.type_aliases.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::TypeAlias, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -329,15 +348,18 @@ impl GlobalState { ); } for (index, symbol) in self.symbols.attributes.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Attribute, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -348,15 +370,18 @@ impl GlobalState { ); } for (index, symbol) in self.symbols.rules.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Rule, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -367,15 +392,18 @@ impl GlobalState { ); } for (index, symbol) in self.symbols.values.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Value, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -386,15 +414,18 @@ impl GlobalState { ); } for (index, symbol) in self.symbols.unresolved.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Unresolved, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -406,15 +437,19 @@ impl GlobalState { } for (index, symbol) in self.symbols.exprs.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } + let symbol_ref = SymbolRef { kind: SymbolKind::Expression, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -426,15 +461,18 @@ impl GlobalState { } for (index, symbol) in self.symbols.comments.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Comment, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -446,15 +484,18 @@ impl GlobalState { } for (index, symbol) in self.symbols.decorators.iter() { + if file_sema_map_cache.contains_key(&symbol.start.filename) { + continue; + } let symbol_ref = SymbolRef { kind: SymbolKind::Decorator, id: index, }; - let filename = symbol.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &symbol.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.symbols.push(symbol_ref); file_sema_info.symbol_locs.insert( symbol_ref, @@ -473,6 +514,8 @@ impl GlobalState { .symbols .sort_by_key(|symbol_ref| sema_info.symbol_locs.get(symbol_ref).unwrap()) } + + file_sema_map_cache.extend(file_sema_map); } fn build_sema_db_with_scopes(&self, file_sema_map: &mut IndexMap) { // put scope @@ -481,11 +524,11 @@ impl GlobalState { kind: ScopeKind::Local, id: index, }; - let filename = scope.start.filename.clone(); - if !file_sema_map.contains_key(&filename) { + let filename = &scope.start.filename; + if !file_sema_map.contains_key(filename) { file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); } - let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + let file_sema_info = file_sema_map.get_mut(filename).unwrap(); file_sema_info.local_scope_locs.insert( scope_ref, CachedRange { @@ -500,7 +543,7 @@ impl GlobalState { }, ); file_sema_map - .get_mut(&filename) + .get_mut(filename) .unwrap() .scopes .push(scope_ref); @@ -535,11 +578,43 @@ impl GlobalState { } pub(crate) fn build_sema_db(&mut self) { - let mut file_sema_map = IndexMap::::default(); - self.build_sema_db_with_symbols(&mut file_sema_map); - self.build_sema_db_with_scopes(&mut file_sema_map); - self.sort_local_scopes(&mut file_sema_map); + let mut file_sema_map_cache = self.get_sema_db_mut().file_sema_map.clone(); + + self.build_sema_db_with_symbols(&mut file_sema_map_cache); + self.build_sema_db_with_scopes(&mut file_sema_map_cache); + self.sort_local_scopes(&mut file_sema_map_cache); + + self.sema_db.file_sema_map = file_sema_map_cache; + } + + pub fn clear_cache(&mut self) { + let invalidate_pkgs = self.new_or_invalidate_pkgs.clone(); + self.clear_sema_db_cache(&invalidate_pkgs); + self.get_scopes_mut().clear_cache(&invalidate_pkgs); + self.get_packages_mut().clear_cache(&invalidate_pkgs); + self.get_symbols_mut().clear_cache(&invalidate_pkgs); + } - self.sema_db.file_sema_map = file_sema_map; + fn clear_sema_db_cache(&mut self, invalidate_pkgs: &HashSet) { + let mut to_remove: Vec = Vec::new(); + let mut files: IndexSet = IndexSet::new(); + for invalidate_pkg in invalidate_pkgs { + if let Some(symbols) = self + .get_symbols() + .symbols_info + .pkg_symbol_map + .get(invalidate_pkg) + { + to_remove.extend(symbols.iter().cloned()); + } + } + for symbol in to_remove { + if let Some(s) = self.get_symbols().get_symbol(symbol) { + files.insert(s.get_range().0.filename); + } + } + for file in files { + self.sema_db.file_sema_map.remove(&file); + } } } diff --git a/kclvm/sema/src/core/package.rs b/kclvm/sema/src/core/package.rs index 3854fa9d4..a8488767c 100644 --- a/kclvm/sema/src/core/package.rs +++ b/kclvm/sema/src/core/package.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use indexmap::{IndexMap, IndexSet}; #[derive(Default, Debug, Clone)] @@ -39,6 +41,12 @@ impl PackageDB { pub fn get_module_info(&self, name: &str) -> Option<&ModuleInfo> { self.module_info.get(name) } + + pub fn clear_cache(&mut self, invalidate_pkgs: &HashSet) { + for invalidate_pkg in invalidate_pkgs { + self.package_info.remove(invalidate_pkg); + } + } } #[derive(Debug, Clone)] pub struct PackageInfo { diff --git a/kclvm/sema/src/core/scope.rs b/kclvm/sema/src/core/scope.rs index 0d98861c3..b1baf688b 100644 --- a/kclvm/sema/src/core/scope.rs +++ b/kclvm/sema/src/core/scope.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use indexmap::{IndexMap, IndexSet}; use kclvm_error::Position; @@ -108,6 +108,17 @@ impl ScopeData { } } + pub fn remove_scope(&mut self, scope: &ScopeRef) { + match scope.get_kind() { + ScopeKind::Local => { + self.locals.remove(scope.get_id()); + } + ScopeKind::Root => { + self.roots.remove(scope.get_id()); + } + } + } + pub fn try_get_local_scope(&self, scope: &ScopeRef) -> Option<&LocalSymbolScope> { match scope.get_kind() { ScopeKind::Local => Some(self.locals.get(scope.get_id())?), @@ -180,6 +191,24 @@ impl ScopeData { kind: ScopeKind::Local, } } + + pub fn clear_cache(&mut self, invalidate_pkgs: &HashSet) { + for invalidate_pkg in invalidate_pkgs { + if let Some(scope_ref) = self.root_map.remove(invalidate_pkg) { + self.clear_scope_and_child(scope_ref); + self.roots.remove(scope_ref.get_id()); + } + } + } + + pub fn clear_scope_and_child(&mut self, scope_ref: ScopeRef) { + if let Some(scope) = self.get_scope(&scope_ref) { + for c in scope.get_children() { + self.clear_scope_and_child(c) + } + } + self.remove_scope(&scope_ref) + } } #[derive(Debug, Clone)] diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs index 37ace5323..ccd1e799f 100644 --- a/kclvm/sema/src/core/symbol.rs +++ b/kclvm/sema/src/core/symbol.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{collections::HashSet, sync::Arc}; use generational_arena::Arena; use indexmap::{IndexMap, IndexSet}; @@ -54,6 +54,7 @@ pub struct KCLSymbolSemanticInfo { } pub(crate) const BUILTIN_STR_PACKAGE: &'static str = "@str"; +pub(crate) const BUILTIN_FUNCTION_PACKAGE: &'static str = "@builtin"; #[derive(Default, Debug, Clone)] pub struct SymbolData { @@ -79,6 +80,7 @@ pub struct SymbolDB { pub(crate) schema_builtin_symbols: IndexMap>, pub(crate) node_symbol_map: IndexMap, pub(crate) symbol_node_map: IndexMap, + pub(crate) pkg_symbol_map: IndexMap>, } impl SymbolData { @@ -183,6 +185,41 @@ impl SymbolData { } } + pub fn remove_symbol(&mut self, id: &SymbolRef) { + match id.get_kind() { + SymbolKind::Schema => { + self.schemas.remove(id.get_id()); + } + SymbolKind::Attribute => { + self.attributes.remove(id.get_id()); + } + SymbolKind::Value => { + self.values.remove(id.get_id()); + } + SymbolKind::Package => { + self.packages.remove(id.get_id()); + } + SymbolKind::TypeAlias => { + self.type_aliases.remove(id.get_id()); + } + SymbolKind::Unresolved => { + self.unresolved.remove(id.get_id()); + } + SymbolKind::Rule => { + self.rules.remove(id.get_id()); + } + SymbolKind::Expression => { + self.exprs.remove(id.get_id()); + } + SymbolKind::Comment => { + self.comments.remove(id.get_id()); + } + SymbolKind::Decorator => { + self.decorators.remove(id.get_id()); + } + } + } + pub fn set_symbol_type(&mut self, id: SymbolRef, ty: TypeRef) { match id.get_kind() { SymbolKind::Schema => { @@ -498,17 +535,37 @@ impl SymbolData { } } - pub fn alloc_package_symbol(&mut self, pkg: PackageSymbol) -> SymbolRef { + pub fn insert_package_symbol(&mut self, symbol_ref: SymbolRef, pkg_name: String) { + if !self.symbols_info.pkg_symbol_map.contains_key(&pkg_name) { + self.symbols_info + .pkg_symbol_map + .insert(pkg_name.clone(), IndexSet::default()); + } + + self.symbols_info + .pkg_symbol_map + .get_mut(&pkg_name) + .unwrap() + .insert(symbol_ref); + } + + pub fn alloc_package_symbol(&mut self, pkg: PackageSymbol, pkg_name: String) -> SymbolRef { let symbol_id = self.packages.insert(pkg); let symbol_ref = SymbolRef { id: symbol_id, kind: SymbolKind::Package, }; self.packages.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } - pub fn alloc_schema_symbol(&mut self, schema: SchemaSymbol, node_key: NodeKey) -> SymbolRef { + pub fn alloc_schema_symbol( + &mut self, + schema: SchemaSymbol, + node_key: NodeKey, + pkg_name: String, + ) -> SymbolRef { self.symbols_info.symbol_pos_set.insert(schema.end.clone()); let symbol_id = self.schemas.insert(schema); let symbol_ref = SymbolRef { @@ -522,6 +579,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.schemas.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } @@ -529,6 +587,7 @@ impl SymbolData { &mut self, unresolved: UnresolvedSymbol, node_key: NodeKey, + pkg_name: String, ) -> SymbolRef { self.symbols_info .symbol_pos_set @@ -545,6 +604,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.unresolved.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } @@ -552,6 +612,7 @@ impl SymbolData { &mut self, alias: TypeAliasSymbol, node_key: NodeKey, + pkg_name: String, ) -> SymbolRef { self.symbols_info.symbol_pos_set.insert(alias.end.clone()); let symbol_id = self.type_aliases.insert(alias); @@ -566,10 +627,16 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.type_aliases.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } - pub fn alloc_rule_symbol(&mut self, rule: RuleSymbol, node_key: NodeKey) -> SymbolRef { + pub fn alloc_rule_symbol( + &mut self, + rule: RuleSymbol, + node_key: NodeKey, + pkg_name: String, + ) -> SymbolRef { self.symbols_info.symbol_pos_set.insert(rule.end.clone()); let symbol_id = self.rules.insert(rule); let symbol_ref = SymbolRef { @@ -583,6 +650,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.rules.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } @@ -590,6 +658,7 @@ impl SymbolData { &mut self, attribute: AttributeSymbol, node_key: NodeKey, + pkg_name: String, ) -> SymbolRef { self.symbols_info .symbol_pos_set @@ -606,10 +675,16 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.attributes.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } - pub fn alloc_value_symbol(&mut self, value: ValueSymbol, node_key: NodeKey) -> SymbolRef { + pub fn alloc_value_symbol( + &mut self, + value: ValueSymbol, + node_key: NodeKey, + pkg_name: String, + ) -> SymbolRef { self.symbols_info.symbol_pos_set.insert(value.end.clone()); let symbol_id = self.values.insert(value); let symbol_ref = SymbolRef { @@ -623,6 +698,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.values.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); symbol_ref } @@ -630,6 +706,7 @@ impl SymbolData { &mut self, expr: ExpressionSymbol, node_key: NodeKey, + pkg_name: String, ) -> Option { if self.symbols_info.symbol_pos_set.contains(&expr.end) { return None; @@ -647,6 +724,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.exprs.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); Some(symbol_ref) } @@ -654,6 +732,7 @@ impl SymbolData { &mut self, comment: CommentSymbol, node_key: NodeKey, + pkg_name: String, ) -> Option { let symbol_id = self.comments.insert(comment); let symbol_ref = SymbolRef { @@ -667,6 +746,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.comments.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); Some(symbol_ref) } @@ -674,6 +754,7 @@ impl SymbolData { &mut self, decorator: DecoratorSymbol, node_key: NodeKey, + pkg_name: String, ) -> Option { let symbol_id = self.decorators.insert(decorator); let symbol_ref = SymbolRef { @@ -687,6 +768,7 @@ impl SymbolData { .symbol_node_map .insert(symbol_ref, node_key); self.decorators.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + self.insert_package_symbol(symbol_ref, pkg_name); Some(symbol_ref) } @@ -709,6 +791,19 @@ impl SymbolData { pub fn get_builtin_symbols(&self) -> &IndexMap { &self.symbols_info.global_builtin_symbols } + + pub fn clear_cache(&mut self, invalidate_pkgs: &HashSet) { + let mut to_remove: Vec = Vec::new(); + + for invalidate_pkg in invalidate_pkgs { + if let Some(symbols) = self.symbols_info.pkg_symbol_map.get(invalidate_pkg) { + to_remove.extend(symbols.iter().cloned()); + } + } + for symbol in to_remove { + self.remove_symbol(&symbol); + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] diff --git a/kclvm/sema/src/namer/mod.rs b/kclvm/sema/src/namer/mod.rs index 8f2d14a1d..67143f2a3 100644 --- a/kclvm/sema/src/namer/mod.rs +++ b/kclvm/sema/src/namer/mod.rs @@ -45,7 +45,9 @@ use crate::builtin::{ }; use crate::core::global_state::GlobalState; use crate::core::package::{ModuleInfo, PackageInfo}; -use crate::core::symbol::{PackageSymbol, SymbolRef, ValueSymbol, BUILTIN_STR_PACKAGE}; +use crate::core::symbol::{ + PackageSymbol, SymbolRef, ValueSymbol, BUILTIN_FUNCTION_PACKAGE, BUILTIN_STR_PACKAGE, +}; use crate::resolver::scope::NodeKey; use indexmap::IndexSet; use kclvm_ast::ast::AstIndex; @@ -57,7 +59,7 @@ mod node; pub const BUILTIN_SYMBOL_PKG_PATH: &str = "@builtin"; pub struct Namer<'ctx> { - gs: GlobalState, + gs: &'ctx mut GlobalState, ctx: NamerContext<'ctx>, } @@ -83,7 +85,7 @@ impl<'ctx> NamerContext<'ctx> { } impl<'ctx> Namer<'ctx> { - fn new(program: &'ctx Program, gs: GlobalState) -> Self { + fn new(program: &'ctx Program, gs: &'ctx mut GlobalState) -> Self { Self { ctx: NamerContext { program, @@ -97,7 +99,7 @@ impl<'ctx> Namer<'ctx> { } // serial namer pass - pub fn find_symbols(program: &'ctx Program, gs: GlobalState) -> GlobalState { + pub fn find_symbols(program: &'ctx Program, gs: &'ctx mut GlobalState) { let mut namer = Self::new(program, gs); namer.ctx.current_package_info = Some(PackageInfo::new( BUILTIN_SYMBOL_PKG_PATH.to_string(), @@ -111,6 +113,16 @@ impl<'ctx> Namer<'ctx> { .add_package(namer.ctx.current_package_info.take().unwrap()); for (name, modules) in namer.ctx.program.pkgs.iter() { + // new pkgs or invalidate pkg + if namer.gs.get_packages().get_package_info(name).is_some() + && !namer.gs.new_or_invalidate_pkgs.contains(name) + { + continue; + } + + // add new pkgs to invalidate pkgs + namer.gs.new_or_invalidate_pkgs.insert(name.clone()); + { if modules.is_empty() { continue; @@ -131,7 +143,10 @@ impl<'ctx> Namer<'ctx> { }; let pkg_symbol = PackageSymbol::new(name.clone(), pkg_pos.clone(), pkg_pos); - let symbol_ref = namer.gs.get_symbols_mut().alloc_package_symbol(pkg_symbol); + let symbol_ref = namer + .gs + .get_symbols_mut() + .alloc_package_symbol(pkg_symbol, name.to_string()); namer.ctx.owner_symbols.push(symbol_ref); namer.ctx.current_package_info = @@ -164,7 +179,7 @@ impl<'ctx> Namer<'ctx> { namer.define_symbols(); - namer.gs + // namer.gs } fn init_builtin_symbols(&mut self) { @@ -179,10 +194,11 @@ impl<'ctx> Namer<'ctx> { ); value_symbol.sema_info.ty = Some(Arc::new(builtin_func.clone())); value_symbol.sema_info.doc = builtin_func.ty_doc(); - let symbol_ref = self - .gs - .get_symbols_mut() - .alloc_value_symbol(value_symbol, self.ctx.get_node_key(&AstIndex::default())); + let symbol_ref = self.gs.get_symbols_mut().alloc_value_symbol( + value_symbol, + self.ctx.get_node_key(&AstIndex::default()), + BUILTIN_FUNCTION_PACKAGE.to_string(), + ); self.gs .get_symbols_mut() .symbols_info @@ -192,14 +208,14 @@ impl<'ctx> Namer<'ctx> { //add system modules for system_pkg_name in STANDARD_SYSTEM_MODULES { - let package_symbol_ref = - self.gs - .get_symbols_mut() - .alloc_package_symbol(PackageSymbol::new( - system_pkg_name.to_string(), - Position::dummy_pos(), - Position::dummy_pos(), - )); + let package_symbol_ref = self.gs.get_symbols_mut().alloc_package_symbol( + PackageSymbol::new( + system_pkg_name.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + ), + system_pkg_name.to_string(), + ); for func_name in get_system_module_members(system_pkg_name) { let func_ty = get_system_member_function_ty(*system_pkg_name, func_name); let mut value_symbol = ValueSymbol::new( @@ -211,10 +227,11 @@ impl<'ctx> Namer<'ctx> { ); value_symbol.sema_info.ty = Some(func_ty.clone()); value_symbol.sema_info.doc = func_ty.ty_doc(); - let func_symbol_ref = self - .gs - .get_symbols_mut() - .alloc_value_symbol(value_symbol, self.ctx.get_node_key(&AstIndex::default())); + let func_symbol_ref = self.gs.get_symbols_mut().alloc_value_symbol( + value_symbol, + self.ctx.get_node_key(&AstIndex::default()), + system_pkg_name.to_string(), + ); self.gs .get_symbols_mut() .packages @@ -226,14 +243,14 @@ impl<'ctx> Namer<'ctx> { } //add string builtin function - let package_symbol_ref = - self.gs - .get_symbols_mut() - .alloc_package_symbol(PackageSymbol::new( - BUILTIN_STR_PACKAGE.to_string(), - Position::dummy_pos(), - Position::dummy_pos(), - )); + let package_symbol_ref = self.gs.get_symbols_mut().alloc_package_symbol( + PackageSymbol::new( + BUILTIN_STR_PACKAGE.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + ), + BUILTIN_STR_PACKAGE.to_string(), + ); for (name, builtin_func) in STRING_MEMBER_FUNCTIONS.iter() { let mut value_symbol = ValueSymbol::new( name.to_string(), @@ -244,10 +261,11 @@ impl<'ctx> Namer<'ctx> { ); value_symbol.sema_info.ty = Some(Arc::new(builtin_func.clone())); value_symbol.sema_info.doc = builtin_func.ty_doc(); - let symbol_ref = self - .gs - .get_symbols_mut() - .alloc_value_symbol(value_symbol, self.ctx.get_node_key(&AstIndex::default())); + let symbol_ref = self.gs.get_symbols_mut().alloc_value_symbol( + value_symbol, + self.ctx.get_node_key(&AstIndex::default()), + BUILTIN_STR_PACKAGE.to_string(), + ); self.gs .get_symbols_mut() .packages @@ -283,8 +301,8 @@ mod tests { ) .unwrap() .program; - let gs = GlobalState::default(); - let gs = Namer::find_symbols(&program, gs); + let mut gs = GlobalState::default(); + Namer::find_symbols(&program, &mut gs); let symbols = gs.get_symbols(); diff --git a/kclvm/sema/src/namer/node.rs b/kclvm/sema/src/namer/node.rs index ab923cef7..e07af9545 100644 --- a/kclvm/sema/src/namer/node.rs +++ b/kclvm/sema/src/namer/node.rs @@ -68,6 +68,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { let value_ref = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(value_name, start_pos, end_pos, Some(owner), true), self.ctx.get_node_key(&unification_stmt.target.id), + self.ctx + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, ); self.ctx .value_fully_qualified_name_set @@ -92,6 +97,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { owner, ), self.ctx.get_node_key(&type_alias_stmt.type_name.id), + self.ctx + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, ); Some(vec![type_alias_ref]) } @@ -117,6 +127,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { let value_ref = self.gs.get_symbols_mut().alloc_value_symbol( ValueSymbol::new(value_name, start_pos, end_pos, Some(owner), true), self.ctx.get_node_key(&target.id), + self.ctx + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, ); self.ctx .value_fully_qualified_name_set @@ -172,6 +187,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { let shcema_ref = self.gs.get_symbols_mut().alloc_schema_symbol( SchemaSymbol::new(schema_stmt.name.node.clone(), start_pos, end_pos, *owner), self.ctx.get_node_key(&schema_stmt.name.id), + self.ctx + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, ); self.ctx.owner_symbols.push(shcema_ref); @@ -214,6 +234,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { let rule_ref = self.gs.get_symbols_mut().alloc_rule_symbol( RuleSymbol::new(rule_stmt.name.node.clone(), start_pos, end_pos, owner), self.ctx.get_node_key(&rule_stmt.name.id), + self.ctx + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, ); Some(vec![rule_ref]) } @@ -234,6 +259,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { schema_attr.is_optional, ), self.ctx.get_node_key(&schema_attr.name.id), + self.ctx + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, ); Some(vec![attribute_ref]) } diff --git a/kclvm/sema/src/resolver/arg.rs b/kclvm/sema/src/resolver/arg.rs index e3c7aa0bc..9be8fbf61 100644 --- a/kclvm/sema/src/resolver/arg.rs +++ b/kclvm/sema/src/resolver/arg.rs @@ -57,6 +57,7 @@ impl<'ctx> Resolver<'ctx> { check_table.insert(arg_name.to_string()); let arg_value_type = self.expr_or_any_type(&kw.node.value); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(kw.id.clone()), arg_value_type.clone()); kwarg_types.push((arg_name.to_string(), arg_value_type.clone())); } else { diff --git a/kclvm/sema/src/resolver/mod.rs b/kclvm/sema/src/resolver/mod.rs index a49f1523b..a7f60c0dd 100644 --- a/kclvm/sema/src/resolver/mod.rs +++ b/kclvm/sema/src/resolver/mod.rs @@ -43,7 +43,7 @@ pub struct Resolver<'ctx> { pub scope_map: IndexMap>>, pub scope: Rc>, pub scope_level: usize, - pub node_ty_map: NodeTyMap, + pub node_ty_map: Rc>, pub builtin_scope: Rc>, pub ctx: Context, pub options: Options, @@ -61,7 +61,7 @@ impl<'ctx> Resolver<'ctx> { builtin_scope, scope, scope_level: 0, - node_ty_map: IndexMap::default(), + node_ty_map: Rc::new(RefCell::new(IndexMap::default())), ctx: Context::default(), options, handler: Handler::default(), @@ -181,11 +181,15 @@ pub fn resolve_program_with_opts( resolver.resolve_import(); if let Some(cached_scope) = cached_scope.as_ref() { if let Ok(mut cached_scope) = cached_scope.try_lock() { + cached_scope.invalidate_pkgs.clear(); cached_scope.update(program); resolver.scope_map = cached_scope.scope_map.clone(); resolver.scope_map.remove(kclvm_ast::MAIN_PKG); resolver.node_ty_map = cached_scope.node_ty_map.clone(); resolver.ctx.schema_mapping = cached_scope.schema_mapping.clone(); + cached_scope + .invalidate_pkgs + .insert(kclvm_ast::MAIN_PKG.to_string()); } } let scope = resolver.check_and_lint(kclvm_ast::MAIN_PKG); @@ -196,9 +200,11 @@ pub fn resolve_program_with_opts( cached_scope.node_ty_map = scope.node_ty_map.clone(); cached_scope.scope_map.remove(kclvm_ast::MAIN_PKG); cached_scope.schema_mapping = resolver.ctx.schema_mapping; + cached_scope + .invalidate_pkgs + .insert(kclvm_ast::MAIN_PKG.to_string()); } } - if opts.type_erasure { let type_alias_mapping = resolver.ctx.type_alias_mapping.clone(); // Erase all the function type to a named type "function" diff --git a/kclvm/sema/src/resolver/node.rs b/kclvm/sema/src/resolver/node.rs index 1e9d4cfa7..7f9ba1801 100644 --- a/kclvm/sema/src/resolver/node.rs +++ b/kclvm/sema/src/resolver/node.rs @@ -119,7 +119,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { doc: None, }, ); - self.node_ty_map.insert( + self.node_ty_map.borrow_mut().insert( self.get_node_key(type_alias_stmt.type_name.id.clone()), ty.clone(), ); @@ -191,7 +191,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { expected_ty.clone(), &assign_stmt.value.get_span_pos(), ); - self.node_ty_map.insert( + self.node_ty_map.borrow_mut().insert( self.get_node_key(assign_stmt.value.id.clone()), upgrade_schema_type.clone(), ); @@ -226,7 +226,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { expected_ty.clone(), &assign_stmt.value.get_span_pos(), ); - self.node_ty_map.insert( + self.node_ty_map.borrow_mut().insert( self.get_node_key(assign_stmt.value.id.clone()), upgrade_schema_type.clone(), ); @@ -402,7 +402,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { .get_type_of_attr(name) .map_or(self.any_ty(), |ty| ty); - self.node_ty_map.insert( + self.node_ty_map.borrow_mut().insert( self.get_node_key(schema_attr.name.id.clone()), expected_ty.clone(), ); @@ -534,7 +534,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { ); } - self.node_ty_map.insert( + self.node_ty_map.borrow_mut().insert( self.get_node_key(selector_expr.attr.id.clone()), value_ty.clone(), ); @@ -546,6 +546,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { selector_expr.attr.get_span_pos(), ); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), value_ty.clone()); } @@ -973,7 +974,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { ); let init_stack_depth = self.switch_config_expr_context(Some(obj)); self.expr(&schema_expr.config); - self.node_ty_map.insert( + self.node_ty_map.borrow_mut().insert( self.get_node_key(schema_expr.config.id.clone()), def_ty.clone(), ); @@ -1061,6 +1062,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { }; if let Some(name) = arg.node.names.last() { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), ty.clone()); } @@ -1137,6 +1139,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { let ty = self.parse_ty_with_scope(ty, arg.get_span_pos()); if let Some(name) = arg.node.names.last() { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), ty.clone()); } let value = &arguments.defaults[i]; @@ -1175,6 +1178,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { ); for (index, name) in identifier.names.iter().enumerate() { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), tys[index].clone()); } tys.last().unwrap().clone() @@ -1287,9 +1291,11 @@ impl<'ctx> Resolver<'ctx> { let upgrade_ty = self.upgrade_dict_to_schema(ty.clone(), expected_ty, &expr.get_span_pos()); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(expr.id.clone()), upgrade_ty); } else { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(expr.id.clone()), ty.clone()); } @@ -1303,6 +1309,7 @@ impl<'ctx> Resolver<'ctx> { self.ctx.end_pos = end; let ty = self.walk_stmt(&stmt.node); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(stmt.id.clone()), ty.clone()); ty } @@ -1316,6 +1323,7 @@ impl<'ctx> Resolver<'ctx> { Some(expr) => { let ty = self.walk_expr(&expr.node); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(expr.id.clone()), ty.clone()); ty } @@ -1335,10 +1343,12 @@ impl<'ctx> Resolver<'ctx> { ); for (index, name) in identifier.node.names.iter().enumerate() { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), tys[index].clone()); } let ident_ty = tys.last().unwrap().clone(); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(identifier.id.clone()), ident_ty.clone()); ident_ty diff --git a/kclvm/sema/src/resolver/schema.rs b/kclvm/sema/src/resolver/schema.rs index 01691c904..4b42df4f7 100644 --- a/kclvm/sema/src/resolver/schema.rs +++ b/kclvm/sema/src/resolver/schema.rs @@ -24,6 +24,7 @@ impl<'ctx> Resolver<'ctx> { let ty = self.lookup_type_from_scope(&schema_stmt.name.node, schema_stmt.name.get_span_pos()); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(schema_stmt.name.id.clone()), ty.clone()); let scope_ty = if ty.is_schema() { ty.into_schema_type() @@ -47,6 +48,7 @@ impl<'ctx> Resolver<'ctx> { let ty = self.parse_ty_with_scope(ty, arg.get_span_pos()); if let Some(name) = arg.node.names.last() { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), ty.clone()); } } @@ -136,6 +138,7 @@ impl<'ctx> Resolver<'ctx> { self.resolve_unique_key(&rule_stmt.name.node, &rule_stmt.name.get_span_pos()); let ty = self.lookup_type_from_scope(&rule_stmt.name.node, rule_stmt.name.get_span_pos()); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(rule_stmt.name.id.clone()), ty.clone()); let scope_ty = if ty.is_schema() { ty.into_schema_type() diff --git a/kclvm/sema/src/resolver/scope.rs b/kclvm/sema/src/resolver/scope.rs index e543af75a..e2ad853d8 100644 --- a/kclvm/sema/src/resolver/scope.rs +++ b/kclvm/sema/src/resolver/scope.rs @@ -286,7 +286,7 @@ pub struct ProgramScope { pub scope_map: IndexMap>>, pub import_names: IndexMap>, pub schema_mapping: IndexMap>>, - pub node_ty_map: NodeTyMap, + pub node_ty_map: Rc>, pub handler: Handler, } @@ -460,6 +460,7 @@ impl<'ctx> Resolver<'ctx> { let mut obj = obj.borrow_mut(); let infer_ty = self.ctx.ty_ctx.infer_to_variable_type(ty); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(node.id.clone()), infer_ty.clone()); obj.ty = infer_ty; } @@ -511,7 +512,8 @@ pub struct CachedScope { pub program_root: String, pub scope_map: IndexMap>>, pub schema_mapping: IndexMap>>, - pub node_ty_map: NodeTyMap, + pub node_ty_map: Rc>, + pub invalidate_pkgs: HashSet, dependency_graph: DependencyGraph, } @@ -674,6 +676,7 @@ impl CachedScope { program_root: program.root.to_string(), scope_map: scope.scope_map.clone(), node_ty_map: scope.node_ty_map.clone(), + invalidate_pkgs: HashSet::default(), dependency_graph: DependencyGraph::default(), schema_mapping: scope.schema_mapping.clone(), }; @@ -684,8 +687,9 @@ impl CachedScope { pub fn clear(&mut self) { self.scope_map.clear(); - self.node_ty_map.clear(); + self.node_ty_map.borrow_mut().clear(); self.dependency_graph.clear(); + self.invalidate_pkgs.clear(); } pub fn invalidate_cache(&mut self, invalidated_pkgs: Result<&HashSet, &String>) { @@ -694,6 +698,7 @@ impl CachedScope { for invalidated_pkg in invalidated_pkgs.iter() { self.scope_map.remove(invalidated_pkg); } + self.invalidate_pkgs = invalidated_pkgs.clone(); } Err(_) => self.clear(), } diff --git a/kclvm/sema/src/resolver/ty.rs b/kclvm/sema/src/resolver/ty.rs index 2971ed5a5..b8e338f24 100644 --- a/kclvm/sema/src/resolver/ty.rs +++ b/kclvm/sema/src/resolver/ty.rs @@ -76,6 +76,7 @@ impl<'ctx> Resolver<'ctx> { ); if let Some(ty) = ty_node { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(ty.id.clone()), ret_ty.clone()); }; ret_ty @@ -451,10 +452,12 @@ impl<'ctx> Resolver<'ctx> { if let ast::Type::Named(identifier) = &ty_node.node { for (index, name) in identifier.names.iter().enumerate() { self.node_ty_map + .borrow_mut() .insert(self.get_node_key(name.id.clone()), tys[index].clone()); } let ident_ty = tys.last().unwrap().clone(); self.node_ty_map + .borrow_mut() .insert(self.get_node_key(ty_node.id.clone()), ident_ty.clone()); } }; diff --git a/kclvm/tools/src/LSP/src/find_refs.rs b/kclvm/tools/src/LSP/src/find_refs.rs index f62a29344..37ed99ea6 100644 --- a/kclvm/tools/src/LSP/src/find_refs.rs +++ b/kclvm/tools/src/LSP/src/find_refs.rs @@ -9,9 +9,7 @@ use crate::state::{KCLEntryCache, KCLVfs, KCLWordIndexMap}; use anyhow::Result; use kclvm_driver::toolchain; use kclvm_error::Position as KCLPos; -use kclvm_parser::KCLModuleCache; use kclvm_sema::core::global_state::GlobalState; -use kclvm_sema::resolver::scope::KCLScopeCache; use lsp_types::Location; use parking_lot::lock_api::RwLock; @@ -24,8 +22,6 @@ pub(crate) fn find_refs Result<(), anyhow::Error>>( vfs: Option, logger: F, gs: &GlobalState, - module_cache: Option, - scope_cache: Option, entry_cache: Option, ) -> Result, String> { let def = find_def(kcl_pos, gs, true); @@ -43,8 +39,6 @@ pub(crate) fn find_refs Result<(), anyhow::Error>>( include_declaration, Some(FIND_REFS_LIMIT), logger, - module_cache, - scope_cache, entry_cache, )) } else { @@ -69,8 +63,6 @@ pub(crate) fn find_refs_from_def Result<(), anyhow::Error>>( include_declaration: bool, limit: Option, logger: F, - module_cache: Option, - scope_cache: Option, entry_cache: Option, ) -> Vec { let mut ref_locations = vec![]; @@ -94,9 +86,10 @@ pub(crate) fn find_refs_from_def Result<(), anyhow::Error>>( Ok(file_path) => { match compile_with_params(Params { file: file_path.clone(), - module_cache: module_cache.clone(), - scope_cache: scope_cache.clone(), + module_cache: None, + scope_cache: None, vfs: vfs.clone(), + gs_cache: None, entry_cache: entry_cache.clone(), tool: Arc::new(RwLock::new(toolchain::default())), }) @@ -222,8 +215,6 @@ mod tests { Some(20), logger, None, - None, - None, ), ); } @@ -280,8 +271,6 @@ mod tests { Some(20), logger, None, - None, - None, ), ); } @@ -338,8 +327,6 @@ mod tests { Some(20), logger, None, - None, - None, ), ); } @@ -389,8 +376,6 @@ mod tests { Some(20), logger, None, - None, - None, ), ); } diff --git a/kclvm/tools/src/LSP/src/quick_fix.rs b/kclvm/tools/src/LSP/src/quick_fix.rs index 00c8f050c..c0ae2ddd8 100644 --- a/kclvm/tools/src/LSP/src/quick_fix.rs +++ b/kclvm/tools/src/LSP/src/quick_fix.rs @@ -190,6 +190,7 @@ mod tests { vfs: Some(KCLVfs::default()), entry_cache: None, tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: None, }) .0; diff --git a/kclvm/tools/src/LSP/src/rename.rs b/kclvm/tools/src/LSP/src/rename.rs index ff08e6a08..31ea7f02a 100644 --- a/kclvm/tools/src/LSP/src/rename.rs +++ b/kclvm/tools/src/LSP/src/rename.rs @@ -189,12 +189,12 @@ where None, ); - let gs = GlobalState::default(); - let gs = Namer::find_symbols(&program, gs); - let node_ty_map = prog_scope.node_ty_map.clone(); - let global_state = AdvancedResolver::resolve_program(&program, gs, node_ty_map)?; + let mut gs = GlobalState::default(); + Namer::find_symbols(&program, &mut gs); + let node_ty_map = prog_scope.node_ty_map; + AdvancedResolver::resolve_program(&program, &mut gs, node_ty_map)?; - Ok((program, global_state)) + Ok((program, gs)) } fn apply_rename_changes( diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index d911cfc70..48bfb3fb0 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -273,8 +273,6 @@ 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 entry_cache = snapshot.entry_cache.clone(); match find_refs( &pos, @@ -283,8 +281,6 @@ pub(crate) fn handle_reference( Some(snapshot.vfs.clone()), log, &db.gs, - Some(module_cache), - None, Some(entry_cache), ) { core::result::Result::Ok(locations) => Ok(Some(locations)), @@ -410,8 +406,6 @@ pub(crate) fn handle_rename( Some(snapshot.vfs.clone()), log, &db.gs, - Some(snapshot.module_cache), - Some(snapshot.scope_cache), Some(snapshot.entry_cache), ); match references { diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index b7e257eef..af671e2ab 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -8,6 +8,7 @@ use crossbeam_channel::{select, unbounded, Receiver, Sender}; use kclvm_driver::toolchain::{self, Toolchain}; use kclvm_driver::CompileUnitOptions; use kclvm_parser::KCLModuleCache; +use kclvm_sema::core::global_state::GlobalState; use kclvm_sema::resolver::scope::KCLScopeCache; use lsp_server::{ReqQueue, Request, Response}; use lsp_types::Url; @@ -18,6 +19,7 @@ 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}; @@ -49,6 +51,7 @@ pub(crate) type KCLVfs = Arc>; pub(crate) type KCLWordIndexMap = Arc>>>>; pub(crate) type KCLEntryCache = Arc>>; pub(crate) type KCLToolChain = Arc>; +pub(crate) type KCLGlobalStateCache = Arc>; /// State for the language server pub(crate) struct LanguageServerState { @@ -82,6 +85,8 @@ pub(crate) struct LanguageServerState { pub entry_cache: KCLEntryCache, /// Toolchain is used to provider KCL tool features for the language server. pub tool: KCLToolChain, + /// KCL globalstate cache + pub gs_cache: KCLGlobalStateCache, } /// A snapshot of the state of the language server @@ -134,6 +139,7 @@ impl LanguageServerState { scope_cache: KCLScopeCache::default(), entry_cache: KCLEntryCache::default(), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: KCLGlobalStateCache::default(), }; let word_index_map = state.word_index_map.clone(); @@ -223,6 +229,7 @@ impl LanguageServerState { let scope_cache = Arc::clone(&self.scope_cache); let entry = Arc::clone(&self.entry_cache); let tool = Arc::clone(&self.tool); + let gs_cache = Arc::clone(&self.gs_cache); move || match url(&snapshot, file.file_id) { Ok(uri) => { let version = @@ -235,6 +242,7 @@ impl LanguageServerState { vfs: Some(snapshot.vfs), entry_cache: Some(entry), tool, + gs_cache: Some(gs_cache), }); let current_version = diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index 7f4ba0cd8..31f37cd5c 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -77,6 +77,7 @@ use crate::goto_def::goto_def; use crate::hover::hover; use crate::main_loop::main_loop; use crate::state::KCLEntryCache; +use crate::state::KCLGlobalStateCache; use crate::state::KCLVfs; use crate::to_lsp::kcl_diag_to_lsp_diags; use crate::util::lookup_compile_unit_with_cache; @@ -134,6 +135,7 @@ pub(crate) fn compile_test_file( vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }); let (program, gs) = compile_res.unwrap(); (file, program, diags, gs) @@ -297,6 +299,7 @@ fn diagnostics_test() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .0; @@ -485,6 +488,7 @@ fn complete_import_external_file_test() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .1 .unwrap(); @@ -546,6 +550,7 @@ fn goto_import_external_file_test() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }); let gs = compile_res.unwrap().1; @@ -1401,6 +1406,7 @@ fn konfig_goto_def_test_base() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .1 .unwrap(); @@ -1495,6 +1501,7 @@ fn konfig_goto_def_test_main() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .1 .unwrap(); @@ -1561,6 +1568,7 @@ fn konfig_completion_test_main() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .1 .unwrap(); @@ -1676,6 +1684,7 @@ fn konfig_hover_test_main() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .1 .unwrap(); @@ -2111,6 +2120,7 @@ fn compile_unit_test() { vfs: Some(KCLVfs::default()), entry_cache: Some(KCLEntryCache::default()), tool: Arc::new(RwLock::new(toolchain::default())), + gs_cache: Some(KCLGlobalStateCache::default()), }) .1 .unwrap() diff --git a/kclvm/tools/src/LSP/src/util.rs b/kclvm/tools/src/LSP/src/util.rs index aab9c7661..fd63b9403 100644 --- a/kclvm/tools/src/LSP/src/util.rs +++ b/kclvm/tools/src/LSP/src/util.rs @@ -19,12 +19,14 @@ use kclvm_sema::resolver::resolve_program_with_opts; use kclvm_sema::resolver::scope::KCLScopeCache; use crate::from_lsp; -use crate::state::{KCLEntryCache, KCLToolChain, KCLVfs}; +use crate::state::{KCLEntryCache, KCLToolChain}; +use crate::state::{KCLGlobalStateCache, KCLVfs}; use lsp_types::Url; use parking_lot::RwLockReadGuard; use ra_ap_vfs::{FileId, Vfs}; use serde::{de::DeserializeOwned, Serialize}; +use std::collections::HashSet; use std::fs; use std::path::Path; @@ -66,6 +68,7 @@ pub(crate) struct Params { pub entry_cache: Option, pub vfs: Option, pub tool: KCLToolChain, + pub gs_cache: Option, } pub(crate) fn lookup_compile_unit_with_cache( @@ -125,6 +128,7 @@ pub(crate) fn compile_with_params( Err(e) => return (diags, Err(anyhow::anyhow!("Parse failed: {:?}", e))), }; diags.extend(sess.1.borrow().diagnostics.clone()); + // Resolver let prog_scope = resolve_program_with_opts( &mut program, @@ -133,15 +137,37 @@ pub(crate) fn compile_with_params( type_erasure: false, ..Default::default() }, - params.scope_cache, + params.scope_cache.clone(), ); diags.extend(prog_scope.handler.diagnostics); - // Please note that there is no global state cache at this stage. - let gs = GlobalState::default(); - let gs = Namer::find_symbols(&program, gs); - match AdvancedResolver::resolve_program(&program, gs, prog_scope.node_ty_map.clone()) { - Ok(gs) => (diags, Ok((program, gs))), + let mut default = GlobalState::default(); + let mut gs_ref; + + let mut gs = match ¶ms.gs_cache { + Some(cache) => match cache.try_lock() { + Ok(locked_state) => { + gs_ref = locked_state; + &mut gs_ref + } + Err(_) => &mut default, + }, + None => &mut default, + }; + + gs.new_or_invalidate_pkgs = match ¶ms.scope_cache { + Some(cache) => match cache.try_lock() { + Ok(scope) => scope.invalidate_pkgs.clone(), + Err(_) => HashSet::new(), + }, + None => HashSet::new(), + }; + gs.clear_cache(); + + Namer::find_symbols(&program, &mut gs); + + match AdvancedResolver::resolve_program(&program, gs, prog_scope.node_ty_map) { + Ok(_) => (diags, Ok((program, gs.clone()))), Err(e) => (diags, Err(anyhow::anyhow!("Resolve failed: {:?}", e))), } }