aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_expand/src/lib.rs')
-rw-r--r--crates/hir_expand/src/lib.rs58
1 files changed, 45 insertions, 13 deletions
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 7532d00b8..b8045fda9 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -15,6 +15,7 @@ pub mod proc_macro;
15pub mod quote; 15pub mod quote;
16pub mod eager; 16pub mod eager;
17 17
18use either::Either;
18pub use mbe::{ExpandError, ExpandResult}; 19pub use mbe::{ExpandError, ExpandResult};
19 20
20use std::hash::Hash; 21use std::hash::Hash;
@@ -83,7 +84,11 @@ impl HirFileId {
83 } 84 }
84 MacroCallId::EagerMacro(id) => { 85 MacroCallId::EagerMacro(id) => {
85 let loc = db.lookup_intern_eager_expansion(id); 86 let loc = db.lookup_intern_eager_expansion(id);
86 loc.call.file_id 87 if let Some(included_file) = loc.included_file {
88 return included_file;
89 } else {
90 loc.call.file_id
91 }
87 } 92 }
88 }; 93 };
89 file_id.original_file(db) 94 file_id.original_file(db)
@@ -143,7 +148,7 @@ impl HirFileId {
143 148
144 let arg_tt = loc.kind.arg(db)?; 149 let arg_tt = loc.kind.arg(db)?;
145 150
146 let def = loc.def.ast_id.and_then(|id| { 151 let def = loc.def.ast_id().left().and_then(|id| {
147 let def_tt = match id.to_node(db) { 152 let def_tt = match id.to_node(db) {
148 ast::Macro::MacroRules(mac) => mac.token_tree()?, 153 ast::Macro::MacroRules(mac) => mac.token_tree()?,
149 ast::Macro::MacroDef(_) => return None, 154 ast::Macro::MacroDef(_) => return None,
@@ -180,13 +185,28 @@ impl HirFileId {
180 }; 185 };
181 let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); 186 let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
182 let item = match loc.def.kind { 187 let item = match loc.def.kind {
183 MacroDefKind::BuiltInDerive(_) => loc.kind.node(db), 188 MacroDefKind::BuiltInDerive(..) => loc.kind.node(db),
184 _ => return None, 189 _ => return None,
185 }; 190 };
186 Some(item.with_value(ast::Item::cast(item.value.clone())?)) 191 Some(item.with_value(ast::Item::cast(item.value.clone())?))
187 } 192 }
188 } 193 }
189 } 194 }
195
196 /// Return whether this file is an include macro
197 pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool {
198 match self.0 {
199 HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
200 MacroCallId::EagerMacro(id) => {
201 let loc = db.lookup_intern_eager_expansion(id);
202 return loc.included_file.is_some();
203 }
204 _ => {}
205 },
206 _ => {}
207 }
208 false
209 }
190} 210}
191 211
192#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 212#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -224,7 +244,6 @@ impl From<EagerMacroId> for MacroCallId {
224#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 244#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
225pub struct MacroDefId { 245pub struct MacroDefId {
226 pub krate: CrateId, 246 pub krate: CrateId,
227 pub ast_id: Option<AstId<ast::Macro>>,
228 pub kind: MacroDefKind, 247 pub kind: MacroDefKind,
229 248
230 pub local_inner: bool, 249 pub local_inner: bool,
@@ -239,16 +258,27 @@ impl MacroDefId {
239 ) -> LazyMacroId { 258 ) -> LazyMacroId {
240 db.intern_macro(MacroCallLoc { def: self, krate, kind }) 259 db.intern_macro(MacroCallLoc { def: self, krate, kind })
241 } 260 }
261
262 pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> {
263 let id = match &self.kind {
264 MacroDefKind::Declarative(id) => id,
265 MacroDefKind::BuiltIn(_, id) => id,
266 MacroDefKind::BuiltInDerive(_, id) => id,
267 MacroDefKind::BuiltInEager(_, id) => id,
268 MacroDefKind::ProcMacro(_, id) => return Either::Right(*id),
269 };
270 Either::Left(*id)
271 }
242} 272}
243 273
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 274#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
245pub enum MacroDefKind { 275pub enum MacroDefKind {
246 Declarative, 276 Declarative(AstId<ast::Macro>),
247 BuiltIn(BuiltinFnLikeExpander), 277 BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
248 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander 278 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
249 BuiltInDerive(BuiltinDeriveExpander), 279 BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
250 BuiltInEager(EagerExpander), 280 BuiltInEager(EagerExpander, AstId<ast::Macro>),
251 ProcMacro(ProcMacroExpander), 281 ProcMacro(ProcMacroExpander, AstId<ast::Fn>),
252} 282}
253 283
254#[derive(Debug, Clone, PartialEq, Eq, Hash)] 284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -261,21 +291,21 @@ pub struct MacroCallLoc {
261#[derive(Debug, Clone, PartialEq, Eq, Hash)] 291#[derive(Debug, Clone, PartialEq, Eq, Hash)]
262pub enum MacroCallKind { 292pub enum MacroCallKind {
263 FnLike(AstId<ast::MacroCall>), 293 FnLike(AstId<ast::MacroCall>),
264 Attr(AstId<ast::Item>, String), 294 Derive(AstId<ast::Item>, String),
265} 295}
266 296
267impl MacroCallKind { 297impl MacroCallKind {
268 fn file_id(&self) -> HirFileId { 298 fn file_id(&self) -> HirFileId {
269 match self { 299 match self {
270 MacroCallKind::FnLike(ast_id) => ast_id.file_id, 300 MacroCallKind::FnLike(ast_id) => ast_id.file_id,
271 MacroCallKind::Attr(ast_id, _) => ast_id.file_id, 301 MacroCallKind::Derive(ast_id, _) => ast_id.file_id,
272 } 302 }
273 } 303 }
274 304
275 fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { 305 fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> {
276 match self { 306 match self {
277 MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), 307 MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()),
278 MacroCallKind::Attr(ast_id, _) => { 308 MacroCallKind::Derive(ast_id, _) => {
279 ast_id.with_value(ast_id.to_node(db).syntax().clone()) 309 ast_id.with_value(ast_id.to_node(db).syntax().clone())
280 } 310 }
281 } 311 }
@@ -286,7 +316,7 @@ impl MacroCallKind {
286 MacroCallKind::FnLike(ast_id) => { 316 MacroCallKind::FnLike(ast_id) => {
287 Some(ast_id.to_node(db).token_tree()?.syntax().clone()) 317 Some(ast_id.to_node(db).token_tree()?.syntax().clone())
288 } 318 }
289 MacroCallKind::Attr(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()), 319 MacroCallKind::Derive(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()),
290 } 320 }
291 } 321 }
292} 322}
@@ -304,6 +334,8 @@ pub struct EagerCallLoc {
304 pub(crate) subtree: Arc<tt::Subtree>, 334 pub(crate) subtree: Arc<tt::Subtree>,
305 pub(crate) krate: CrateId, 335 pub(crate) krate: CrateId,
306 pub(crate) call: AstId<ast::MacroCall>, 336 pub(crate) call: AstId<ast::MacroCall>,
337 // The included file ID of the include macro.
338 pub(crate) included_file: Option<FileId>,
307} 339}
308 340
309/// ExpansionInfo mainly describes how to map text range between src and expanded macro 341/// ExpansionInfo mainly describes how to map text range between src and expanded macro