Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/expr_store/scope.rs')
| -rw-r--r-- | crates/hir-def/src/expr_store/scope.rs | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/crates/hir-def/src/expr_store/scope.rs b/crates/hir-def/src/expr_store/scope.rs index 1952dae9d7..43ce053836 100644 --- a/crates/hir-def/src/expr_store/scope.rs +++ b/crates/hir-def/src/expr_store/scope.rs @@ -4,7 +4,7 @@ use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx}; use triomphe::Arc; use crate::{ - BlockId, DefWithBodyId, + BlockId, DefWithBodyId, ExpressionStoreOwner, GenericDefId, db::DefDatabase, expr_store::{Body, ExpressionStore, HygieneId}, hir::{Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement}, @@ -51,13 +51,37 @@ pub struct ScopeData { } impl ExprScopes { - pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> { + pub(crate) fn expr_scopes_query( + db: &dyn DefDatabase, + def: ExpressionStoreOwner, + ) -> Arc<ExprScopes> { + match def { + ExpressionStoreOwner::Body(def) => db.body_expr_scopes(def), + ExpressionStoreOwner::Signature(def) => db.sig_expr_scopes(def), + } + } + + pub(crate) fn body_expr_scopes_query( + db: &dyn DefDatabase, + def: DefWithBodyId, + ) -> Arc<ExprScopes> { let body = db.body(def); let mut scopes = ExprScopes::new_body(&body); scopes.shrink_to_fit(); Arc::new(scopes) } + pub(crate) fn sig_expr_scopes_query( + db: &dyn DefDatabase, + def: GenericDefId, + ) -> Arc<ExprScopes> { + let (_, store) = db.generic_params_and_store(def); + let roots = store.signature_const_expr_roots(); + let mut scopes = ExprScopes::new_store(&store, roots); + scopes.shrink_to_fit(); + Arc::new(scopes) + } + pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { &self.scope_entries[self.scopes[scope].entries.clone()] } @@ -119,6 +143,22 @@ impl ExprScopes { scopes } + fn new_store(store: &ExpressionStore, roots: impl IntoIterator<Item = ExprId>) -> ExprScopes { + let mut scopes = ExprScopes { + scopes: Arena::default(), + scope_entries: Arena::default(), + scope_by_expr: ArenaMap::with_capacity( + store.expr_only.as_ref().map_or(0, |it| it.exprs.len()), + ), + }; + let root = scopes.root_scope(); + for root_expr in roots { + let mut scope = scopes.new_scope(root); + compute_expr_scopes(root_expr, store, &mut scopes, &mut scope); + } + scopes + } + fn root_scope(&mut self) -> ScopeId { self.scopes.alloc(ScopeData { parent: None, @@ -327,7 +367,8 @@ mod tests { use test_utils::{assert_eq_text, extract_offset}; use crate::{ - FunctionId, ModuleDefId, db::DefDatabase, nameres::crate_def_map, test_db::TestDB, + DefWithBodyId, FunctionId, ModuleDefId, db::DefDatabase, nameres::crate_def_map, + test_db::TestDB, }; fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { @@ -363,7 +404,7 @@ mod tests { let marker: ast::PathExpr = find_node_at_offset(&file_syntax, offset).unwrap(); let function = find_function(&db, file_id); - let scopes = db.expr_scopes(function.into()); + let scopes = db.expr_scopes(DefWithBodyId::from(function).into()); let (_body, source_map) = db.body_with_source_map(function.into()); let expr_id = source_map @@ -522,7 +563,7 @@ fn foo() { let function = find_function(&db, file_id); - let scopes = db.expr_scopes(function.into()); + let scopes = db.expr_scopes(DefWithBodyId::from(function).into()); let (_, source_map) = db.body_with_source_map(function.into()); let expr_scope = { |