//! 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::{
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 },
}
};
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;
crate_def_map: Arc<CrateDefMap>,
current_file_id: HirFileId,
hygiene: Hygiene,
+ ast_id_map: Arc<AstIdMap>,
module: ModuleId,
}
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(
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));
}
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> {
.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.).
}
};
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))
}
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)
}
}
//! 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,
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(),
struct ExprCollector<DB> {
db: DB,
+ def: DefWithBodyId,
expander: Expander,
body: Body,
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 {
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)