Add local functions to bodies

This commit is contained in:
Aleksey Kladov 2019-12-20 11:19:09 +01:00
parent 08c6933104
commit a04177f135
6 changed files with 76 additions and 21 deletions

1
Cargo.lock generated
View file

@ -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)",

View file

@ -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 },
}
};

View file

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

View file

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

View file

@ -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)

View file

@ -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",
);
}
}