diff --git a/kclvm/api/src/service/service_impl.rs b/kclvm/api/src/service/service_impl.rs index cce3184e5..681088c16 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 @@ -351,7 +351,7 @@ impl KclvmServiceImpl { /// /// let serv = KclvmServiceImpl::default(); /// let args = &ListVariablesArgs { - /// file: Path::new(".").join("src").join("testdata").join("variables").join("main.k").canonicalize().unwrap().display().to_string(), + /// files: vec![Path::new(".").join("src").join("testdata").join("variables").join("main.k").canonicalize().unwrap().display().to_string()], /// specs: vec!["a".to_string()] /// }; /// let result = serv.list_variables(args).unwrap(); @@ -359,10 +359,10 @@ impl KclvmServiceImpl { /// assert_eq!(result.variables.get("a").unwrap().value, "1"); /// ``` pub fn list_variables(&self, args: &ListVariablesArgs) -> anyhow::Result { - let k_file = args.file.to_string(); + let k_files = args.files.clone(); let specs = args.specs.clone(); - let select_res = list_variables(k_file, specs)?; + let select_res = list_variables(k_files, specs)?; let variables: HashMap = select_res .variables diff --git a/kclvm/api/src/testdata/list-variables.json b/kclvm/api/src/testdata/list-variables.json index b03e74c3e..db27f88b9 100644 --- a/kclvm/api/src/testdata/list-variables.json +++ b/kclvm/api/src/testdata/list-variables.json @@ -1,4 +1,4 @@ { - "file": "./src/testdata/variables/main.k", + "files": ["./src/testdata/variables/main.k"], "specs": ["a", "b", "c"] } diff --git a/kclvm/api/src/testdata/rename/main.k b/kclvm/api/src/testdata/rename/main.k new file mode 100644 index 000000000..e69de29bb 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/query/src/selector.rs b/kclvm/query/src/selector.rs index 01627bcd4..0096d61cb 100644 --- a/kclvm/query/src/selector.rs +++ b/kclvm/query/src/selector.rs @@ -2,21 +2,22 @@ use super::util::{invalid_symbol_selector_spec_error, split_field_path}; use anyhow::Result; use kclvm_ast::ast; use kclvm_error::diagnostic::Errors; +use kclvm_parser::ParseSession; use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, VecDeque}; +use std::{ + collections::{HashMap, VecDeque}, + sync::Arc, +}; use kclvm_ast::path::get_key_path; use kclvm_ast::walker::MutSelfWalker; use kclvm_ast_pretty::{print_ast_node, ASTNode}; -use kclvm_parser::parse_file; +use kclvm_parser::load_program; -use kclvm_sema::resolver::Options; - -use kclvm_ast::MAIN_PKG; use kclvm_sema::pre_process::pre_process_program; -use maplit::hashmap; +use kclvm_sema::resolver::Options; #[derive(Debug, Default)] /// UnsupportedSelectee is used to store the unsupported selectee, such as if, for, etc. pub struct UnsupportedSelectee { @@ -461,26 +462,29 @@ impl Variable { /// list_options provides users with the ability to parse kcl program and get all option /// calling information. -pub fn list_variables(file: String, specs: Vec) -> Result { +pub fn list_variables(files: Vec, specs: Vec) -> Result { let mut selector = Selector::new(specs)?; - let parse_result = parse_file(&file, None)?; + let mut load_result = load_program( + Arc::new(ParseSession::default()), + &files.iter().map(AsRef::as_ref).collect::>(), + None, + None, + )?; let mut opts = Options::default(); opts.merge_program = true; - pre_process_program( - &mut ast::Program { - root: file, - pkgs: hashmap! { MAIN_PKG.to_string() => vec![parse_result.module.clone()] }, - }, - &opts, - ); + pre_process_program(&mut load_result.program, &opts); - selector.walk_module(&parse_result.module); + for (_, modules) in load_result.program.pkgs.iter() { + for module in modules.iter() { + selector.walk_module(&module); + } + } Ok(ListVariablesResult { variables: selector.select_result, unsupported: selector.unsupported, - parse_errors: parse_result.errors, + parse_errors: load_result.errors, }) } diff --git a/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/kcl.mod b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/kcl.mod new file mode 100644 index 000000000..f893ac172 --- /dev/null +++ b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_list_merged_variables" +edition = "v0.9.0" +version = "0.0.1" + diff --git a/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/override/base.k b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/override/base.k new file mode 100644 index 000000000..cc4c5914b --- /dev/null +++ b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/override/base.k @@ -0,0 +1,11 @@ + +import test + +_tests = test.Test { + pots: [ + test.Pot { + name: "http" + number: 90 + } + ] +} \ No newline at end of file diff --git a/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/override/main.k b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/override/main.k new file mode 100644 index 000000000..074e18a18 --- /dev/null +++ b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/override/main.k @@ -0,0 +1,6 @@ + +import test + +_tests = test.Test { + aType: "Internet" +} diff --git a/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/test.k b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/test.k new file mode 100644 index 000000000..a484f7f47 --- /dev/null +++ b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/test.k @@ -0,0 +1,7 @@ +schema Pot: + name: str + number: int + +schema Test: + aType?: str + pots?: [Pot] diff --git a/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/union/base.k b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/union/base.k new file mode 100644 index 000000000..6f908c51e --- /dev/null +++ b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/union/base.k @@ -0,0 +1,11 @@ + +import test + +tests = test.Test { + pots: [ + test.Pot { + name: "http" + number: 90 + } + ] +} \ No newline at end of file diff --git a/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/union/main.k b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/union/main.k new file mode 100644 index 000000000..2c7f7aa3b --- /dev/null +++ b/kclvm/query/src/test_data/test_list_variables/test_list_merged_variables/union/main.k @@ -0,0 +1,6 @@ + +import test + +tests : test.Test { + aType: "Internet" +} diff --git a/kclvm/query/src/tests.rs b/kclvm/query/src/tests.rs index 0aaf84c29..28b905136 100644 --- a/kclvm/query/src/tests.rs +++ b/kclvm/query/src/tests.rs @@ -381,7 +381,7 @@ fn test_list_variables() { for (spec, expected, expected_name, op_sym) in test_cases { let specs = vec![spec.to_string()]; - let result = list_variables(file.clone(), specs).unwrap(); + let result = list_variables(vec![file.clone()], specs).unwrap(); assert_eq!(result.variables.get(spec).unwrap().value, expected); assert_eq!(result.variables.get(spec).unwrap().type_name, expected_name); assert_eq!(result.variables.get(spec).unwrap().op_sym, op_sym); @@ -470,7 +470,7 @@ fn test_list_all_variables() { ]; for (spec, expected, expected_name, op_sym) in test_cases { - let result = list_variables(file.clone(), vec![]).unwrap(); + let result = list_variables(vec![file.clone()], vec![]).unwrap(); assert_eq!(result.variables.get(spec).unwrap().value, expected); assert_eq!(result.variables.get(spec).unwrap().type_name, expected_name); assert_eq!(result.variables.get(spec).unwrap().op_sym, op_sym); @@ -521,7 +521,7 @@ fn test_list_unsupported_variables() { for (spec, expected_code) in test_cases { let specs = vec![spec.to_string()]; - let result = list_variables(file.clone(), specs).unwrap(); + let result = list_variables(vec![file.clone()], specs).unwrap(); assert_eq!(result.variables.get(spec), None); assert_eq!(result.unsupported[0].code, expected_code); assert_eq!(result.parse_errors.len(), 0); @@ -545,7 +545,7 @@ fn test_list_unsupported_variables() { for (spec, expected_code) in test_cases { let specs = vec![spec.to_string()]; - let result = list_variables(file.clone(), specs).unwrap(); + let result = list_variables(vec![file.clone()], specs).unwrap(); assert_eq!(result.variables.get(spec).unwrap().value, expected_code); } } @@ -626,7 +626,7 @@ fn test_list_variable_with_invalid_kcl() { .display() .to_string(); let specs = vec!["a".to_string()]; - let result = list_variables(file.clone(), specs).unwrap(); + let result = list_variables(vec![file.clone()], specs).unwrap(); assert_eq!(result.variables.get("a"), None); assert_eq!(result.parse_errors.len(), 2); assert_eq!(result.parse_errors[0].level, Level::Error); @@ -682,7 +682,7 @@ fn test_list_variables_with_file_noexist() { .display() .to_string(); let specs = vec!["a".to_string()]; - let result = list_variables(file.clone(), specs); + let result = list_variables(vec![file.clone()], specs); assert!(result.is_err()); let err = result.err().unwrap(); assert_eq!(err.to_string(), "Cannot find the kcl file, please check the file path ./src/test_data/test_list_variables/noexist.k"); @@ -702,3 +702,58 @@ fn test_override_file_with_invalid_spec() { let err = result.err().unwrap(); assert_eq!(err.to_string(), "Invalid spec format '....', expected =filed_value>, :filed_value>, +=filed_value> or -"); } + +#[test] +fn test_list_merged_variables() { + let file = PathBuf::from("./src/test_data/test_list_variables/test_list_merged_variables") + .canonicalize() + .unwrap(); + + let test_cases = vec![ + ( + "override/base.k", + "override/main.k", + vec!["_tests.aType".to_string(), "_tests.pots".to_string()], + r#""Internet""#.to_string(), + r#"[test.Pot { + name: "http" + number: 90 +}]"# + .to_string(), + ), + ( + "union/base.k", + "union/main.k", + vec!["tests.aType".to_string(), "tests.pots".to_string()], + r#""Internet""#.to_string(), + r#"[test.Pot { + name: "http" + number: 90 +}]"# + .to_string(), + ), + ]; + + for (base_file_name, main_file_name, specs, expected_value1, expected_value2) in test_cases { + let base_file = file.join(base_file_name).display().to_string(); + let main_file = file.join(main_file_name).display().to_string(); + + let result = list_variables(vec![main_file, base_file], specs.clone()).unwrap(); + assert_eq!( + result + .variables + .get(&specs.get(0).unwrap().to_string()) + .unwrap() + .value, + expected_value1 + ); + assert_eq!( + result + .variables + .get(&specs.get(1).unwrap().to_string()) + .unwrap() + .value, + expected_value2 + ); + } +} diff --git a/kclvm/sema/src/advanced_resolver/mod.rs b/kclvm/sema/src/advanced_resolver/mod.rs index bdbcee5fe..b63dfc168 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 d7f085c11..b2fe0b086 100644 --- a/kclvm/sema/src/advanced_resolver/node.rs +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -11,8 +11,8 @@ use crate::{ core::{ scope::LocalSymbolScopeKind, symbol::{ - CommentSymbol, DecoratorSymbol, ExpressionSymbol, FunctionSymbol, - KCLSymbolSemanticInfo, SymbolRef, UnresolvedSymbol, ValueSymbol, + CommentSymbol, DecoratorSymbol, ExpressionSymbol, KCLSymbolSemanticInfo, SymbolRef, + UnresolvedSymbol, ValueSymbol, }, }, ty::{Type, TypeKind, SCHEMA_MEMBER_FUNCTIONS}, @@ -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() @@ -193,7 +197,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { false, None, )); - let mut func_value = FunctionSymbol::new( + let mut func_value = ValueSymbol::new( name.to_string(), Position::dummy_pos(), Position::dummy_pos(), @@ -201,9 +205,10 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { false, ); func_value.sema_info.ty = Some(func_ty); - let func_symbol_ref = self.gs.get_symbols_mut().alloc_function_symbol( + 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), @@ -1007,36 +1047,11 @@ impl<'ctx> AdvancedResolver<'ctx> { if maybe_def { let (start_pos, end_pos): Range = first_name.get_span_pos(); let ast_id = first_name.id.clone(); - - let ty = self - .ctx - .node_ty_map - .get(&self.ctx.get_node_key(&first_name.id)); - let first_value = match ty { - Some(ty) if matches!(ty.kind, TypeKind::Function(_)) => { - self.gs.get_symbols_mut().alloc_function_symbol( - FunctionSymbol::new( - first_name.node.clone(), - start_pos, - end_pos, - None, - false, - ), - self.ctx.get_node_key(&ast_id), - ) - } - _ => 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), - ), - }; - + 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, first_name.node.clone(), @@ -1053,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, @@ -1066,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( @@ -1081,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, @@ -1124,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, @@ -1209,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()) { @@ -1216,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, @@ -1283,8 +1304,9 @@ 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(), ); } } } -} +} \ No newline at end of file diff --git a/kclvm/sema/src/core/global_state.rs b/kclvm/sema/src/core/global_state.rs index 04458664e..6305bdd5a 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, @@ -493,6 +534,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 @@ -501,11 +544,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 { @@ -520,7 +563,7 @@ impl GlobalState { }, ); file_sema_map - .get_mut(&filename) + .get_mut(filename) .unwrap() .scopes .push(scope_ref); @@ -555,11 +598,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 a32a3e52f..265da861c 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 { @@ -80,6 +81,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 { @@ -196,6 +198,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 => { @@ -528,17 +565,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 { @@ -552,6 +609,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 } @@ -559,6 +617,7 @@ impl SymbolData { &mut self, unresolved: UnresolvedSymbol, node_key: NodeKey, + pkg_name: String, ) -> SymbolRef { self.symbols_info .symbol_pos_set @@ -575,6 +634,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 } @@ -582,6 +642,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); @@ -596,10 +657,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 { @@ -613,6 +680,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 } @@ -620,6 +688,7 @@ impl SymbolData { &mut self, attribute: AttributeSymbol, node_key: NodeKey, + pkg_name: String, ) -> SymbolRef { self.symbols_info .symbol_pos_set @@ -636,10 +705,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 { @@ -653,6 +728,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 } @@ -660,6 +736,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; @@ -677,6 +754,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) } @@ -684,6 +762,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 { @@ -697,6 +776,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) } @@ -704,6 +784,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 { @@ -717,6 +798,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) } @@ -762,6 +844,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 0cff03e42..c9978c914 100644 --- a/kclvm/sema/src/namer/mod.rs +++ b/kclvm/sema/src/namer/mod.rs @@ -45,7 +45,7 @@ use crate::builtin::{ }; use crate::core::global_state::GlobalState; use crate::core::package::{ModuleInfo, PackageInfo}; -use crate::core::symbol::{FunctionSymbol, PackageSymbol, SymbolRef, BUILTIN_STR_PACKAGE}; +use crate::core::symbol::{FunctionSymbol, PackageSymbol, SymbolRef, BUILTIN_FUNCTION_PACKAGE, BUILTIN_STR_PACKAGE}; use crate::resolver::scope::NodeKey; use indexmap::IndexSet; use kclvm_ast::ast::AstIndex; @@ -57,7 +57,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 +83,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 +97,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 +111,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 +141,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 +177,7 @@ impl<'ctx> Namer<'ctx> { namer.define_symbols(); - namer.gs + // namer.gs } fn init_builtin_symbols(&mut self) { @@ -177,12 +190,13 @@ impl<'ctx> Namer<'ctx> { None, true, ); + func_symbol.sema_info.ty = Some(Arc::new(builtin_func.clone())); func_symbol.sema_info.doc = builtin_func.ty_doc(); let symbol_ref = self .gs .get_symbols_mut() - .alloc_function_symbol(func_symbol, self.ctx.get_node_key(&AstIndex::default())); + .alloc_function_symbol(func_symbol, self.ctx.get_node_key(&AstIndex::default()), BUILTIN_FUNCTION_PACKAGE.to_string()); self.gs .get_symbols_mut() .symbols_info @@ -192,14 +206,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 func_symbol = FunctionSymbol::new( @@ -209,11 +223,13 @@ impl<'ctx> Namer<'ctx> { Some(package_symbol_ref), false, ); + func_symbol.sema_info.ty = Some(func_ty.clone()); func_symbol.sema_info.doc = func_ty.ty_doc(); let func_symbol_ref = self.gs.get_symbols_mut().alloc_function_symbol( func_symbol, self.ctx.get_node_key(&AstIndex::default()), + system_pkg_name.to_string() ); self.gs .get_symbols_mut() @@ -226,14 +242,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 func_symbol = FunctionSymbol::new( name.to_string(), @@ -242,12 +258,13 @@ impl<'ctx> Namer<'ctx> { Some(package_symbol_ref), true, ); + func_symbol.sema_info.ty = Some(Arc::new(builtin_func.clone())); func_symbol.sema_info.doc = builtin_func.ty_doc(); let symbol_ref = self .gs .get_symbols_mut() - .alloc_function_symbol(func_symbol, self.ctx.get_node_key(&AstIndex::default())); + .alloc_function_symbol(func_symbol, self.ctx.get_node_key(&AstIndex::default()), BUILTIN_STR_PACKAGE.to_string()); self.gs .get_symbols_mut() .packages @@ -283,8 +300,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/spec/gpyrpc/gpyrpc.proto b/kclvm/spec/gpyrpc/gpyrpc.proto index 4225fa926..d33e944fc 100644 --- a/kclvm/spec/gpyrpc/gpyrpc.proto +++ b/kclvm/spec/gpyrpc/gpyrpc.proto @@ -285,7 +285,7 @@ message OverrideFile_Result { } message ListVariables_Args { - string file = 1; + repeated string files = 1; repeated string specs = 2; } 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))), } }