diff options
| author | Aleksey Kladov <[email protected]> | 2019-12-20 10:19:09 +0000 |
|---|---|---|
| committer | Aleksey Kladov <[email protected]> | 2019-12-20 10:52:17 +0000 |
| commit | a04177f135be89ddbf1788c6f747c26812e90438 (patch) | |
| tree | f2dbdf832caab0448427641b6a93ae3c66465c12 /crates | |
| parent | 08c6933104baca84fd4135a76cdc7daf60a0c631 (diff) | |
Add local functions to bodies
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/ra_hir/src/from_source.rs | 11 | ||||
| -rw-r--r-- | crates/ra_hir_def/Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/ra_hir_def/src/body.rs | 43 | ||||
| -rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 24 | ||||
| -rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 17 |
5 files changed, 75 insertions, 21 deletions
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 @@ | |||
| 1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
| 2 | use hir_def::{ | 2 | use hir_def::{ |
| 3 | child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, | 3 | child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, |
| 4 | ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId, | 4 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, |
| 5 | TraitId, TypeAliasId, UnionId, VariantId, | 5 | StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, |
| 6 | }; | 6 | }; |
| 7 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; | 7 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; |
| 8 | use ra_syntax::{ | 8 | use ra_syntax::{ |
| @@ -227,7 +227,12 @@ fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option | |||
| 227 | ast::ImplBlock(it) => { | 227 | ast::ImplBlock(it) => { |
| 228 | let c = ImplBlock::from_source(db, src.with_value(it))?; | 228 | let c = ImplBlock::from_source(db, src.with_value(it))?; |
| 229 | c.id.child_by_source(db) | 229 | c.id.child_by_source(db) |
| 230 | }, | 230 | }, |
| 231 | ast::FnDef(it) => { | ||
| 232 | let f = Function::from_source(db, src.with_value(it))?; | ||
| 233 | DefWithBodyId::from(f.id) | ||
| 234 | .child_by_source(db) | ||
| 235 | }, | ||
| 231 | _ => { continue }, | 236 | _ => { continue }, |
| 232 | } | 237 | } |
| 233 | }; | 238 | }; |
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" | |||
| 13 | rustc-hash = "1.0" | 13 | rustc-hash = "1.0" |
| 14 | either = "1.5" | 14 | either = "1.5" |
| 15 | anymap = "0.12" | 15 | anymap = "0.12" |
| 16 | drop_bomb = "0.1.4" | ||
| 16 | 17 | ||
| 17 | ra_arena = { path = "../ra_arena" } | 18 | ra_arena = { path = "../ra_arena" } |
| 18 | ra_db = { path = "../ra_db" } | 19 | 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 @@ | |||
| 3 | mod lower; | 3 | mod lower; |
| 4 | pub mod scope; | 4 | pub mod scope; |
| 5 | 5 | ||
| 6 | use std::{ops::Index, sync::Arc}; | 6 | use std::{mem, ops::Index, sync::Arc}; |
| 7 | 7 | ||
| 8 | use drop_bomb::DropBomb; | ||
| 8 | use either::Either; | 9 | use either::Either; |
| 9 | use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; | 10 | use hir_expand::{ |
| 11 | ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, | ||
| 12 | }; | ||
| 10 | use ra_arena::{map::ArenaMap, Arena}; | 13 | use ra_arena::{map::ArenaMap, Arena}; |
| 11 | use ra_syntax::{ast, AstNode, AstPtr}; | 14 | use ra_syntax::{ast, AstNode, AstPtr}; |
| 12 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
| @@ -24,6 +27,7 @@ struct Expander { | |||
| 24 | crate_def_map: Arc<CrateDefMap>, | 27 | crate_def_map: Arc<CrateDefMap>, |
| 25 | current_file_id: HirFileId, | 28 | current_file_id: HirFileId, |
| 26 | hygiene: Hygiene, | 29 | hygiene: Hygiene, |
| 30 | ast_id_map: Arc<AstIdMap>, | ||
| 27 | module: ModuleId, | 31 | module: ModuleId, |
| 28 | } | 32 | } |
| 29 | 33 | ||
| @@ -31,7 +35,8 @@ impl Expander { | |||
| 31 | fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { | 35 | fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { |
| 32 | let crate_def_map = db.crate_def_map(module.krate); | 36 | let crate_def_map = db.crate_def_map(module.krate); |
| 33 | let hygiene = Hygiene::new(db, current_file_id); | 37 | let hygiene = Hygiene::new(db, current_file_id); |
| 34 | Expander { crate_def_map, current_file_id, hygiene, module } | 38 | let ast_id_map = db.ast_id_map(current_file_id); |
| 39 | Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } | ||
| 35 | } | 40 | } |
| 36 | 41 | ||
| 37 | fn enter_expand( | 42 | fn enter_expand( |
| @@ -52,9 +57,14 @@ impl Expander { | |||
| 52 | if let Some(expr) = ast::Expr::cast(node) { | 57 | if let Some(expr) = ast::Expr::cast(node) { |
| 53 | log::debug!("macro expansion {:#?}", expr.syntax()); | 58 | log::debug!("macro expansion {:#?}", expr.syntax()); |
| 54 | 59 | ||
| 55 | let mark = Mark { file_id: self.current_file_id }; | 60 | let mark = Mark { |
| 61 | file_id: self.current_file_id, | ||
| 62 | ast_id_map: mem::take(&mut self.ast_id_map), | ||
| 63 | bomb: DropBomb::new("expansion mark dropped"), | ||
| 64 | }; | ||
| 56 | self.hygiene = Hygiene::new(db, file_id); | 65 | self.hygiene = Hygiene::new(db, file_id); |
| 57 | self.current_file_id = file_id; | 66 | self.current_file_id = file_id; |
| 67 | self.ast_id_map = db.ast_id_map(file_id); | ||
| 58 | 68 | ||
| 59 | return Some((mark, expr)); | 69 | return Some((mark, expr)); |
| 60 | } | 70 | } |
| @@ -67,10 +77,11 @@ impl Expander { | |||
| 67 | None | 77 | None |
| 68 | } | 78 | } |
| 69 | 79 | ||
| 70 | fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { | 80 | fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { |
| 71 | self.hygiene = Hygiene::new(db, mark.file_id); | 81 | self.hygiene = Hygiene::new(db, mark.file_id); |
| 72 | self.current_file_id = mark.file_id; | 82 | self.current_file_id = mark.file_id; |
| 73 | std::mem::forget(mark); | 83 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
| 84 | mark.bomb.defuse(); | ||
| 74 | } | 85 | } |
| 75 | 86 | ||
| 76 | fn to_source<T>(&self, value: T) -> InFile<T> { | 87 | fn to_source<T>(&self, value: T) -> InFile<T> { |
| @@ -91,18 +102,17 @@ impl Expander { | |||
| 91 | .0 | 102 | .0 |
| 92 | .take_macros() | 103 | .take_macros() |
| 93 | } | 104 | } |
| 105 | |||
| 106 | fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> { | ||
| 107 | let file_local_id = self.ast_id_map.ast_id(item); | ||
| 108 | AstId::new(self.current_file_id, file_local_id) | ||
| 109 | } | ||
| 94 | } | 110 | } |
| 95 | 111 | ||
| 96 | struct Mark { | 112 | struct Mark { |
| 97 | file_id: HirFileId, | 113 | file_id: HirFileId, |
| 98 | } | 114 | ast_id_map: Arc<AstIdMap>, |
| 99 | 115 | bomb: DropBomb, | |
| 100 | impl Drop for Mark { | ||
| 101 | fn drop(&mut self) { | ||
| 102 | if !std::thread::panicking() { | ||
| 103 | panic!("dropped mark") | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | 116 | } |
| 107 | 117 | ||
| 108 | /// The body of an item (function, const etc.). | 118 | /// The body of an item (function, const etc.). |
| @@ -174,7 +184,7 @@ impl Body { | |||
| 174 | } | 184 | } |
| 175 | }; | 185 | }; |
| 176 | let expander = Expander::new(db, file_id, module); | 186 | let expander = Expander::new(db, file_id, module); |
| 177 | let (body, source_map) = Body::new(db, expander, params, body); | 187 | let (body, source_map) = Body::new(db, def, expander, params, body); |
| 178 | (Arc::new(body), Arc::new(source_map)) | 188 | (Arc::new(body), Arc::new(source_map)) |
| 179 | } | 189 | } |
| 180 | 190 | ||
| @@ -184,11 +194,12 @@ impl Body { | |||
| 184 | 194 | ||
| 185 | fn new( | 195 | fn new( |
| 186 | db: &impl DefDatabase, | 196 | db: &impl DefDatabase, |
| 197 | def: DefWithBodyId, | ||
| 187 | expander: Expander, | 198 | expander: Expander, |
| 188 | params: Option<ast::ParamList>, | 199 | params: Option<ast::ParamList>, |
| 189 | body: Option<ast::Expr>, | 200 | body: Option<ast::Expr>, |
| 190 | ) -> (Body, BodySourceMap) { | 201 | ) -> (Body, BodySourceMap) { |
| 191 | lower::lower(db, expander, params, body) | 202 | lower::lower(db, def, expander, params, body) |
| 192 | } | 203 | } |
| 193 | } | 204 | } |
| 194 | 205 | ||
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 @@ | |||
| 2 | //! representation. | 2 | //! representation. |
| 3 | 3 | ||
| 4 | use either::Either; | 4 | use either::Either; |
| 5 | |||
| 5 | use hir_expand::name::{name, AsName, Name}; | 6 | use hir_expand::name::{name, AsName, Name}; |
| 6 | use ra_arena::Arena; | 7 | use ra_arena::Arena; |
| 7 | use ra_syntax::{ | 8 | use ra_syntax::{ |
| 8 | ast::{ | 9 | ast::{ |
| 9 | self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, | 10 | self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, |
| 10 | TypeAscriptionOwner, | 11 | TypeAscriptionOwner, |
| 11 | }, | 12 | }, |
| 12 | AstNode, AstPtr, | 13 | AstNode, AstPtr, |
| @@ -24,17 +25,20 @@ use crate::{ | |||
| 24 | path::GenericArgs, | 25 | path::GenericArgs, |
| 25 | path::Path, | 26 | path::Path, |
| 26 | type_ref::{Mutability, TypeRef}, | 27 | type_ref::{Mutability, TypeRef}, |
| 28 | ContainerId, DefWithBodyId, FunctionLoc, Intern, | ||
| 27 | }; | 29 | }; |
| 28 | 30 | ||
| 29 | pub(super) fn lower( | 31 | pub(super) fn lower( |
| 30 | db: &impl DefDatabase, | 32 | db: &impl DefDatabase, |
| 33 | def: DefWithBodyId, | ||
| 31 | expander: Expander, | 34 | expander: Expander, |
| 32 | params: Option<ast::ParamList>, | 35 | params: Option<ast::ParamList>, |
| 33 | body: Option<ast::Expr>, | 36 | body: Option<ast::Expr>, |
| 34 | ) -> (Body, BodySourceMap) { | 37 | ) -> (Body, BodySourceMap) { |
| 35 | ExprCollector { | 38 | ExprCollector { |
| 36 | expander, | ||
| 37 | db, | 39 | db, |
| 40 | def, | ||
| 41 | expander, | ||
| 38 | source_map: BodySourceMap::default(), | 42 | source_map: BodySourceMap::default(), |
| 39 | body: Body { | 43 | body: Body { |
| 40 | exprs: Arena::default(), | 44 | exprs: Arena::default(), |
| @@ -49,6 +53,7 @@ pub(super) fn lower( | |||
| 49 | 53 | ||
| 50 | struct ExprCollector<DB> { | 54 | struct ExprCollector<DB> { |
| 51 | db: DB, | 55 | db: DB, |
| 56 | def: DefWithBodyId, | ||
| 52 | expander: Expander, | 57 | expander: Expander, |
| 53 | 58 | ||
| 54 | body: Body, | 59 | body: Body, |
| @@ -467,6 +472,7 @@ where | |||
| 467 | Some(block) => block, | 472 | Some(block) => block, |
| 468 | None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), | 473 | None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), |
| 469 | }; | 474 | }; |
| 475 | self.collect_block_items(&block); | ||
| 470 | let statements = block | 476 | let statements = block |
| 471 | .statements() | 477 | .statements() |
| 472 | .map(|s| match s { | 478 | .map(|s| match s { |
| @@ -483,6 +489,20 @@ where | |||
| 483 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) | 489 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) |
| 484 | } | 490 | } |
| 485 | 491 | ||
| 492 | fn collect_block_items(&mut self, block: &ast::Block) { | ||
| 493 | let container = ContainerId::DefWithBodyId(self.def); | ||
| 494 | for item in block.items() { | ||
| 495 | match item { | ||
| 496 | ast::ModuleItem::FnDef(def) => { | ||
| 497 | let ast_id = self.expander.ast_id(&def); | ||
| 498 | self.body.defs.push(FunctionLoc { container, ast_id }.intern(self.db).into()) | ||
| 499 | } | ||
| 500 | // FIXME: handle other items | ||
| 501 | _ => (), | ||
| 502 | } | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 486 | fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { | 506 | fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { |
| 487 | if let Some(block) = expr { | 507 | if let Some(block) = expr { |
| 488 | self.collect_block(block) | 508 | 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 { | |||
| 858 | "y", | 858 | "y", |
| 859 | ); | 859 | ); |
| 860 | } | 860 | } |
| 861 | |||
| 862 | #[test] | ||
| 863 | fn goto_def_in_local_fn() { | ||
| 864 | check_goto( | ||
| 865 | " | ||
| 866 | //- /lib.rs | ||
| 867 | fn main() { | ||
| 868 | fn foo() { | ||
| 869 | let x = 92; | ||
| 870 | <|>x; | ||
| 871 | } | ||
| 872 | } | ||
| 873 | ", | ||
| 874 | "x BIND_PAT FileId(1) [39; 40)", | ||
| 875 | "x", | ||
| 876 | ); | ||
| 877 | } | ||
| 861 | } | 878 | } |
