mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-24 12:03:31 +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"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource,
|
child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource,
|
||||||
ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId,
|
ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId,
|
||||||
TraitId, TypeAliasId, UnionId, VariantId,
|
StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
|
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
|
@ -227,7 +227,12 @@ fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option
|
||||||
ast::ImplBlock(it) => {
|
ast::ImplBlock(it) => {
|
||||||
let c = ImplBlock::from_source(db, src.with_value(it))?;
|
let c = ImplBlock::from_source(db, src.with_value(it))?;
|
||||||
c.id.child_by_source(db)
|
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 },
|
_ => { continue },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@ once_cell = "1.0.1"
|
||||||
rustc-hash = "1.0"
|
rustc-hash = "1.0"
|
||||||
either = "1.5"
|
either = "1.5"
|
||||||
anymap = "0.12"
|
anymap = "0.12"
|
||||||
|
drop_bomb = "0.1.4"
|
||||||
|
|
||||||
ra_arena = { path = "../ra_arena" }
|
ra_arena = { path = "../ra_arena" }
|
||||||
ra_db = { path = "../ra_db" }
|
ra_db = { path = "../ra_db" }
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
mod lower;
|
mod lower;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
|
|
||||||
use std::{ops::Index, sync::Arc};
|
use std::{mem, ops::Index, sync::Arc};
|
||||||
|
|
||||||
|
use drop_bomb::DropBomb;
|
||||||
use either::Either;
|
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_arena::{map::ArenaMap, Arena};
|
||||||
use ra_syntax::{ast, AstNode, AstPtr};
|
use ra_syntax::{ast, AstNode, AstPtr};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -24,6 +27,7 @@ struct Expander {
|
||||||
crate_def_map: Arc<CrateDefMap>,
|
crate_def_map: Arc<CrateDefMap>,
|
||||||
current_file_id: HirFileId,
|
current_file_id: HirFileId,
|
||||||
hygiene: Hygiene,
|
hygiene: Hygiene,
|
||||||
|
ast_id_map: Arc<AstIdMap>,
|
||||||
module: ModuleId,
|
module: ModuleId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +35,8 @@ impl Expander {
|
||||||
fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
|
fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
|
||||||
let crate_def_map = db.crate_def_map(module.krate);
|
let crate_def_map = db.crate_def_map(module.krate);
|
||||||
let hygiene = Hygiene::new(db, current_file_id);
|
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(
|
fn enter_expand(
|
||||||
|
@ -52,9 +57,14 @@ impl Expander {
|
||||||
if let Some(expr) = ast::Expr::cast(node) {
|
if let Some(expr) = ast::Expr::cast(node) {
|
||||||
log::debug!("macro expansion {:#?}", expr.syntax());
|
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.hygiene = Hygiene::new(db, file_id);
|
||||||
self.current_file_id = file_id;
|
self.current_file_id = file_id;
|
||||||
|
self.ast_id_map = db.ast_id_map(file_id);
|
||||||
|
|
||||||
return Some((mark, expr));
|
return Some((mark, expr));
|
||||||
}
|
}
|
||||||
|
@ -67,10 +77,11 @@ impl Expander {
|
||||||
None
|
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.hygiene = Hygiene::new(db, mark.file_id);
|
||||||
self.current_file_id = 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> {
|
fn to_source<T>(&self, value: T) -> InFile<T> {
|
||||||
|
@ -91,18 +102,17 @@ impl Expander {
|
||||||
.0
|
.0
|
||||||
.take_macros()
|
.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 {
|
struct Mark {
|
||||||
file_id: HirFileId,
|
file_id: HirFileId,
|
||||||
}
|
ast_id_map: Arc<AstIdMap>,
|
||||||
|
bomb: DropBomb,
|
||||||
impl Drop for Mark {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if !std::thread::panicking() {
|
|
||||||
panic!("dropped mark")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body of an item (function, const etc.).
|
/// The body of an item (function, const etc.).
|
||||||
|
@ -174,7 +184,7 @@ impl Body {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let expander = Expander::new(db, file_id, module);
|
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))
|
(Arc::new(body), Arc::new(source_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,11 +194,12 @@ impl Body {
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
db: &impl DefDatabase,
|
db: &impl DefDatabase,
|
||||||
|
def: DefWithBodyId,
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
params: Option<ast::ParamList>,
|
params: Option<ast::ParamList>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
lower::lower(db, expander, params, body)
|
lower::lower(db, def, expander, params, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
//! representation.
|
//! representation.
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
|
||||||
use hir_expand::name::{name, AsName, Name};
|
use hir_expand::name::{name, AsName, Name};
|
||||||
use ra_arena::Arena;
|
use ra_arena::Arena;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{
|
ast::{
|
||||||
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner,
|
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
|
||||||
TypeAscriptionOwner,
|
TypeAscriptionOwner,
|
||||||
},
|
},
|
||||||
AstNode, AstPtr,
|
AstNode, AstPtr,
|
||||||
|
@ -24,17 +25,20 @@ use crate::{
|
||||||
path::GenericArgs,
|
path::GenericArgs,
|
||||||
path::Path,
|
path::Path,
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
|
ContainerId, DefWithBodyId, FunctionLoc, Intern,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn lower(
|
pub(super) fn lower(
|
||||||
db: &impl DefDatabase,
|
db: &impl DefDatabase,
|
||||||
|
def: DefWithBodyId,
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
params: Option<ast::ParamList>,
|
params: Option<ast::ParamList>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
ExprCollector {
|
ExprCollector {
|
||||||
expander,
|
|
||||||
db,
|
db,
|
||||||
|
def,
|
||||||
|
expander,
|
||||||
source_map: BodySourceMap::default(),
|
source_map: BodySourceMap::default(),
|
||||||
body: Body {
|
body: Body {
|
||||||
exprs: Arena::default(),
|
exprs: Arena::default(),
|
||||||
|
@ -49,6 +53,7 @@ pub(super) fn lower(
|
||||||
|
|
||||||
struct ExprCollector<DB> {
|
struct ExprCollector<DB> {
|
||||||
db: DB,
|
db: DB,
|
||||||
|
def: DefWithBodyId,
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
|
|
||||||
body: Body,
|
body: Body,
|
||||||
|
@ -467,6 +472,7 @@ where
|
||||||
Some(block) => block,
|
Some(block) => block,
|
||||||
None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
|
None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
|
||||||
};
|
};
|
||||||
|
self.collect_block_items(&block);
|
||||||
let statements = block
|
let statements = block
|
||||||
.statements()
|
.statements()
|
||||||
.map(|s| match s {
|
.map(|s| match s {
|
||||||
|
@ -483,6 +489,20 @@ where
|
||||||
self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
|
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 {
|
fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
|
||||||
if let Some(block) = expr {
|
if let Some(block) = expr {
|
||||||
self.collect_block(block)
|
self.collect_block(block)
|
||||||
|
|
|
@ -858,4 +858,21 @@ mod tests {
|
||||||
"y",
|
"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