aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-12-20 10:19:09 +0000
committerAleksey Kladov <[email protected]>2019-12-20 10:52:17 +0000
commita04177f135be89ddbf1788c6f747c26812e90438 (patch)
treef2dbdf832caab0448427641b6a93ae3c66465c12 /crates
parent08c6933104baca84fd4135a76cdc7daf60a0c631 (diff)
Add local functions to bodies
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/from_source.rs11
-rw-r--r--crates/ra_hir_def/Cargo.toml1
-rw-r--r--crates/ra_hir_def/src/body.rs43
-rw-r--r--crates/ra_hir_def/src/body/lower.rs24
-rw-r--r--crates/ra_ide/src/goto_definition.rs17
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
2use hir_def::{ 2use 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};
7use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 7use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
8use ra_syntax::{ 8use 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"
13rustc-hash = "1.0" 13rustc-hash = "1.0"
14either = "1.5" 14either = "1.5"
15anymap = "0.12" 15anymap = "0.12"
16drop_bomb = "0.1.4"
16 17
17ra_arena = { path = "../ra_arena" } 18ra_arena = { path = "../ra_arena" }
18ra_db = { path = "../ra_db" } 19ra_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 @@
3mod lower; 3mod lower;
4pub mod scope; 4pub mod scope;
5 5
6use std::{ops::Index, sync::Arc}; 6use std::{mem, ops::Index, sync::Arc};
7 7
8use drop_bomb::DropBomb;
8use either::Either; 9use either::Either;
9use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; 10use hir_expand::{
11 ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
12};
10use ra_arena::{map::ArenaMap, Arena}; 13use ra_arena::{map::ArenaMap, Arena};
11use ra_syntax::{ast, AstNode, AstPtr}; 14use ra_syntax::{ast, AstNode, AstPtr};
12use rustc_hash::FxHashMap; 15use 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
96struct Mark { 112struct Mark {
97 file_id: HirFileId, 113 file_id: HirFileId,
98} 114 ast_id_map: Arc<AstIdMap>,
99 115 bomb: DropBomb,
100impl 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
4use either::Either; 4use either::Either;
5
5use hir_expand::name::{name, AsName, Name}; 6use hir_expand::name::{name, AsName, Name};
6use ra_arena::Arena; 7use ra_arena::Arena;
7use ra_syntax::{ 8use 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
29pub(super) fn lower( 31pub(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
50struct ExprCollector<DB> { 54struct 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}