diff --git a/kclvm/sema/src/resolver/import.rs b/kclvm/sema/src/resolver/import.rs index 1b9c67ffd..e3901fa1b 100644 --- a/kclvm/sema/src/resolver/import.rs +++ b/kclvm/sema/src/resolver/import.rs @@ -205,6 +205,7 @@ impl<'ctx> Resolver<'ctx> { if pkgpath.is_empty() { return; } + if !self.scope_map.contains_key(pkgpath) { let scope = Rc::new(RefCell::new(Scope { parent: Some(Rc::downgrade(&self.builtin_scope)), @@ -212,7 +213,7 @@ impl<'ctx> Resolver<'ctx> { elems: IndexMap::default(), start: Position::dummy_pos(), end: Position::dummy_pos(), - kind: ScopeKind::Package, + kind: ScopeKind::Package(vec![]), })); self.scope_map .insert(pkgpath.to_string(), Rc::clone(&scope)); @@ -220,6 +221,10 @@ impl<'ctx> Resolver<'ctx> { } self.ctx.pkgpath = pkgpath.to_string(); self.ctx.filename = filename.to_string(); - self.scope = self.scope_map.get(pkgpath).unwrap().clone(); + let scope = self.scope_map.get(pkgpath).unwrap().clone(); + if let ScopeKind::Package(files) = &mut scope.borrow_mut().kind { + files.push(filename.to_string()) + } + self.scope = scope; } } diff --git a/kclvm/sema/src/resolver/scope.rs b/kclvm/sema/src/resolver/scope.rs index 5e513d198..045bd082f 100644 --- a/kclvm/sema/src/resolver/scope.rs +++ b/kclvm/sema/src/resolver/scope.rs @@ -42,6 +42,12 @@ impl ScopeObject { } } +impl ContainsPos for ScopeObject { + fn contains_pos(&self, pos: &Position) -> bool { + self.start.less_equal(pos) && pos.less_equal(&self.end) + } +} + #[derive(PartialEq, Clone, Debug)] pub enum ScopeObjectKind { Variable, @@ -106,14 +112,27 @@ impl Scope { impl ContainsPos for Scope { /// Check if current scope contains a position fn contains_pos(&self, pos: &Position) -> bool { - self.start.less_equal(pos) && pos.less_equal(&self.end) + match &self.kind { + ScopeKind::Package(files) => { + if files.contains(&pos.filename) { + self.children.iter().any(|s| s.borrow().contains_pos(pos)) + || self + .elems + .iter() + .any(|(_, child)| child.borrow().contains_pos(pos)) + } else { + false + } + } + _ => self.start.less_equal(pos) && pos.less_equal(&self.end), + } } } #[derive(Clone, Debug)] pub enum ScopeKind { /// Package scope. - Package, + Package(Vec<String>), /// Builtin scope. Builtin, /// Schema name string. diff --git a/kclvm/sema/src/resolver/test_data/pkg_scope.k b/kclvm/sema/src/resolver/test_data/pkg_scope.k new file mode 100644 index 000000000..91667ad12 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/pkg_scope.k @@ -0,0 +1,3 @@ +import pkg +schema Person1: + name: str \ No newline at end of file diff --git a/kclvm/sema/src/resolver/tests.rs b/kclvm/sema/src/resolver/tests.rs index f46a0cb87..ea21a9907 100644 --- a/kclvm/sema/src/resolver/tests.rs +++ b/kclvm/sema/src/resolver/tests.rs @@ -6,6 +6,7 @@ use crate::resolver::resolve_program; use crate::resolver::scope::*; use crate::ty::{Type, TypeKind}; use kclvm_ast::ast; +use kclvm_ast::pos::ContainsPos; use kclvm_error::*; use kclvm_parser::ParseSession; use kclvm_parser::{load_program, parse_program}; @@ -372,3 +373,67 @@ See also: kusion_models/core/v1/metadata.k." attrs_scope.get("labels").unwrap().borrow().doc ); } + +#[test] +fn test_pkg_scope() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/pkg_scope.k"], + None, + ) + .unwrap(); + let scope = resolve_program(&mut program); + + assert_eq!(scope.scope_map.len(), 2); + let main_scope = scope + .scope_map + .get(kclvm_runtime::MAIN_PKG_PATH) + .unwrap() + .borrow_mut() + .clone(); + let pkg_scope = scope.scope_map.get("pkg").unwrap().borrow_mut().clone(); + + let root = &program.root.clone(); + let filename = Path::new(&root.clone()) + .join("pkg_scope.k") + .display() + .to_string(); + + let pos = Position { + filename: filename.clone(), + line: 2, + column: Some(0), + }; + + assert!(main_scope.contains_pos(&pos)); + + let pos = Position { + filename: filename.clone(), + line: 10, + column: Some(0), + }; + assert!(!main_scope.contains_pos(&pos)); + + let filename = Path::new(&root.clone()) + .join("pkg") + .join("pkg.k") + .display() + .to_string(); + + let pos = Position { + filename: filename.clone(), + line: 4, + column: Some(0), + }; + + assert!(pkg_scope.contains_pos(&pos)); + + let pos = Position { + filename: filename.clone(), + line: 10, + column: Some(0), + }; + + assert!(!pkg_scope.contains_pos(&pos)); +}