diff --git a/kclvm/ast/src/ast.rs b/kclvm/ast/src/ast.rs index b021bff62..9dbae2924 100644 --- a/kclvm/ast/src/ast.rs +++ b/kclvm/ast/src/ast.rs @@ -413,7 +413,9 @@ impl Into for Program { pub struct Program { pub root: String, pub pkgs: HashMap>, + pub pkgs_not_imported: HashMap>, pub modules: HashMap>>, + pub modules_not_imported: HashMap>>, } impl Program { @@ -453,7 +455,11 @@ impl Program { &self, module_path: &str, ) -> anyhow::Result>> { - match self.modules.get(module_path) { + match self + .modules + .get(module_path) + .or(self.modules_not_imported.get(module_path)) + { Some(module_ref) => match module_ref.read() { Ok(m) => Ok(Some(m)), Err(_) => Err(anyhow::anyhow!("Failed to acquire module lock")), @@ -466,7 +472,11 @@ impl Program { &self, module_path: &str, ) -> anyhow::Result>> { - match self.modules.get(module_path) { + match self + .modules + .get(module_path) + .or(self.modules_not_imported.get(module_path)) + { Some(module_ref) => match module_ref.write() { Ok(m) => Ok(Some(m)), Err(_) => Err(anyhow::anyhow!("Failed to acquire module lock")), @@ -476,12 +486,19 @@ impl Program { } pub fn get_module_ref(&self, module_path: &str) -> Option>> { - self.modules.get(module_path).cloned() + self.modules + .get(module_path) + .cloned() + .or(self.modules_not_imported.get(module_path).cloned()) } pub fn get_modules_for_pkg(&self, pkg_name: &str) -> Vec>> { let mut result = Vec::new(); - if let Some(module_names) = self.pkgs.get(pkg_name) { + if let Some(module_names) = self + .pkgs + .get(pkg_name) + .or(self.pkgs_not_imported.get(pkg_name)) + { for module_name in module_names { if let Some(module) = self.get_module_ref(module_name) { result.push(module); diff --git a/kclvm/driver/src/lib.rs b/kclvm/driver/src/lib.rs index bbb4c896a..a455e4e3e 100644 --- a/kclvm/driver/src/lib.rs +++ b/kclvm/driver/src/lib.rs @@ -146,14 +146,12 @@ pub fn lookup_compile_workspaces( } } WorkSpaceKind::Folder(folder) => { - let mut load_opt = kclvm_parser::LoadProgramOptions::default(); - let metadata = - fill_pkg_maps_for_k_file(tool, path.into(), &mut load_opt).unwrap_or(None); + let load_opt = kclvm_parser::LoadProgramOptions::default(); + let metadata = None; if load_pkg { if folder.is_dir() { if let Ok(files) = get_kcl_files(folder.clone(), false) { - // return (files, Some(load_opt), metadata); workspaces.insert(workspace, (files, Some(load_opt), metadata)); return (workspaces, None); } diff --git a/kclvm/parser/src/lib.rs b/kclvm/parser/src/lib.rs index d4cdb7c8d..04c707bae 100644 --- a/kclvm/parser/src/lib.rs +++ b/kclvm/parser/src/lib.rs @@ -926,7 +926,10 @@ pub fn parse_program( opts: &LoadProgramOptions, ) -> Result { let compile_entries = get_compile_entries_from_paths(&paths, &opts)?; - let workdir = compile_entries.get_root_path().to_string(); + let workdir = compile_entries + .get_root_path() + .to_string() + .adjust_canonicalization(); let mut pkgs: HashMap> = HashMap::new(); let mut new_files = HashSet::new(); for entry in compile_entries.iter() { @@ -1004,11 +1007,12 @@ pub fn parse_program( } } } - let program = ast::Program { root: workdir, pkgs, + pkgs_not_imported: HashMap::new(), modules, + modules_not_imported: HashMap::new(), }; Ok(LoadProgramResult { @@ -1038,9 +1042,13 @@ pub fn load_all_files_under_paths( &loader.opts, ) { Ok(res) => { + let diag = sess.1.read().diagnostics.clone(); let mut res = res.clone(); let k_files_from_import = res.paths.clone(); - let (k_files_under_path, pkgmap) = get_files_from_path(paths, opts)?; + let mut paths = paths.to_vec(); + paths.push(&res.program.root); + let (k_files_under_path, pkgmap) = + get_files_from_path(&res.program.root, &paths, opts)?; loader.pkgmap.extend(pkgmap); // Filter unparsed file @@ -1054,33 +1062,69 @@ pub fn load_all_files_under_paths( } } - let module_cache = module_cache.unwrap_or_default(); - let pkgs = &mut res.program.pkgs; + let module_cache = loader.module_cache.clone(); + let pkgs_not_imported = &mut res.program.pkgs_not_imported; let mut new_files = HashSet::new(); - // Bfs unparsed and import files + loader.parsed_file.extend(unparsed_file.clone()); while let Some(file) = unparsed_file.pop_front() { new_files.insert(file.clone()); - let deps = parse_file( - sess.clone(), - file, - None, - module_cache.clone(), - pkgs, - &mut loader.pkgmap, - loader.file_graph.clone(), - &loader.opts, - )?; - for dep in deps { - if loader.parsed_file.insert(dep.clone()) { - unparsed_file.push_back(dep.clone()); - } + let module_cache_read = module_cache.read(); + match &module_cache_read { + Ok(m_cache) => match m_cache.ast_cache.get(file.get_path()) { + Some(_) => continue, + None => { + drop(module_cache_read); + let deps = parse_file( + sess.clone(), + file.clone(), + None, + module_cache.clone(), + pkgs_not_imported, + &mut loader.pkgmap, + loader.file_graph.clone(), + &loader.opts, + )?; + + let m_ref = match module_cache.read() { + Ok(module_cache) => module_cache + .ast_cache + .get(file.get_path()) + .expect(&format!( + "Module not found in module: {:?}", + file.get_path() + )) + .clone(), + Err(e) => { + return Err(anyhow::anyhow!("Parse program failed: {e}")) + } + }; + + let pkg = loader.pkgmap.get(&file).expect("file not in pkgmap"); + let mut m = m_ref.write().unwrap(); + fix_rel_import_path_with_file( + &pkg.pkg_root, + &mut m, + &file, + &loader.pkgmap, + &loader.opts, + sess.clone(), + ); + + for dep in deps { + if loader.parsed_file.insert(dep.clone()) { + unparsed_file.push_back(dep.clone()); + } + } + } + }, + Err(e) => return Err(anyhow::anyhow!("Parse entry failed: {e}")), } } // Merge unparsed module into res - let modules = &mut res.program.modules; + let modules_not_imported = &mut res.program.modules_not_imported; for file in &new_files { let filename = file.get_path().to_str().unwrap().to_string(); let m_ref = match module_cache.read() { @@ -1094,52 +1138,17 @@ pub fn load_all_files_under_paths( .clone(), Err(e) => return Err(anyhow::anyhow!("Parse program failed: {e}")), }; - modules.insert(filename.clone(), m_ref); - match pkgs.get_mut(&file.pkg_path) { + modules_not_imported.insert(filename.clone(), m_ref); + match pkgs_not_imported.get_mut(&file.pkg_path) { Some(pkg_modules) => { pkg_modules.push(filename.clone()); } None => { - pkgs.insert(file.pkg_path.clone(), vec![filename]); + pkgs_not_imported.insert(file.pkg_path.clone(), vec![filename]); } } } - - // Generate new paths - let files = match loader.file_graph.read() { - Ok(file_graph) => { - let files = match file_graph.toposort() { - Ok(files) => files, - Err(_) => file_graph.paths(), - }; - - let file_path_graph = file_graph.file_path_graph().0; - if let Err(cycle) = toposort(&file_path_graph) { - let formatted_cycle = cycle - .iter() - .map(|file| format!("- {}\n", file.to_string_lossy())) - .collect::(); - - sess.1.write().add_error( - ErrorKind::RecursiveLoad, - &[Message { - range: (Position::dummy_pos(), Position::dummy_pos()), - style: Style::Line, - message: format!( - "Could not compiles due to cyclic import statements\n{}", - formatted_cycle.trim_end() - ), - note: None, - suggested_replacement: None, - }], - ); - } - files - } - Err(e) => return Err(anyhow::anyhow!("Parse program failed: {e}")), - }; - - res.paths = files.iter().map(|file| file.get_path().clone()).collect(); + sess.1.write().diagnostics = diag; return Ok(res); } e => return e, @@ -1149,6 +1158,7 @@ pub fn load_all_files_under_paths( /// Get all kcl files under path and dependencies from opts, regardless of whether they are imported or not pub fn get_files_from_path( + root: &str, paths: &[&str], opts: Option, ) -> Result<(HashMap>, HashMap)> { @@ -1175,11 +1185,15 @@ pub fn get_files_from_path( .to_str() .unwrap() .to_string(); - let fix_path = fix_path + let mut fix_path = fix_path .replace(['/', '\\'], ".") .trim_end_matches('.') .to_string(); + if fix_path.is_empty() { + fix_path = MAIN_PKG.to_string(); + } + let pkgfile = PkgFile::new(p.clone(), fix_path.clone()); pkgmap.insert( pkgfile, @@ -1203,12 +1217,11 @@ pub fn get_files_from_path( if path_buf.is_dir() { let all_k_files_under_path = get_kcl_files(path, true)?; for f in &all_k_files_under_path { - let p = PathBuf::from(f); - + let p = PathBuf::from(f.adjust_canonicalization()); let fix_path = p .parent() .unwrap() - .strip_prefix(path_buf.clone()) + .strip_prefix(root) .unwrap() .to_str() .unwrap() diff --git a/kclvm/parser/src/tests.rs b/kclvm/parser/src/tests.rs index bcbe17b05..b09c17829 100644 --- a/kclvm/parser/src/tests.rs +++ b/kclvm/parser/src/tests.rs @@ -865,6 +865,8 @@ fn parse_all_file_under_path() { let res = load_all_files_under_paths(sess.clone(), &[main], Some(opt), None).unwrap(); - assert_eq!(res.program.pkgs.keys().len(), 4); - assert_eq!(res.paths.len(), 4); + assert_eq!(res.program.pkgs.keys().len(), 1); + assert_eq!(res.program.pkgs_not_imported.keys().len(), 3); + + assert_eq!(res.paths.len(), 1); } diff --git a/kclvm/query/src/query.rs b/kclvm/query/src/query.rs index f7f926cee..ece300208 100644 --- a/kclvm/query/src/query.rs +++ b/kclvm/query/src/query.rs @@ -207,7 +207,7 @@ pub fn get_full_schema_type( /// use maplit::hashmap; /// use kclvm_ast::MAIN_PKG; /// -/// let work_dir_parent = Path::new(".").join("src").join("test_data").join("get_schema_ty_under_path"); +/// let work_dir_parent = Path::new(env!("CARGO_MANIFEST_DIR")).join("src").join("test_data").join("get_schema_ty_under_path"); /// /// let result = get_full_schema_type_under_path( /// None, @@ -236,33 +236,8 @@ pub fn get_full_schema_type_under_path( schema_name: Option<&str>, opts: CompilationOptions, ) -> Result>> { - let mut result = IndexMap::new(); let program_scope = resolve_paths(&opts)?; - for (pkg, scope) in &program_scope.scope_map { - for (name, o) in &scope.borrow().elems { - if o.borrow().ty.is_schema() { - let schema_ty = o.borrow().ty.into_schema_type(); - if opts.get_schema_opts == GetSchemaOption::All - || (opts.get_schema_opts == GetSchemaOption::Definitions - && !schema_ty.is_instance) - || (opts.get_schema_opts == GetSchemaOption::Instances && schema_ty.is_instance) - { - // Schema name filter - match schema_name { - Some(schema_name) => { - if schema_name.is_empty() || schema_name == name { - result.entry(pkg.clone()).or_insert(vec![]).push(schema_ty); - } - } - None => { - result.entry(pkg.clone()).or_insert(vec![]).push(schema_ty); - } - } - } - } - } - } - Ok(result) + Ok(filter_pkg_schemas(&program_scope, schema_name, Some(opts))) } fn get_full_schema_type_recursive(schema_ty: SchemaType) -> Result { @@ -308,3 +283,50 @@ fn resolve_paths(opts: &CompilationOptions) -> Result { None, )) } + +pub fn filter_pkg_schemas( + program_scope: &ProgramScope, + schema_name: Option<&str>, + opts: Option, +) -> IndexMap> { + let mut result = IndexMap::new(); + for (pkg, scope) in &program_scope.scope_map { + for (name, o) in &scope.borrow().elems { + if o.borrow().ty.is_schema() { + let schema_ty = o.borrow().ty.into_schema_type(); + if let Some(opts) = &opts { + if opts.get_schema_opts == GetSchemaOption::All + || (opts.get_schema_opts == GetSchemaOption::Definitions + && !schema_ty.is_instance) + || (opts.get_schema_opts == GetSchemaOption::Instances + && schema_ty.is_instance) + { + // Schema name filter + match schema_name { + Some(schema_name) => { + if schema_name.is_empty() || schema_name == name { + result.entry(pkg.clone()).or_insert(vec![]).push(schema_ty); + } + } + None => { + result.entry(pkg.clone()).or_insert(vec![]).push(schema_ty); + } + } + } + } else { + match schema_name { + Some(schema_name) => { + if schema_name.is_empty() || schema_name == name { + result.entry(pkg.clone()).or_insert(vec![]).push(schema_ty); + } + } + None => { + result.entry(pkg.clone()).or_insert(vec![]).push(schema_ty); + } + } + } + } + } + } + result +} diff --git a/kclvm/runner/src/assembler.rs b/kclvm/runner/src/assembler.rs index 3aff09456..5915fca8e 100644 --- a/kclvm/runner/src/assembler.rs +++ b/kclvm/runner/src/assembler.rs @@ -299,6 +299,8 @@ impl KclvmAssembler { root: self.program.root.clone(), pkgs, modules: self.program.modules.clone(), + pkgs_not_imported: HashMap::new(), + modules_not_imported: HashMap::new(), }; compile_progs.insert( pkgpath, diff --git a/kclvm/runner/src/lib.rs b/kclvm/runner/src/lib.rs index 6dbe81f48..934438146 100644 --- a/kclvm/runner/src/lib.rs +++ b/kclvm/runner/src/lib.rs @@ -261,6 +261,8 @@ pub fn execute_module(m: Module) -> Result { root: MAIN_PKG.to_string(), pkgs, modules, + pkgs_not_imported: HashMap::new(), + modules_not_imported: HashMap::new(), }; execute( diff --git a/kclvm/runner/src/tests.rs b/kclvm/runner/src/tests.rs index 22d1f3bf5..8e0f172e2 100644 --- a/kclvm/runner/src/tests.rs +++ b/kclvm/runner/src/tests.rs @@ -187,6 +187,8 @@ fn construct_program(module: Module) -> Program { root: MAIN_PKG_NAME.to_string(), pkgs: pkgs_ast, modules, + pkgs_not_imported: HashMap::new(), + modules_not_imported: HashMap::new(), } } diff --git a/kclvm/sema/src/advanced_resolver/mod.rs b/kclvm/sema/src/advanced_resolver/mod.rs index b38be6dec..b10039cff 100644 --- a/kclvm/sema/src/advanced_resolver/mod.rs +++ b/kclvm/sema/src/advanced_resolver/mod.rs @@ -121,66 +121,76 @@ impl<'ctx> AdvancedResolver<'ctx> { }; // Scan all scehma symbol for (name, modules) in advanced_resolver.ctx.program.pkgs.iter() { - if !advanced_resolver.gs.new_or_invalidate_pkgs.contains(name) { - continue; + advanced_resolver.scan_schemas(name, modules)?; + } + + for (name, modules) in advanced_resolver.ctx.program.pkgs.iter() { + advanced_resolver.walk_pkg(name, modules)?; + } + + advanced_resolver.gs.build_sema_db(); + advanced_resolver.gs.new_or_invalidate_pkgs.clear(); + Ok(()) + } + + fn scan_schemas(&mut self, name: &String, modules: &Vec) -> anyhow::Result<()> { + if !self.gs.new_or_invalidate_pkgs.contains(name) { + return Ok(()); + } + self.ctx.current_pkgpath = Some(name.clone()); + if let Some(pkg_info) = self.gs.get_packages().get_package_info(name) { + if modules.is_empty() { + return Ok(()); + } + if !self.ctx.scopes.is_empty() { + self.ctx.scopes.clear(); } - 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() { - continue; - } - if !advanced_resolver.ctx.scopes.is_empty() { - advanced_resolver.ctx.scopes.clear(); - } - advanced_resolver.enter_root_scope( - name.clone(), - pkg_info.pkg_filepath.clone(), - pkg_info.kfile_paths.clone(), - ); + self.enter_root_scope( + name.clone(), + pkg_info.pkg_filepath.clone(), + pkg_info.kfile_paths.clone(), + ); - let modules = advanced_resolver.ctx.program.get_modules_for_pkg(name); - for module in modules.iter() { - let module = module.read().expect("Failed to acquire module lock"); - advanced_resolver.ctx.current_filename = Some(module.filename.clone()); - advanced_resolver.walk_module_schemas(&module)?; - } - advanced_resolver.leave_scope() + let modules = self.ctx.program.get_modules_for_pkg(name); + for module in modules.iter() { + let module = module.read().expect("Failed to acquire module lock"); + self.ctx.current_filename = Some(module.filename.clone()); + self.walk_module_schemas(&module)?; } + self.leave_scope() } + Ok(()) + } - for (name, modules) in advanced_resolver.ctx.program.pkgs.iter() { - if !advanced_resolver.gs.new_or_invalidate_pkgs.contains(name) { - continue; + fn walk_pkg(&mut self, name: &String, modules: &Vec) -> anyhow::Result<()> { + if !self.gs.new_or_invalidate_pkgs.contains(name) { + return Ok(()); + } + self.ctx.current_pkgpath = Some(name.clone()); + if let Some(_) = self.gs.get_packages().get_package_info(name) { + if modules.is_empty() { + return Ok(()); + } + if !self.ctx.scopes.is_empty() { + self.ctx.scopes.clear(); } - advanced_resolver.ctx.current_pkgpath = Some(name.clone()); - if let Some(_) = advanced_resolver.gs.get_packages().get_package_info(name) { - if modules.is_empty() { - continue; - } - if !advanced_resolver.ctx.scopes.is_empty() { - advanced_resolver.ctx.scopes.clear(); - } - let scope_ref = advanced_resolver - .gs - .get_scopes_mut() - .get_root_scope(name.to_string()) - .unwrap(); + let scope_ref = self + .gs + .get_scopes_mut() + .get_root_scope(name.to_string()) + .unwrap(); - advanced_resolver.ctx.scopes.push(scope_ref); - let modules = advanced_resolver.ctx.program.get_modules_for_pkg(name); - for module in modules.iter() { - let module = module.read().expect("Failed to acquire module lock"); - advanced_resolver.ctx.current_filename = Some(module.filename.clone()); - advanced_resolver.walk_module(&module)?; - } - advanced_resolver.leave_scope() + self.ctx.scopes.push(scope_ref); + let modules = self.ctx.program.get_modules_for_pkg(name); + for module in modules.iter() { + let module = module.read().expect("Failed to acquire module lock"); + self.ctx.current_filename = Some(module.filename.clone()); + self.walk_module(&module)?; } + self.leave_scope() } - - advanced_resolver.gs.build_sema_db(); - advanced_resolver.gs.new_or_invalidate_pkgs.clear(); Ok(()) } diff --git a/kclvm/sema/src/advanced_resolver/node.rs b/kclvm/sema/src/advanced_resolver/node.rs index b74ac15c6..0d7faf4cc 100644 --- a/kclvm/sema/src/advanced_resolver/node.rs +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -62,7 +62,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'_> { .gs .get_symbols() .get_symbol(schema_symbol) - .ok_or(anyhow!("schema_symbol not found"))?; + .ok_or(anyhow!("schema_symbol not found1"))?; if let Some(schema_ty) = schema_symbol.get_sema_info().ty.clone() { if !unification_stmt.target.node.names.is_empty() { let schema_ty = schema_ty.into_schema_type(); @@ -232,7 +232,10 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'_> { .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 when walk schema stmt {:?}", + schema_stmt + ))? .clone(); let schema_symbol = self .gs @@ -875,7 +878,10 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'_> { .node_ty_map .borrow() .get(&self.ctx.get_node_key(&schema_expr.name.id)) - .ok_or(anyhow!("schema_ty not found"))? + .ok_or(anyhow!( + "schema_ty not found when walk schema expr {:?}", + schema_expr + ))? .clone(); match schema_ty.kind { TypeKind::Schema(_) => { diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs index cd14b03c3..0b81521fe 100644 --- a/kclvm/sema/src/core/symbol.rs +++ b/kclvm/sema/src/core/symbol.rs @@ -106,6 +106,10 @@ pub enum SymbolHintKind { } impl SymbolData { + pub fn get_all_schemas(&self) -> &Arena { + &self.schemas + } + pub fn get_package_symbol(&self, id: SymbolRef) -> Option<&PackageSymbol> { if matches!(id.get_kind(), SymbolKind::Package) { self.packages.get(id.get_id()) diff --git a/kclvm/sema/src/namer/mod.rs b/kclvm/sema/src/namer/mod.rs index 2303fd663..5c6560672 100644 --- a/kclvm/sema/src/namer/mod.rs +++ b/kclvm/sema/src/namer/mod.rs @@ -113,75 +113,74 @@ 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; - } + namer.walk_pkg(name, modules); + } - // add new pkgs to invalidate pkgs - namer.gs.new_or_invalidate_pkgs.insert(name.clone()); - - { - if modules.is_empty() { - continue; - } - namer.ctx.value_fully_qualified_name_set.clear(); - let mut real_path = Path::new(&program.root) - .join(name.replace('.', &std::path::MAIN_SEPARATOR.to_string())) - .to_str() - .unwrap() - .to_string(); - if name == kclvm_ast::MAIN_PKG { - real_path = program.root.clone() - } - let pkg_pos = Position { - filename: real_path.clone(), - line: 0, - column: None, - }; - - 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, name.to_string()); - namer.ctx.owner_symbols.push(symbol_ref); + namer.define_symbols(); + } - namer.ctx.current_package_info = - Some(PackageInfo::new(name.to_string(), real_path, false)); - } + fn walk_pkg(&mut self, name: &String, modules: &Vec) { + // new pkgs or invalidate pkg + if self.gs.get_packages().get_package_info(name).is_some() + && !self.gs.new_or_invalidate_pkgs.contains(name) + { + return; + } - let modules = namer.ctx.program.get_modules_for_pkg(name); - for module in modules.iter() { - let module = module.read().expect("Failed to acquire module lock"); - namer - .ctx - .current_package_info - .as_mut() - .unwrap() - .kfile_paths - .insert(module.filename.clone()); - namer.ctx.current_module_info = - Some(ModuleInfo::new(module.filename.clone(), name.to_string())); - namer.walk_module(&module); - namer - .gs - .get_packages_mut() - .add_module_info(namer.ctx.current_module_info.take().unwrap()); - } + // add new pkgs to invalidate pkgs + self.gs.new_or_invalidate_pkgs.insert(name.clone()); - namer.ctx.owner_symbols.pop(); - namer + { + if modules.is_empty() { + return; + } + self.ctx.value_fully_qualified_name_set.clear(); + let mut real_path = Path::new(&self.ctx.program.root) + .join(name.replace('.', &std::path::MAIN_SEPARATOR.to_string())) + .to_str() + .unwrap() + .to_string(); + if name == kclvm_ast::MAIN_PKG { + real_path = self.ctx.program.root.clone() + } + let pkg_pos = Position { + filename: real_path.clone(), + line: 0, + column: None, + }; + + let pkg_symbol = PackageSymbol::new(name.clone(), pkg_pos.clone(), pkg_pos); + let symbol_ref = self .gs - .get_packages_mut() - .add_package(namer.ctx.current_package_info.take().unwrap()) + .get_symbols_mut() + .alloc_package_symbol(pkg_symbol, name.to_string()); + self.ctx.owner_symbols.push(symbol_ref); + + self.ctx.current_package_info = + Some(PackageInfo::new(name.to_string(), real_path, false)); } - namer.define_symbols(); + let modules = self.ctx.program.get_modules_for_pkg(name); + for module in modules.iter() { + let module = module.read().expect("Failed to acquire module lock"); + self.ctx + .current_package_info + .as_mut() + .unwrap() + .kfile_paths + .insert(module.filename.clone()); + self.ctx.current_module_info = + Some(ModuleInfo::new(module.filename.clone(), name.to_string())); + self.walk_module(&module); + self.gs + .get_packages_mut() + .add_module_info(self.ctx.current_module_info.take().unwrap()); + } - // namer.gs + self.ctx.owner_symbols.pop(); + self.gs + .get_packages_mut() + .add_package(self.ctx.current_package_info.take().unwrap()) } fn init_builtin_symbols(&mut self) { diff --git a/kclvm/sema/src/resolver/global.rs b/kclvm/sema/src/resolver/global.rs index 4796a114d..9f5c97adc 100644 --- a/kclvm/sema/src/resolver/global.rs +++ b/kclvm/sema/src/resolver/global.rs @@ -27,7 +27,12 @@ impl<'ctx> Resolver<'_> { pub(crate) fn init_global_types(&mut self) { // 1. Scan all schema and rule type symbols let pkgpath = &self.ctx.pkgpath; - match self.program.pkgs.get(pkgpath) { + match self + .program + .pkgs + .get(pkgpath) + .or(self.program.pkgs_not_imported.get(pkgpath)) + { Some(modules) => { // 1. Scan all schema and rule type symbol for module in modules { diff --git a/kclvm/sema/src/resolver/mod.rs b/kclvm/sema/src/resolver/mod.rs index 8b318c993..3987f821a 100644 --- a/kclvm/sema/src/resolver/mod.rs +++ b/kclvm/sema/src/resolver/mod.rs @@ -73,7 +73,12 @@ impl<'ctx> Resolver<'ctx> { pub(crate) fn check(&mut self, pkgpath: &str) { self.check_import(pkgpath); self.init_global_types(); - match self.program.pkgs.get(pkgpath) { + match self + .program + .pkgs + .get(pkgpath) + .or(self.program.pkgs_not_imported.get(pkgpath)) + { Some(modules) => { for module in modules { let module = self @@ -99,26 +104,29 @@ impl<'ctx> Resolver<'ctx> { pub(crate) fn check_and_lint_all_pkgs(&mut self) -> ProgramScope { self.check(kclvm_ast::MAIN_PKG); - for pkg in self.program.pkgs.keys() { + self.lint_check_scope_map(); + let mut handler = self.handler.clone(); + for diag in &self.linter.handler.diagnostics { + handler.diagnostics.insert(diag.clone()); + } + + for pkg in self.program.pkgs_not_imported.keys() { if !self.scope_map.contains_key(pkg) { self.check(pkg); } } + let mut scope_map = self.scope_map.clone(); for invalid_pkg_scope in &self.ctx.invalid_pkg_scope { scope_map.remove(invalid_pkg_scope); } - let mut scope = ProgramScope { + let scope = ProgramScope { scope_map, import_names: self.ctx.import_names.clone(), node_ty_map: self.node_ty_map.clone(), - handler: self.handler.clone(), + handler, schema_mapping: self.ctx.schema_mapping.clone(), }; - self.lint_check_scope_map(); - for diag in &self.linter.handler.diagnostics { - scope.handler.diagnostics.insert(diag.clone()); - } scope } } diff --git a/kclvm/sema/src/resolver/tests.rs b/kclvm/sema/src/resolver/tests.rs index 3d0240973..88b3d8682 100644 --- a/kclvm/sema/src/resolver/tests.rs +++ b/kclvm/sema/src/resolver/tests.rs @@ -30,6 +30,8 @@ pub fn parse_program(filename: &str) -> Result { root: abspath.parent().unwrap().adjust_canonicalization(), pkgs: HashMap::new(), modules: HashMap::new(), + pkgs_not_imported: HashMap::new(), + modules_not_imported: HashMap::new(), }; let mut module = parse_file_force_errors(abspath.to_str().unwrap(), None)?; diff --git a/kclvm/tools/src/LSP/src/analysis.rs b/kclvm/tools/src/LSP/src/analysis.rs index 3cb60a77f..fbcef2258 100644 --- a/kclvm/tools/src/LSP/src/analysis.rs +++ b/kclvm/tools/src/LSP/src/analysis.rs @@ -1,8 +1,8 @@ -use indexmap::IndexSet; +use indexmap::{IndexMap, IndexSet}; use kclvm_ast::ast::Program; use kclvm_driver::WorkSpaceKind; use kclvm_error::Diagnostic; -use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::{core::global_state::GlobalState, ty::SchemaType}; use parking_lot::RwLock; use std::{ collections::{HashMap, HashSet}, @@ -38,4 +38,5 @@ pub struct AnalysisDatabase { pub prog: Program, pub gs: GlobalState, pub diags: IndexSet, + pub schema_map: IndexMap>, } diff --git a/kclvm/tools/src/LSP/src/compile.rs b/kclvm/tools/src/LSP/src/compile.rs index ed87010f4..3bfc02ff6 100644 --- a/kclvm/tools/src/LSP/src/compile.rs +++ b/kclvm/tools/src/LSP/src/compile.rs @@ -1,16 +1,18 @@ -use indexmap::IndexSet; +use indexmap::{IndexMap, IndexSet}; use kclvm_ast::ast::Program; use kclvm_driver::{lookup_compile_workspace, toolchain}; use kclvm_error::Diagnostic; use kclvm_parser::{ - entry::get_normalized_k_files_from_paths, load_program, KCLModuleCache, LoadProgramOptions, - ParseSessionRef, + entry::get_normalized_k_files_from_paths, load_all_files_under_paths, KCLModuleCache, + LoadProgramOptions, ParseSessionRef, }; +use kclvm_query::query::filter_pkg_schemas; use kclvm_sema::{ advanced_resolver::AdvancedResolver, core::global_state::GlobalState, namer::Namer, resolver::{resolve_program_with_opts, scope::KCLScopeCache}, + ty::SchemaType, }; use std::collections::HashSet; use std::path::PathBuf; @@ -32,7 +34,10 @@ pub fn compile( params: Params, files: &mut [String], opts: Option, -) -> (IndexSet, anyhow::Result<(Program, GlobalState)>) { +) -> ( + IndexSet, + anyhow::Result<(Program, IndexMap>, GlobalState)>, +) { // Ignore the kcl plugin sematic check. let mut opts = opts.unwrap_or_default(); opts.load_plugins = true; @@ -92,10 +97,12 @@ pub fn compile( } } } - let mut program = match load_program(sess.clone(), &files, Some(opts), params.module_cache) { - Ok(r) => r.program, - Err(e) => return (diags, Err(anyhow::anyhow!("Parse failed: {:?}", e))), - }; + + let mut program = + match load_all_files_under_paths(sess.clone(), &files, Some(opts), params.module_cache) { + Ok(r) => r.program, + Err(e) => return (diags, Err(anyhow::anyhow!("Parse failed: {:?}", e))), + }; diags.extend(sess.1.read().diagnostics.clone()); // Resolver @@ -118,6 +125,7 @@ pub fn compile( }, params.scope_cache.clone(), ); + let schema_map: IndexMap> = filter_pkg_schemas(&prog_scope, None, None); diags.extend(prog_scope.handler.diagnostics); let mut default = GlobalState::default(); @@ -141,12 +149,16 @@ pub fn compile( }, None => HashSet::new(), }; + + gs.new_or_invalidate_pkgs + .extend(program.pkgs_not_imported.keys().map(|n| n.clone())); + gs.clear_cache(); Namer::find_symbols(&program, gs); match AdvancedResolver::resolve_program(&program, gs, prog_scope.node_ty_map) { - Ok(_) => (diags, Ok((program, gs.clone()))), + Ok(_) => (diags, Ok((program, schema_map, gs.clone()))), Err(e) => (diags, Err(anyhow::anyhow!("Resolve failed: {:?}", e))), } } @@ -156,7 +168,7 @@ pub fn compile_with_params( params: Params, ) -> ( IndexSet, - anyhow::Result<(Program, GlobalState)>, + anyhow::Result<(Program, IndexMap>, GlobalState)>, ) { let file = PathBuf::from(params.file.clone().unwrap()) .canonicalize() diff --git a/kclvm/tools/src/LSP/src/completion.rs b/kclvm/tools/src/LSP/src/completion.rs index 70db428d1..83f763f09 100644 --- a/kclvm/tools/src/LSP/src/completion.rs +++ b/kclvm/tools/src/LSP/src/completion.rs @@ -16,11 +16,13 @@ //! + schema init use crate::goto_def::{find_def, find_symbol}; -use indexmap::IndexSet; +use crate::to_lsp::lsp_pos; +use indexmap::{IndexMap, IndexSet}; use kclvm_ast::ast::{self, ImportStmt, Program, Stmt}; use kclvm_ast::MAIN_PKG; use kclvm_config::modfile::KCL_FILE_EXTENSION; use kclvm_driver::toolchain::{get_real_path_from_external, Metadata, Toolchain}; +use kclvm_error::diagnostic::Range; use kclvm_parser::get_kcl_files; use kclvm_sema::core::global_state::GlobalState; use std::io; @@ -65,6 +67,12 @@ impl From for CompletionItemKind { } } +#[derive(Debug, Clone, PartialEq, Hash, Eq, Default)] +pub struct TextEdit { + pub range: Range, + pub new_text: String, +} + /// Abstraction of CompletionItem in KCL #[derive(Debug, Clone, PartialEq, Hash, Eq, Default)] pub(crate) struct KCLCompletionItem { @@ -73,6 +81,7 @@ pub(crate) struct KCLCompletionItem { pub documentation: Option, pub kind: Option, pub insert_text: Option, + pub additional_text_edits: Option>, } /// Computes completions at the given position. @@ -83,6 +92,7 @@ pub fn completion( gs: &GlobalState, tool: &dyn Toolchain, metadata: Option, + schema_map: &IndexMap>, ) -> Option { match trigger_character { Some(c) => match c { @@ -107,6 +117,7 @@ pub fn completion( documentation: None, kind: Some(KCLCompletionItemKind::Module), insert_text: None, + additional_text_edits: None, })); } @@ -132,6 +143,7 @@ pub fn completion( name, &ty.into_func_type(), )), + additional_text_edits: None, }, )); } @@ -150,8 +162,13 @@ pub fn completion( name, &ty.into_func_type(), )), + additional_text_edits: None, } })); + // Complete all schema def in gs if in main pkg + if program.get_main_files().contains(&pos.filename) { + completions.extend(unimport_schemas(&pos.filename, gs, schema_map)); + } } } @@ -172,7 +189,7 @@ pub fn completion( )); // complete schema value completions.insert(schema_ty_to_value_complete_item( - &schema_ty, + &schema_ty, true, )); } SymbolKind::Package => { @@ -182,6 +199,7 @@ pub fn completion( documentation: sema_info.doc.clone(), kind: Some(KCLCompletionItemKind::Module), insert_text: None, + additional_text_edits: None, }); } _ => { @@ -197,6 +215,7 @@ pub fn completion( documentation: sema_info.doc.clone(), kind: type_to_item_kind(ty), insert_text: None, + additional_text_edits: None, }); } }, @@ -317,6 +336,7 @@ fn completion_dot( documentation, kind, insert_text, + additional_text_edits: None, }); } None => { @@ -326,6 +346,7 @@ fn completion_dot( documentation: None, kind: None, insert_text: None, + additional_text_edits: None, }); } } @@ -367,6 +388,7 @@ fn completion_assign(pos: &KCLPos, gs: &GlobalState) -> Option {} @@ -491,6 +515,7 @@ fn completion_import_builtin_pkg() -> IndexSet { documentation: None, kind: Some(KCLCompletionItemKind::Module), insert_text: None, + additional_text_edits: None, }) .collect() } @@ -521,6 +546,7 @@ fn completion_import_internal_pkg( documentation: None, kind: Some(KCLCompletionItemKind::Dir), insert_text: None, + additional_text_edits: None, }); } } else { @@ -541,6 +567,7 @@ fn completion_import_internal_pkg( documentation: None, kind: Some(KCLCompletionItemKind::Module), insert_text: None, + additional_text_edits: None, }); } } @@ -565,6 +592,7 @@ fn completion_import_external_pkg(metadata: Option) -> IndexSet IndexSet::new(), @@ -580,13 +608,22 @@ fn completion_import_external_pkg(metadata: Option) -> IndexSet +/// import pkg +/// p = pkg.Person(param1, param2){} /// ``` -fn schema_ty_to_value_complete_item(schema_ty: &SchemaType) -> KCLCompletionItem { +fn schema_ty_to_value_complete_item(schema_ty: &SchemaType, has_import: bool) -> KCLCompletionItem { + let schema = schema_ty.clone(); let param = schema_ty.func.params.clone(); + let pkg_path_last_name = if schema.pkgpath.is_empty() || schema.pkgpath == MAIN_PKG { + "".to_string() + } else { + format!("{}", schema.pkgpath.split('.').last().unwrap()) + }; + let need_import = !pkg_path_last_name.is_empty() && !has_import; + let label = format!( - "{}{}{}", - schema_ty.name.clone(), + "{}{}{}{}", + schema.name, if param.is_empty() { "".to_string() } else { @@ -599,26 +636,24 @@ fn schema_ty_to_value_complete_item(schema_ty: &SchemaType) -> KCLCompletionItem .join(", ") ) }, - "{}" + "{}", + if need_import { + format!("(import {})", schema.pkgpath) + } else { + "".to_string() + }, ); - let detail = { - let mut details = vec![]; - let (pkgpath, rest_sign) = schema_ty.schema_ty_signature_str(); - details.push(format!("{}\n\n{}", pkgpath, rest_sign)); - details.push("Attributes:".to_string()); - for (name, attr) in &schema_ty.attrs { - details.push(format!( - "{}{}: {}", - name, - if attr.is_optional { "?" } else { "" }, - attr.ty.ty_str(), - )); - } - details.join("\n") - }; + + // `pkg_path.schema_name{}` or `schema_name{}` let insert_text = format!( - "{}{}{}", - schema_ty.name.clone(), + "{}{}{}{}{}", + pkg_path_last_name, + if pkg_path_last_name.is_empty() { + "" + } else { + "." + }, + schema.name, if param.is_empty() { "".to_string() } else { @@ -632,14 +667,42 @@ fn schema_ty_to_value_complete_item(schema_ty: &SchemaType) -> KCLCompletionItem .join(", ") ) }, - "{}" + "{$0}" ); + + // insert `import pkg` + let additional_text_edits = if need_import { + Some(vec![TextEdit { + range: (KCLPos::dummy_pos(), KCLPos::dummy_pos()), + new_text: format!("import {}\n", schema.pkgpath), + }]) + } else { + None + }; + + let detail = { + let mut details = vec![]; + let (pkgpath, rest_sign) = schema_ty.schema_ty_signature_str(); + details.push(format!("{}\n\n{}", pkgpath, rest_sign)); + details.push("Attributes:".to_string()); + for (name, attr) in &schema_ty.attrs { + details.push(format!( + "{}{}: {}", + name, + if attr.is_optional { "?" } else { "" }, + attr.ty.ty_str(), + )); + } + details.join("\n") + }; + KCLCompletionItem { label, detail: Some(detail), documentation: Some(schema_ty.doc.clone()), kind: Some(KCLCompletionItemKind::Schema), insert_text: Some(insert_text), + additional_text_edits, } } @@ -676,6 +739,7 @@ fn schema_ty_to_type_complete_item(schema_ty: &SchemaType) -> KCLCompletionItem documentation: Some(schema_ty.doc.clone()), kind: Some(KCLCompletionItemKind::Schema), insert_text: None, + additional_text_edits: None, } } @@ -709,6 +773,7 @@ fn dot_completion_in_import_stmt( documentation: None, kind: Some(KCLCompletionItemKind::Dir), insert_text: None, + additional_text_edits: None, }); } else if path.is_file() { if let Some(extension) = path.extension() { @@ -725,6 +790,7 @@ fn dot_completion_in_import_stmt( documentation: None, kind: Some(KCLCompletionItemKind::File), insert_text: None, + additional_text_edits: None, }); } } @@ -835,25 +901,71 @@ fn type_to_item_kind(ty: &Type) -> Option { pub(crate) fn into_completion_items(items: &IndexSet) -> Vec { items .iter() - .map(|item| CompletionItem { - label: item.label.clone(), - detail: item.detail.clone(), - documentation: item - .documentation - .clone() - .map(lsp_types::Documentation::String), - kind: item.kind.clone().map(|kind| kind.into()), - insert_text: item.insert_text.clone(), - insert_text_format: if item.insert_text.is_some() { - Some(InsertTextFormat::SNIPPET) - } else { - None - }, - ..Default::default() + .map(|item| { + let additional_text_edits = match &item.additional_text_edits { + Some(edits) => { + let mut res = vec![]; + for edit in edits { + res.push(lsp_types::TextEdit { + range: lsp_types::Range { + start: lsp_pos(&edit.range.0), + end: lsp_pos(&edit.range.1), + }, + new_text: edit.new_text.clone(), + }) + } + + Some(res) + } + None => None, + }; + + CompletionItem { + label: item.label.clone(), + detail: item.detail.clone(), + documentation: item + .documentation + .clone() + .map(lsp_types::Documentation::String), + kind: item.kind.clone().map(|kind| kind.into()), + insert_text: item.insert_text.clone(), + insert_text_format: if item.insert_text.is_some() { + Some(InsertTextFormat::SNIPPET) + } else { + None + }, + additional_text_edits, + + ..Default::default() + } }) .collect() } +fn unimport_schemas( + filename: &str, + gs: &GlobalState, + schema_map: &IndexMap>, +) -> IndexSet { + let module = gs.get_packages().get_module_info(filename); + let mut completions: IndexSet = IndexSet::new(); + for (_, schemas) in schema_map { + for schema in schemas { + let has_import = match module { + Some(m) => m + .get_imports() + .iter() + .any(|(_, info)| info.get_fully_qualified_name() == schema.pkgpath), + None => false, + }; + if schema.pkgpath != MAIN_PKG { + completions.insert(schema_ty_to_value_complete_item(&schema, has_import)); + } + } + } + completions +} + #[cfg(test)] mod tests { use crate::{ @@ -875,8 +987,8 @@ mod tests { #[test] #[bench_test] fn var_completion_test() { - let (file, program, _, gs) = - compile_test_file("src/test_data/completion_test/dot/completion.k"); + let (file, program, _, gs, schema_map) = + compile_test_file("src/test_data/completion_test/dot/completion/completion.k"); // test completion for var let pos = KCLPos { @@ -886,7 +998,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let mut got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -894,8 +1006,22 @@ mod tests { let mut expected_labels: Vec = vec![ "", // generate from error recovery of "pkg." - "subpkg", "math", "Person", "Person{}", "P", "P{}", "p", "p1", "p2", "p3", "p4", - "aaaa", "Config", "Config{}", "n", + "subpkg", + "math", + "Person", + "Person1{}", + "Person{}", + "P", + "P{}", + "p", + "p1", + "p2", + "p3", + "p4", + "aaaa", + "Config", + "Config{}", + "n", ] .iter() .map(|s| s.to_string()) @@ -918,7 +1044,7 @@ mod tests { column: Some(4), }; - let got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let mut got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -936,8 +1062,8 @@ mod tests { #[test] #[bench_test] fn dot_completion_test() { - let (file, program, _, gs) = - compile_test_file("src/test_data/completion_test/dot/completion.k"); + let (file, program, _, gs, schema_map) = + compile_test_file("src/test_data/completion_test/dot/completion/completion.k"); // test completion for schema attr let pos = KCLPos { @@ -947,7 +1073,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -963,7 +1089,7 @@ mod tests { }; // test completion for str builtin function - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -994,7 +1120,7 @@ mod tests { column: Some(12), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1010,7 +1136,7 @@ mod tests { column: Some(12), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1024,7 +1150,7 @@ mod tests { line: 19, column: Some(5), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1042,7 +1168,7 @@ mod tests { column: Some(4), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1060,7 +1186,7 @@ mod tests { column: Some(11), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1076,7 +1202,7 @@ mod tests { column: Some(30), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1092,7 +1218,7 @@ mod tests { #[test] #[bench_test] fn dot_completion_test_without_dot() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/without_dot/completion.k"); // test completion for schema attr @@ -1103,7 +1229,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1119,7 +1245,7 @@ mod tests { }; // test completion for str builtin function - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1137,7 +1263,7 @@ mod tests { column: Some(12), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1153,7 +1279,7 @@ mod tests { column: Some(12), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1167,7 +1293,7 @@ mod tests { line: 19, column: Some(5), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1198,7 +1324,7 @@ mod tests { column: Some(4), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1229,7 +1355,7 @@ mod tests { column: Some(11), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1245,7 +1371,7 @@ mod tests { column: Some(30), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1274,7 +1400,7 @@ mod tests { #[test] #[bench_test] fn import_builtin_package() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/import/builtin/builtin_pkg.k"); let mut items: IndexSet = IndexSet::new(); @@ -1286,7 +1412,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let _got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1315,6 +1441,7 @@ mod tests { detail: None, documentation: None, insert_text: None, + additional_text_edits: None, }) .collect::>(), ); @@ -1325,7 +1452,7 @@ mod tests { #[test] #[bench_test] fn attr_value_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/assign/completion.k"); let pos = KCLPos { @@ -1335,7 +1462,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1348,7 +1475,7 @@ mod tests { line: 16, column: Some(6), }; - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1361,7 +1488,7 @@ mod tests { line: 18, column: Some(6), }; - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1374,7 +1501,7 @@ mod tests { line: 20, column: Some(6), }; - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1387,7 +1514,7 @@ mod tests { line: 22, column: Some(6), }; - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1400,7 +1527,7 @@ mod tests { line: 24, column: Some(6), }; - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1413,7 +1540,7 @@ mod tests { line: 26, column: Some(6), }; - let got = completion(Some(':'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1435,8 +1562,8 @@ mod tests { #[test] #[bench_test] fn schema_sig_completion() { - let (file, program, _, gs) = - compile_test_file("src/test_data/completion_test/schema/schema.k"); + let (file, program, _, gs, schema_map) = + compile_test_file("src/test_data/completion_test/schema/schema/schema.k"); let pos = KCLPos { filename: file.to_owned(), @@ -1445,7 +1572,7 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { assert_eq!( @@ -1458,7 +1585,7 @@ mod tests { .to_string() ), documentation: Some(lsp_types::Documentation::String("".to_string())), - insert_text: Some("Person(${1:b}){}".to_string()), + insert_text: Some("Person(${1:b}){$0}".to_string()), insert_text_format: Some(InsertTextFormat::SNIPPET), ..Default::default() } @@ -1470,7 +1597,7 @@ mod tests { #[test] fn schema_docstring_newline_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/newline/docstring_newline.k"); let pos = KCLPos { @@ -1479,7 +1606,8 @@ mod tests { column: Some(4), }; let tool = toolchain::default(); - let mut got = completion(Some('\n'), &program, &pos, &gs, &tool, None).unwrap(); + let mut got = + completion(Some('\n'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { arr.sort_by(|a, b| a.label.cmp(&b.label)); @@ -1500,7 +1628,7 @@ mod tests { #[test] fn str_dot_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); // test complete str functions when at the end of literal str @@ -1511,7 +1639,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &got { CompletionResponse::Array(arr) => { @@ -1552,7 +1680,7 @@ mod tests { column: Some(6), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1566,7 +1694,7 @@ mod tests { column: Some(5), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => assert!(arr.is_empty()), CompletionResponse::List(_) => panic!("test failed"), @@ -1579,7 +1707,7 @@ mod tests { column: Some(8), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => assert!(arr.is_empty()), CompletionResponse::List(_) => panic!("test failed"), @@ -1590,7 +1718,7 @@ mod tests { line: 3, column: Some(2), }; - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => { assert!(arr @@ -1603,7 +1731,7 @@ mod tests { #[test] fn schema_ty_attr_complete() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/schema_ty_attr/schema_ty_attr.k"); let pos = KCLPos { @@ -1613,7 +1741,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => { assert_eq!( @@ -1632,7 +1760,7 @@ mod tests { #[test] fn schema_end_pos() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/schema/schema_pos/schema_pos.k"); let pos = KCLPos { @@ -1642,7 +1770,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => { assert_eq!(arr.len(), 4); @@ -1656,7 +1784,7 @@ mod tests { #[test] fn comment_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); let pos = KCLPos { @@ -1666,7 +1794,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &got { CompletionResponse::Array(arr) => { @@ -1679,7 +1807,7 @@ mod tests { #[test] #[bench_test] fn missing_expr_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/missing_expr/missing_expr.k"); let pos = KCLPos { @@ -1689,7 +1817,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => { assert_eq!(arr.len(), 2); @@ -1704,7 +1832,7 @@ mod tests { #[test] #[bench_test] fn check_scope_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/check/check.k"); let pos = KCLPos { @@ -1714,7 +1842,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some(':'), &program, &pos, &gs, &tool, None); + let got = completion(Some(':'), &program, &pos, &gs, &tool, None, &schema_map); assert!(got.is_none()); let pos = KCLPos { @@ -1723,7 +1851,7 @@ mod tests { column: Some(9), }; - let got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match got { CompletionResponse::Array(arr) => { assert_eq!(arr.len(), 3); @@ -1737,7 +1865,7 @@ mod tests { #[test] #[bench_test] fn join_str_inner_completion() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); let pos = KCLPos { @@ -1747,7 +1875,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &got { CompletionResponse::Array(arr) => { assert!(arr.is_empty()) @@ -1762,7 +1890,7 @@ mod tests { }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &got { CompletionResponse::Array(arr) => { assert!(arr.is_empty()) @@ -1774,8 +1902,8 @@ mod tests { #[test] #[bench_test] fn schema_type_attr_completion() { - let (file, program, _, gs) = - compile_test_file("src/test_data/completion_test/schema/schema.k"); + let (file, program, _, gs, schema_map) = + compile_test_file("src/test_data/completion_test/schema/schema/schema.k"); let pos = KCLPos { filename: file.to_owned(), @@ -1784,7 +1912,7 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); @@ -1800,7 +1928,7 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); @@ -1813,7 +1941,7 @@ mod tests { #[test] #[bench_test] fn nested_1_test() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/nested/nested_1/nested_1.k"); let pos = KCLPos { @@ -1823,7 +1951,7 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { @@ -1837,7 +1965,7 @@ mod tests { #[test] #[bench_test] fn nested_2_test() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/nested/nested_2/nested_2.k"); let pos = KCLPos { @@ -1848,7 +1976,7 @@ mod tests { let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { @@ -1861,7 +1989,7 @@ mod tests { #[test] #[bench_test] fn nested_3_test() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/nested/nested_3/nested_3.k"); let pos = KCLPos { @@ -1871,7 +1999,7 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { @@ -1885,7 +2013,7 @@ mod tests { #[test] #[bench_test] fn nested_4_test() { - let (file, program, _, gs) = + let (file, program, _, gs, schema_map) = compile_test_file("src/test_data/completion_test/dot/nested/nested_4/nested_4.k"); let pos = KCLPos { @@ -1896,7 +2024,7 @@ mod tests { let tool = toolchain::default(); - let mut got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); match &mut got { CompletionResponse::Array(arr) => { @@ -1912,7 +2040,7 @@ mod tests { ($name:ident, $file:expr, $line:expr, $column: expr, $trigger: expr) => { #[test] fn $name() { - let (file, program, _, gs) = compile_test_file($file); + let (file, program, _, gs, schema_map) = compile_test_file($file); let pos = KCLPos { filename: file.clone(), @@ -1921,7 +2049,8 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion($trigger, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = + completion($trigger, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels = match &mut got { CompletionResponse::Array(arr) => { @@ -1942,7 +2071,7 @@ mod tests { ($name:ident, $file:expr, $line:expr, $column: expr, $trigger: expr) => { #[test] fn $name() { - let (file, program, _, gs) = compile_test_file($file); + let (file, program, _, gs, schema_map) = compile_test_file($file); let pos = KCLPos { filename: file.clone(), @@ -1951,7 +2080,8 @@ mod tests { }; let tool = toolchain::default(); - let mut got = completion($trigger, &program, &pos, &gs, &tool, None).unwrap(); + let mut got = + completion($trigger, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels = match &mut got { CompletionResponse::Array(arr) => { @@ -1984,14 +2114,17 @@ mod tests { ($name:ident, $file:expr, $line:expr, $column: expr, $trigger: expr) => { #[test] fn $name() { - let (file, program, _, gs, metadata) = compile_test_file_and_metadata($file); + let (file, program, _, gs, metadata, schema_map) = + compile_test_file_and_metadata($file); let pos = KCLPos { filename: file.clone(), line: $line, column: Some($column), }; let tool = toolchain::default(); - let mut got = completion($trigger, &program, &pos, &gs, &tool, metadata).unwrap(); + let mut got = + completion($trigger, &program, &pos, &gs, &tool, metadata, &schema_map) + .unwrap(); let got_labels = match &mut got { CompletionResponse::Array(arr) => { let mut labels: Vec = @@ -2094,7 +2227,7 @@ mod tests { completion_label_test_snapshot!( schema_attr_in_right, - "src/test_data/completion_test/schema/schema.k", + "src/test_data/completion_test/schema/schema/schema.k", 23, 11, None @@ -2179,4 +2312,12 @@ mod tests { 23, Some('.') ); + + completion_label_without_builtin_func_test_snapshot!( + complete_unimport_schemas, + "src/test_data/completion_test/unimport/unimport/main.k", + 1, + 1, + None + ); } diff --git a/kclvm/tools/src/LSP/src/document_symbol.rs b/kclvm/tools/src/LSP/src/document_symbol.rs index 882fb9d45..b2315ce8b 100644 --- a/kclvm/tools/src/LSP/src/document_symbol.rs +++ b/kclvm/tools/src/LSP/src/document_symbol.rs @@ -171,7 +171,8 @@ mod tests { #[test] #[bench_test] fn document_symbol_test() { - let (file, _, _, gs) = compile_test_file("src/test_data/document_symbol.k"); + let (file, _, _, gs, _) = + compile_test_file("src/test_data/document_symbol/document_symbol.k"); let mut res = document_symbol(file.as_str(), &gs).unwrap(); let mut expect = vec![]; diff --git a/kclvm/tools/src/LSP/src/find_refs.rs b/kclvm/tools/src/LSP/src/find_refs.rs index 8d42fb560..68d977e9f 100644 --- a/kclvm/tools/src/LSP/src/find_refs.rs +++ b/kclvm/tools/src/LSP/src/find_refs.rs @@ -55,7 +55,7 @@ mod tests { ($name:ident, $file:expr, $line:expr, $column: expr) => { #[test] fn $name() { - let (file, _program, _, gs) = compile_test_file($file); + let (file, _program, _, gs, _) = compile_test_file($file); let pos = KCLPos { filename: file.clone(), diff --git a/kclvm/tools/src/LSP/src/formatting.rs b/kclvm/tools/src/LSP/src/formatting.rs index 0b7833af4..4ba39ac09 100644 --- a/kclvm/tools/src/LSP/src/formatting.rs +++ b/kclvm/tools/src/LSP/src/formatting.rs @@ -115,7 +115,7 @@ mod tests { #[test] #[bench_test] fn format_range_test() { - let (file, _program, _, _gs) = compile_test_file("src/test_data/format/format_range.k"); + let (file, _program, _, _gs, _) = compile_test_file("src/test_data/format/format_range.k"); let lsp_range = Range::new(Position::new(0, 0), Position::new(11, 0)); let text = std::fs::read_to_string(file.clone()).unwrap(); diff --git a/kclvm/tools/src/LSP/src/goto_def.rs b/kclvm/tools/src/LSP/src/goto_def.rs index c04af0109..562f42494 100644 --- a/kclvm/tools/src/LSP/src/goto_def.rs +++ b/kclvm/tools/src/LSP/src/goto_def.rs @@ -116,7 +116,7 @@ mod tests { ($name:ident, $file:expr, $line:expr, $column: expr) => { #[test] fn $name() { - let (file, _program, _, gs) = compile_test_file($file); + let (file, _program, _, gs, _) = compile_test_file($file); let pos = KCLPos { filename: file.clone(), diff --git a/kclvm/tools/src/LSP/src/hover.rs b/kclvm/tools/src/LSP/src/hover.rs index d0ab05ae5..c69c19b40 100644 --- a/kclvm/tools/src/LSP/src/hover.rs +++ b/kclvm/tools/src/LSP/src/hover.rs @@ -263,7 +263,8 @@ mod tests { fn schema_doc_hover_test() { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let (file, _program, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + let (file, _program, _, gs, _) = + compile_test_file("src/test_data/goto_def_test/goto_def.k"); let mut expected_path = path; expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); @@ -360,7 +361,7 @@ mod tests { #[test] #[bench_test] fn schema_doc_hover_test1() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/hover.k"); let pos = KCLPos { filename: file.clone(), @@ -388,7 +389,7 @@ mod tests { #[test] #[bench_test] fn schema_attr_hover_test() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/hover.k"); let pos = KCLPos { filename: file.clone(), @@ -432,7 +433,7 @@ mod tests { #[test] #[bench_test] fn lambda_doc_hover_test() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/lambda.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/lambda.k"); let pos = KCLPos { filename: file.clone(), @@ -457,7 +458,7 @@ mod tests { #[test] #[bench_test] fn func_def_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/hover.k"); let pos = KCLPos { filename: file.clone(), @@ -532,7 +533,7 @@ mod tests { #[test] #[bench_test] fn complex_select_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/fib.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/fib.k"); let pos = KCLPos { filename: file.clone(), line: 14, @@ -552,7 +553,8 @@ mod tests { #[test] #[bench_test] fn assignment_ty_in_lambda_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/ty_in_lambda.k"); + let (file, _program, _, gs, _) = + compile_test_file("src/test_data/hover_test/ty_in_lambda.k"); let pos = KCLPos { filename: file.clone(), line: 3, @@ -572,7 +574,7 @@ mod tests { #[test] #[bench_test] fn str_var_func_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/hover.k"); let pos = KCLPos { filename: file.clone(), line: 28, @@ -599,7 +601,7 @@ mod tests { #[test] #[bench_test] fn import_pkg_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/import_pkg.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/import_pkg.k"); let pos = KCLPos { filename: file.clone(), line: 3, @@ -623,7 +625,7 @@ mod tests { #[test] #[bench_test] fn expr_after_config_if_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/hover.k"); let pos = KCLPos { filename: file.clone(), line: 41, @@ -643,7 +645,7 @@ mod tests { #[test] #[bench_test] fn schema_scope_variable_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/fib.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/fib.k"); let pos = KCLPos { filename: file.clone(), line: 3, @@ -663,7 +665,7 @@ mod tests { #[test] #[bench_test] fn decorator_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/decorator.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/decorator.k"); let pos = KCLPos { filename: file.clone(), line: 1, @@ -703,7 +705,7 @@ mod tests { #[test] #[bench_test] fn inherit_schema_attr_hover() { - let (file, _program, _, gs) = compile_test_file("src/test_data/hover_test/inherit.k"); + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/inherit.k"); let pos = KCLPos { filename: file.clone(), line: 5, @@ -731,7 +733,7 @@ mod tests { #[test] #[bench_test] fn dict_key_in_schema() { - let (file, _program, _, gs) = + let (file, _program, _, gs, _) = compile_test_file("src/test_data/hover_test/dict_key_in_schema/dict_key_in_schema.k"); let pos = KCLPos { filename: file.clone(), diff --git a/kclvm/tools/src/LSP/src/inlay_hints.rs b/kclvm/tools/src/LSP/src/inlay_hints.rs index f9a4817f2..11f8e7da4 100644 --- a/kclvm/tools/src/LSP/src/inlay_hints.rs +++ b/kclvm/tools/src/LSP/src/inlay_hints.rs @@ -146,7 +146,7 @@ mod tests { ($name:ident, $file:expr) => { #[test] fn $name() { - let (file, _, _, gs) = compile_test_file($file); + let (file, _, _, gs, _) = compile_test_file($file); let res = inlay_hints(&file, &gs); insta::assert_snapshot!(format!("{:#?}", res)); } diff --git a/kclvm/tools/src/LSP/src/quick_fix.rs b/kclvm/tools/src/LSP/src/quick_fix.rs index 80020012e..0810c04c2 100644 --- a/kclvm/tools/src/LSP/src/quick_fix.rs +++ b/kclvm/tools/src/LSP/src/quick_fix.rs @@ -177,7 +177,12 @@ mod tests { fn quick_fix_test() { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let test_file = path.clone(); - let test_file = test_file.join("src").join("test_data").join("quick_fix.k"); + let test_file = test_file + .join("src") + .join("test_data") + .join("code_action") + .join("quick_fix") + .join("quick_fix.k"); let file = test_file.to_str().unwrap(); let diags = compile_with_params(Params { diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index a854ecc46..3e43655a8 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -357,6 +357,7 @@ pub(crate) fn handle_completion( &db.gs, &*snapshot.tool.read(), metadata, + &db.schema_map, ); if res.is_none() { diff --git a/kclvm/tools/src/LSP/src/semantic_token.rs b/kclvm/tools/src/LSP/src/semantic_token.rs index 90371bddc..f5b33db61 100644 --- a/kclvm/tools/src/LSP/src/semantic_token.rs +++ b/kclvm/tools/src/LSP/src/semantic_token.rs @@ -167,7 +167,7 @@ mod tests { #[test] #[bench_test] fn semantic_tokens_full_test() { - let (file, _, _, gs) = compile_test_file("src/test_data/sema_token/sema_token.k"); + let (file, _, _, gs, _) = compile_test_file("src/test_data/sema_token/sema_token.k"); let res = semantic_tokens_full(&file, &gs); if let Some(tokens) = res { match &tokens { diff --git a/kclvm/tools/src/LSP/src/signature_help.rs b/kclvm/tools/src/LSP/src/signature_help.rs index b356e9942..a3934db60 100644 --- a/kclvm/tools/src/LSP/src/signature_help.rs +++ b/kclvm/tools/src/LSP/src/signature_help.rs @@ -153,7 +153,7 @@ mod tests { ($name:ident, $file:expr, $line:expr, $column: expr, $trigger_character: expr) => { #[test] fn $name() { - let (file, _program, _, gs) = compile_test_file($file); + let (file, _program, _, gs, _) = compile_test_file($file); let pos = KCLPos { filename: file.clone(), diff --git a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__completion__tests__complete_unimport_schemas.snap b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__completion__tests__complete_unimport_schemas.snap new file mode 100644 index 000000000..2c22b7558 --- /dev/null +++ b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__completion__tests__complete_unimport_schemas.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/LSP/src/completion.rs +expression: "format! (\"{:?}\", got_labels)" +--- +["Name{}(import pkg)", "SubPKg{}(import subpkg)"] diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index a74ba395b..f94417079 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -39,6 +39,7 @@ pub(crate) enum Task { Notify(lsp_server::Notification), Retry(Request), ChangedFile(FileId, ChangeKind), + ReOpenFile(FileId, ChangeKind), } #[derive(Debug, Clone)] @@ -312,7 +313,7 @@ impl LanguageServerState { for (workspace, state) in state_workspaces.iter() { match state { DBState::Ready(db) => { - if db.prog.get_module(&filename).unwrap_or(None).is_some() { + if db.prog.modules.get(&filename).is_some() { let mut openfiles = self.opened_files.write(); let file_info = openfiles.get_mut(&file.file_id).unwrap(); file_info.workspaces.insert(workspace.clone()); @@ -421,10 +422,16 @@ impl LanguageServerState { self.async_compile(workspace, opts, Some(file.file_id), true); } - None => self.log_message(format!( - "Internal Bug: not found any workspace for file {:?}", - filename - )), + None => { + self.log_message(format!( + "Internal Bug: not found any workspace for file {:?}. Try to reload", + filename + )); + + self.task_sender + .send(Task::ReOpenFile(file.file_id, ChangeKind::Create)) + .unwrap(); + } } } } @@ -475,6 +482,10 @@ impl LanguageServerState { change_kind, }) } + Task::ReOpenFile(file_id, change_kind) => self.process_changed_file(ChangedFile { + file_id, + change_kind, + }), } Ok(()) } @@ -703,7 +714,7 @@ impl LanguageServerState { } match compile_res { - Ok((prog, gs)) => { + Ok((prog, schema_map, gs)) => { let mut workspaces = snapshot.workspaces.write(); log_message( format!( @@ -713,7 +724,7 @@ impl LanguageServerState { ); workspaces.insert( workspace.clone(), - DBState::Ready(Arc::new(AnalysisDatabase { prog, gs, diags })), + DBState::Ready(Arc::new(AnalysisDatabase { prog, gs, diags,schema_map })), ); drop(workspaces); if temp && changed_file_id.is_some() { diff --git a/kclvm/tools/src/LSP/src/test_data/load_pkg_test.k b/kclvm/tools/src/LSP/src/test_data/code_action/quick_fix/load_pkg_test.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/load_pkg_test.k rename to kclvm/tools/src/LSP/src/test_data/code_action/quick_fix/load_pkg_test.k diff --git a/kclvm/tools/src/LSP/src/test_data/quick_fix.k b/kclvm/tools/src/LSP/src/test_data/code_action/quick_fix/quick_fix.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/quick_fix.k rename to kclvm/tools/src/LSP/src/test_data/code_action/quick_fix/quick_fix.k diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/completion.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion.k rename to kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/completion.k diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/pkg/file1.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/pkg/file1.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/completion_test/dot/pkg/file1.k rename to kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/pkg/file1.k diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/pkg/file2.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/pkg/file2.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/completion_test/dot/pkg/file2.k rename to kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/pkg/file2.k diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/pkg/subpkg/file1.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/pkg/subpkg/file1.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/completion_test/dot/pkg/subpkg/file1.k rename to kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion/pkg/subpkg/file1.k diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema.k b/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema/schema.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema.k rename to kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema/schema.k diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/pkg/kcl.mod b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/pkg/kcl.mod new file mode 100644 index 000000000..950182eb1 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/pkg/kcl.mod @@ -0,0 +1,6 @@ +[package] +name = "pkg" +edition = "v0.9.0" +version = "0.0.1" + + diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/pkg/main.k b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/pkg/main.k new file mode 100644 index 000000000..ac99847b1 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/pkg/main.k @@ -0,0 +1,2 @@ +schema Name: + name: str \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/kcl.mod b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/kcl.mod new file mode 100644 index 000000000..c78a893dd --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "unimport" +edition = "v0.9.0" +version = "0.0.1" + +[dependencies] +pkg = { path = "../pkg" } \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/main.k b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/main.k new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/subpkg/subpkg.k b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/subpkg/subpkg.k new file mode 100644 index 000000000..9dfbc5485 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/unimport/unimport/subpkg/subpkg.k @@ -0,0 +1,2 @@ +schema SubPKg: + name: str \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/diagnostics.k b/kclvm/tools/src/LSP/src/test_data/diagnostics/diagnostics.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/diagnostics.k rename to kclvm/tools/src/LSP/src/test_data/diagnostics/diagnostics.k diff --git a/kclvm/tools/src/LSP/src/test_data/diagnostics/load_pkg_test.k b/kclvm/tools/src/LSP/src/test_data/diagnostics/load_pkg_test.k new file mode 100644 index 000000000..52fa61550 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/diagnostics/load_pkg_test.k @@ -0,0 +1,2 @@ +schema Person: + age: int \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/document_symbol.k b/kclvm/tools/src/LSP/src/test_data/document_symbol/document_symbol.k similarity index 100% rename from kclvm/tools/src/LSP/src/test_data/document_symbol.k rename to kclvm/tools/src/LSP/src/test_data/document_symbol/document_symbol.k diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index 6de2d1dd9..d035748ef 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -1,11 +1,13 @@ use crossbeam_channel::after; use crossbeam_channel::select; +use indexmap::IndexMap; use indexmap::IndexSet; use kclvm_driver::lookup_compile_workspace; use kclvm_driver::toolchain; use kclvm_driver::toolchain::Metadata; use kclvm_driver::WorkSpaceKind; use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::ty::SchemaType; use kclvm_utils::path::PathPrefix; use kclvm_sema::resolver::scope::KCLScopeCache; @@ -131,7 +133,13 @@ pub(crate) fn compare_goto_res( pub(crate) fn compile_test_file( testfile: &str, -) -> (String, Program, IndexSet, GlobalState) { +) -> ( + String, + Program, + IndexSet, + GlobalState, + IndexMap>, +) { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let file = path .join(testfile) @@ -148,8 +156,8 @@ pub(crate) fn compile_test_file( vfs: Some(KCLVfs::default()), gs_cache: Some(KCLGlobalStateCache::default()), }); - let (program, gs) = compile_res.unwrap(); - (file, program, diags, gs) + let (program, schema_map, gs) = compile_res.unwrap(); + (file, program, diags, gs, schema_map) } pub(crate) fn compile_test_file_and_metadata( @@ -160,6 +168,7 @@ pub(crate) fn compile_test_file_and_metadata( IndexSet, GlobalState, Option, + IndexMap>, ) { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -179,9 +188,9 @@ pub(crate) fn compile_test_file_and_metadata( vfs: Some(KCLVfs::default()), gs_cache: Some(KCLGlobalStateCache::default()), }); - let (program, gs) = compile_res.unwrap(); + let (program, schema_map, gs) = compile_res.unwrap(); - (file, program, diags, gs, metadata) + (file, program, diags, gs, metadata, schema_map) } type Info = (String, (u32, u32, u32, u32), String); @@ -244,7 +253,7 @@ fn build_lsp_diag( fn build_expect_diags() -> Vec { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut test_file = path.clone(); - test_file.push("src/test_data/diagnostics.k"); + test_file.push("src/test_data/diagnostics/diagnostics.k"); let file = test_file.to_str().unwrap(); let expected_diags: Vec = vec![ build_lsp_diag( @@ -267,7 +276,7 @@ fn build_expect_diags() -> Vec { build_lsp_diag( (0, 0, 0, 10), format!( - "Cannot find the module abc from {}/src/test_data/abc", + "Cannot find the module abc from {}/src/test_data/diagnostics/abc", path.to_str().unwrap() ), Some(DiagnosticSeverity::ERROR), @@ -332,7 +341,7 @@ fn build_expect_diags() -> Vec { fn diagnostics_test() { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut test_file = path.clone(); - test_file.push("src/test_data/diagnostics.k"); + test_file.push("src/test_data/diagnostics/diagnostics.k"); let file = test_file.to_str().unwrap(); let diags = compile_with_params(Params { @@ -350,6 +359,7 @@ fn diagnostics_test() { .collect::>(); let expected_diags: Vec = build_expect_diags(); + for (get, expected) in diagnostics.iter().zip(expected_diags.iter()) { assert_eq!(get, expected) } @@ -463,7 +473,7 @@ fn test_lsp_with_kcl_mod_in_order() { fn goto_import_pkg_with_line_test() { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let (file, _program, _, gs) = + let (file, _program, _, gs, _) = compile_test_file("src/test_data/goto_def_with_line_test/main_pkg/main.k"); let pos = KCLPos { filename: file.adjust_canonicalization(), @@ -525,7 +535,7 @@ fn complete_import_external_file_test() { .output() .unwrap(); - let (program, gs) = compile_with_params(Params { + let (program, schema_map, gs) = compile_with_params(Params { file: Some(path.to_string()), module_cache: None, scope_cache: None, @@ -541,7 +551,7 @@ fn complete_import_external_file_test() { column: Some(11), }; let tool = toolchain::default(); - let res = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let res = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match &res { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), @@ -592,7 +602,7 @@ fn goto_import_external_file_test() { vfs: Some(KCLVfs::default()), gs_cache: Some(KCLGlobalStateCache::default()), }); - let gs = compile_res.unwrap().1; + let gs = compile_res.unwrap().2; assert_eq!(diags.len(), 0); @@ -764,7 +774,7 @@ fn notification_test() { let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut path = root.clone(); - path.push("src/test_data/diagnostics.k"); + path.push("src/test_data/diagnostics/diagnostics.k"); let path = path.to_str().unwrap(); let src = std::fs::read_to_string(path).unwrap(); @@ -783,7 +793,7 @@ fn notification_test() { ); // Wait for first "textDocument/publishDiagnostics" notification - server.wait_for_message_cond(2, &|msg: &Message| match msg { + server.wait_for_message_cond(1, &|msg: &Message| match msg { Message::Notification(not) => not.method == "textDocument/publishDiagnostics", _ => false, }); @@ -817,7 +827,7 @@ fn close_file_test() { let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut path = root.clone(); - path.push("src/test_data/diagnostics.k"); + path.push("src/test_data/diagnostics/diagnostics.k"); let path = path.to_str().unwrap(); let src = std::fs::read_to_string(path).unwrap(); @@ -1012,6 +1022,7 @@ fn complete_test() { .join("test_data") .join("completion_test") .join("dot") + .join("completion") .join("completion.k"); let path = path.to_str().unwrap(); @@ -1416,19 +1427,19 @@ fn formatting_unsaved_test() { #[test] fn complete_import_external_file_e2e_test() { - let path = PathBuf::from(".") + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("src") .join("test_data") .join("completion_test") .join("import") .join("external") - .join("external_1") + .join("external_1"); + let path = root .join("main.k") .canonicalize() .unwrap() .display() .to_string(); - let _ = Command::new("kcl") .arg("mod") .arg("metadata") @@ -1448,8 +1459,21 @@ fn complete_import_external_file_e2e_test() { ) .output() .unwrap(); + let src = std::fs::read_to_string(path.clone()).unwrap(); - let server = Project {}.server(InitializeParams::default()); + + let initialize_params = InitializeParams { + workspace_folders: Some(vec![WorkspaceFolder { + uri: Url::from_file_path(root.clone()).unwrap(), + name: "test".to_string(), + }]), + ..Default::default() + }; + let server = Project {}.server(initialize_params); + + // FIXME: It takes longer to parse the k8s package on Windows + #[cfg(target_os = "windows")] + wait_async!(20000); // Mock open file server.notification::( @@ -1462,6 +1486,7 @@ fn complete_import_external_file_e2e_test() { }, }, ); + wait_async!(2000); let id = server.next_request_id.get(); server.next_request_id.set(id.wrapping_add(1)); @@ -1615,7 +1640,7 @@ fn konfig_goto_def_test_base() { .join("base") .join("base.k"); let base_path_str = base_path.to_str().unwrap().to_string(); - let (_program, gs) = compile_with_params(Params { + let (_program, _, gs) = compile_with_params(Params { file: Some(base_path_str.clone()), module_cache: None, scope_cache: None, @@ -1747,7 +1772,7 @@ fn konfig_goto_def_test_main() { .join("dev") .join("main.k"); let main_path_str = main_path.to_str().unwrap().to_string(); - let (_program, gs) = compile_with_params(Params { + let (_program, _, gs) = compile_with_params(Params { file: Some(main_path_str.clone()), module_cache: None, scope_cache: None, @@ -1834,7 +1859,7 @@ fn konfig_completion_test_main() { .join("dev") .join("main.k"); let main_path_str = main_path.to_str().unwrap().to_string(); - let (program, gs) = compile_with_params(Params { + let (program, schema_map, gs) = compile_with_params(Params { file: Some(main_path_str.clone()), module_cache: None, scope_cache: None, @@ -1851,7 +1876,7 @@ fn konfig_completion_test_main() { column: Some(27), }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1870,7 +1895,7 @@ fn konfig_completion_test_main() { column: Some(4), }; let tool = toolchain::default(); - let got = completion(None, &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(None, &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let mut got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1915,7 +1940,7 @@ fn konfig_completion_test_main() { column: Some(35), }; let tool = toolchain::default(); - let got = completion(Some('.'), &program, &pos, &gs, &tool, None).unwrap(); + let got = completion(Some('.'), &program, &pos, &gs, &tool, None, &schema_map).unwrap(); let mut got_labels: Vec = match got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), @@ -1953,7 +1978,7 @@ fn konfig_hover_test_main() { .join("main.k"); let main_path_str = main_path.to_str().unwrap().to_string(); - let (_program, gs) = compile_with_params(Params { + let (_program, _, gs) = compile_with_params(Params { file: Some(main_path_str.clone()), module_cache: None, scope_cache: None, @@ -2648,17 +2673,14 @@ fn init_workspace_sema_token_test() { #[test] fn pkg_mod_test() { - let (_file, _program, diags, _gs) = + let (_file, _program, diags, _gs, _) = compile_test_file("src/test_data/workspace/pkg_mod_test/test/main.k"); - for diag in diags.iter().filter(|diag| diag.is_error()) { - println!("{:?}", diag); - } assert_eq!(diags.iter().filter(|diag| diag.is_error()).count(), 0); } #[test] fn aug_assign_without_define() { - let (_file, _program, diags, _gs) = + let (_file, _program, diags, _gs, _) = compile_test_file("src/test_data/error_code/aug_assign/aug_assign.k"); assert_eq!(diags.len(), 1); }