mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-23 19:43:23 +00:00
Add local functions to bodies
This commit is contained in:
parent
08c6933104
commit
a04177f135
6 changed files with 76 additions and 21 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -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)",
|
||||
|
|
|
@ -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 },
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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<CrateDefMap>,
|
||||
current_file_id: HirFileId,
|
||||
hygiene: Hygiene,
|
||||
ast_id_map: Arc<AstIdMap>,
|
||||
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<T>(&self, value: T) -> InFile<T> {
|
||||
|
@ -91,18 +102,17 @@ impl Expander {
|
|||
.0
|
||||
.take_macros()
|
||||
}
|
||||
|
||||
fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
|
||||
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<AstIdMap>,
|
||||
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<ast::ParamList>,
|
||||
body: Option<ast::Expr>,
|
||||
) -> (Body, BodySourceMap) {
|
||||
lower::lower(db, expander, params, body)
|
||||
lower::lower(db, def, expander, params, body)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ast::ParamList>,
|
||||
body: Option<ast::Expr>,
|
||||
) -> (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: 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<ast::BlockExpr>) -> ExprId {
|
||||
if let Some(block) = expr {
|
||||
self.collect_block(block)
|
||||
|
|
|
@ -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",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue