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 | } |