From a04177f135be89ddbf1788c6f747c26812e90438 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 11:19:09 +0100 Subject: Add local functions to bodies --- Cargo.lock | 1 + crates/ra_hir/src/from_source.rs | 11 ++++++--- crates/ra_hir_def/Cargo.toml | 1 + crates/ra_hir_def/src/body.rs | 43 ++++++++++++++++++++++-------------- crates/ra_hir_def/src/body/lower.rs | 24 ++++++++++++++++++-- crates/ra_ide/src/goto_definition.rs | 17 ++++++++++++++ 6 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7a5108a4..3f2cbc8ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -957,6 +957,7 @@ name = "ra_hir_def" version = "0.1.0" dependencies = [ "anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 7abb4bd75..b3ed88b6b 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,8 +1,8 @@ //! FIXME: write short doc here use hir_def::{ child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, - ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, UnionId, VariantId, + ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, + StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -227,7 +227,12 @@ fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option ast::ImplBlock(it) => { let c = ImplBlock::from_source(db, src.with_value(it))?; c.id.child_by_source(db) - }, + }, + ast::FnDef(it) => { + let f = Function::from_source(db, src.with_value(it))?; + DefWithBodyId::from(f.id) + .child_by_source(db) + }, _ => { continue }, } }; diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index b1923bbf2..2c368f690 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml @@ -13,6 +13,7 @@ once_cell = "1.0.1" rustc-hash = "1.0" either = "1.5" anymap = "0.12" +drop_bomb = "0.1.4" ra_arena = { path = "../ra_arena" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 332c509e1..92c32b080 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -3,10 +3,13 @@ mod lower; pub mod scope; -use std::{ops::Index, sync::Arc}; +use std::{mem, ops::Index, sync::Arc}; +use drop_bomb::DropBomb; use either::Either; -use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; +use hir_expand::{ + ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, +}; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -24,6 +27,7 @@ struct Expander { crate_def_map: Arc, current_file_id: HirFileId, hygiene: Hygiene, + ast_id_map: Arc, module: ModuleId, } @@ -31,7 +35,8 @@ impl Expander { fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { let crate_def_map = db.crate_def_map(module.krate); let hygiene = Hygiene::new(db, current_file_id); - Expander { crate_def_map, current_file_id, hygiene, module } + let ast_id_map = db.ast_id_map(current_file_id); + Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } } fn enter_expand( @@ -52,9 +57,14 @@ impl Expander { if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); - let mark = Mark { file_id: self.current_file_id }; + let mark = Mark { + file_id: self.current_file_id, + ast_id_map: mem::take(&mut self.ast_id_map), + bomb: DropBomb::new("expansion mark dropped"), + }; self.hygiene = Hygiene::new(db, file_id); self.current_file_id = file_id; + self.ast_id_map = db.ast_id_map(file_id); return Some((mark, expr)); } @@ -67,10 +77,11 @@ impl Expander { None } - fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { + fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { self.hygiene = Hygiene::new(db, mark.file_id); self.current_file_id = mark.file_id; - std::mem::forget(mark); + self.ast_id_map = mem::take(&mut mark.ast_id_map); + mark.bomb.defuse(); } fn to_source(&self, value: T) -> InFile { @@ -91,18 +102,17 @@ impl Expander { .0 .take_macros() } + + fn ast_id(&self, item: &N) -> AstId { + let file_local_id = self.ast_id_map.ast_id(item); + AstId::new(self.current_file_id, file_local_id) + } } struct Mark { file_id: HirFileId, -} - -impl Drop for Mark { - fn drop(&mut self) { - if !std::thread::panicking() { - panic!("dropped mark") - } - } + ast_id_map: Arc, + bomb: DropBomb, } /// The body of an item (function, const etc.). @@ -174,7 +184,7 @@ impl Body { } }; let expander = Expander::new(db, file_id, module); - let (body, source_map) = Body::new(db, expander, params, body); + let (body, source_map) = Body::new(db, def, expander, params, body); (Arc::new(body), Arc::new(source_map)) } @@ -184,11 +194,12 @@ impl Body { fn new( db: &impl DefDatabase, + def: DefWithBodyId, expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { - lower::lower(db, expander, params, body) + lower::lower(db, def, expander, params, body) } } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 86960186f..17efa10e2 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -2,11 +2,12 @@ //! representation. use either::Either; + use hir_expand::name::{name, AsName, Name}; use ra_arena::Arena; use ra_syntax::{ ast::{ - self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, + self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, TypeAscriptionOwner, }, AstNode, AstPtr, @@ -24,17 +25,20 @@ use crate::{ path::GenericArgs, path::Path, type_ref::{Mutability, TypeRef}, + ContainerId, DefWithBodyId, FunctionLoc, Intern, }; pub(super) fn lower( db: &impl DefDatabase, + def: DefWithBodyId, expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { ExprCollector { - expander, db, + def, + expander, source_map: BodySourceMap::default(), body: Body { exprs: Arena::default(), @@ -49,6 +53,7 @@ pub(super) fn lower( struct ExprCollector { db: DB, + def: DefWithBodyId, expander: Expander, body: Body, @@ -467,6 +472,7 @@ where Some(block) => block, None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), }; + self.collect_block_items(&block); let statements = block .statements() .map(|s| match s { @@ -483,6 +489,20 @@ where self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) } + fn collect_block_items(&mut self, block: &ast::Block) { + let container = ContainerId::DefWithBodyId(self.def); + for item in block.items() { + match item { + ast::ModuleItem::FnDef(def) => { + let ast_id = self.expander.ast_id(&def); + self.body.defs.push(FunctionLoc { container, ast_id }.intern(self.db).into()) + } + // FIXME: handle other items + _ => (), + } + } + } + fn collect_block_opt(&mut self, expr: Option) -> ExprId { if let Some(block) = expr { self.collect_block(block) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 184555792..ee4ae3e03 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -858,4 +858,21 @@ mod tests { "y", ); } + + #[test] + fn goto_def_in_local_fn() { + check_goto( + " + //- /lib.rs + fn main() { + fn foo() { + let x = 92; + <|>x; + } + } + ", + "x BIND_PAT FileId(1) [39; 40)", + "x", + ); + } } -- cgit v1.2.3