diff options
author | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
---|---|---|
committer | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
commit | 178c3e135a2a249692f7784712492e7884ae0c00 (patch) | |
tree | ac6b769dbf7162150caa0c1624786a4dd79ff3be /crates/hir_expand/src/hygiene.rs | |
parent | 06ff8e6c760ff05f10e868b5d1f9d79e42fbb49c (diff) | |
parent | c2594daf2974dbd4ce3d9b7ec72481764abaceb5 (diff) |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'crates/hir_expand/src/hygiene.rs')
-rw-r--r-- | crates/hir_expand/src/hygiene.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs new file mode 100644 index 000000000..845e9cbc1 --- /dev/null +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -0,0 +1,66 @@ | |||
1 | //! This modules handles hygiene information. | ||
2 | //! | ||
3 | //! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at | ||
4 | //! this moment, this is horribly incomplete and handles only `$crate`. | ||
5 | use base_db::CrateId; | ||
6 | use either::Either; | ||
7 | use syntax::ast; | ||
8 | |||
9 | use crate::{ | ||
10 | db::AstDatabase, | ||
11 | name::{AsName, Name}, | ||
12 | HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind, | ||
13 | }; | ||
14 | |||
15 | #[derive(Clone, Debug)] | ||
16 | pub struct Hygiene { | ||
17 | // This is what `$crate` expands to | ||
18 | def_crate: Option<CrateId>, | ||
19 | |||
20 | // Indicate this is a local inner macro | ||
21 | local_inner: bool, | ||
22 | } | ||
23 | |||
24 | impl Hygiene { | ||
25 | pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { | ||
26 | let (def_crate, local_inner) = match file_id.0 { | ||
27 | HirFileIdRepr::FileId(_) => (None, false), | ||
28 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
29 | MacroCallId::LazyMacro(id) => { | ||
30 | let loc = db.lookup_intern_macro(id); | ||
31 | match loc.def.kind { | ||
32 | MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner), | ||
33 | MacroDefKind::BuiltIn(_) => (None, false), | ||
34 | MacroDefKind::BuiltInDerive(_) => (None, false), | ||
35 | MacroDefKind::BuiltInEager(_) => (None, false), | ||
36 | MacroDefKind::CustomDerive(_) => (None, false), | ||
37 | } | ||
38 | } | ||
39 | MacroCallId::EagerMacro(_id) => (None, false), | ||
40 | }, | ||
41 | }; | ||
42 | Hygiene { def_crate, local_inner } | ||
43 | } | ||
44 | |||
45 | pub fn new_unhygienic() -> Hygiene { | ||
46 | Hygiene { def_crate: None, local_inner: false } | ||
47 | } | ||
48 | |||
49 | // FIXME: this should just return name | ||
50 | pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> { | ||
51 | if let Some(def_crate) = self.def_crate { | ||
52 | if name_ref.text() == "$crate" { | ||
53 | return Either::Right(def_crate); | ||
54 | } | ||
55 | } | ||
56 | Either::Left(name_ref.as_name()) | ||
57 | } | ||
58 | |||
59 | pub fn local_inner_macros(&self) -> Option<CrateId> { | ||
60 | if self.local_inner { | ||
61 | self.def_crate | ||
62 | } else { | ||
63 | None | ||
64 | } | ||
65 | } | ||
66 | } | ||