2
2
//!
3
3
//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
4
4
//! this moment, this is horribly incomplete and handles only `$crate`.
5
- use std:: sync:: Arc ;
6
-
7
- use arena:: { Arena , Idx } ;
8
5
use base_db:: CrateId ;
9
6
use either:: Either ;
10
- use mbe:: Origin ;
11
- use syntax:: { ast, AstNode } ;
7
+ use syntax:: ast;
12
8
13
9
use crate :: {
14
10
db:: AstDatabase ,
15
11
name:: { AsName , Name } ,
16
- ExpansionInfo , HirFileId , HirFileIdRepr , MacroCallId , MacroDefKind ,
12
+ HirFileId , HirFileIdRepr , MacroCallId , MacroDefKind ,
17
13
} ;
18
14
19
15
#[ derive( Clone , Debug ) ]
20
16
pub struct Hygiene {
21
- frames : Option < Arc < HygieneFrames > > ,
22
- }
23
-
24
- impl Hygiene {
25
- pub fn new ( db : & dyn AstDatabase , file_id : HirFileId ) -> Hygiene {
26
- Hygiene { frames : Some ( Arc :: new ( HygieneFrames :: new ( db, file_id. clone ( ) ) ) ) }
27
- }
28
-
29
- pub fn new_unhygienic ( ) -> Hygiene {
30
- Hygiene { frames : None }
31
- }
32
-
33
- // FIXME: this should just return name
34
- pub fn name_ref_to_name ( & self , name_ref : ast:: NameRef ) -> Either < Name , CrateId > {
35
- if let Some ( frames) = & self . frames {
36
- if name_ref. text ( ) == "$crate" {
37
- if let Some ( krate) = frames. root_crate ( & name_ref) {
38
- return Either :: Right ( krate) ;
39
- }
40
- }
41
- }
42
-
43
- Either :: Left ( name_ref. as_name ( ) )
44
- }
45
-
46
- pub fn local_inner_macros ( & self , path : ast:: Path ) -> Option < CrateId > {
47
- let frames = self . frames . as_ref ( ) ?;
48
-
49
- let mut token = path. syntax ( ) . first_token ( ) ?;
50
- let mut current = frames. first ( ) ;
51
-
52
- while let Some ( ( frame, data) ) =
53
- current. and_then ( |it| Some ( ( it, it. expansion . as_ref ( ) ?. map_token_up ( & token) ?) ) )
54
- {
55
- let ( mapped, origin) = data;
56
- if origin == Origin :: Def {
57
- return if frame. local_inner { frame. krate } else { None } ;
58
- }
59
- current = Some ( & frames. 0 [ frame. call_site ?] ) ;
60
- token = mapped. value ;
61
- }
62
- None
63
- }
64
- }
65
-
66
- #[ derive( Default , Debug ) ]
67
- struct HygieneFrames ( Arena < HygieneFrame > ) ;
68
-
69
- #[ derive( Clone , Debug ) ]
70
- struct HygieneFrame {
71
- expansion : Option < ExpansionInfo > ,
17
+ // This is what `$crate` expands to
18
+ def_crate : Option < CrateId > ,
72
19
73
20
// Indicate this is a local inner macro
74
21
local_inner : bool ,
75
- krate : Option < CrateId > ,
76
-
77
- call_site : Option < Idx < HygieneFrame > > ,
78
- def_site : Option < Idx < HygieneFrame > > ,
79
22
}
80
23
81
- impl HygieneFrames {
82
- fn new ( db : & dyn AstDatabase , file_id : HirFileId ) -> Self {
83
- let mut frames = HygieneFrames :: default ( ) ;
84
- frames. add ( db, file_id) ;
85
- frames
86
- }
87
-
88
- fn add ( & mut self , db : & dyn AstDatabase , file_id : HirFileId ) -> Option < Idx < HygieneFrame > > {
89
- let ( krate, local_inner) = match file_id. 0 {
24
+ impl Hygiene {
25
+ pub fn new ( db : & dyn AstDatabase , file_id : HirFileId ) -> Hygiene {
26
+ let ( def_crate, local_inner) = match file_id. 0 {
90
27
HirFileIdRepr :: FileId ( _) => ( None , false ) ,
91
28
HirFileIdRepr :: MacroFile ( macro_file) => match macro_file. macro_call_id {
92
- MacroCallId :: EagerMacro ( _id) => ( None , false ) ,
93
29
MacroCallId :: LazyMacro ( id) => {
94
30
let loc = db. lookup_intern_macro ( id) ;
95
31
match loc. def . kind {
@@ -100,68 +36,31 @@ impl HygieneFrames {
100
36
MacroDefKind :: ProcMacro ( _) => ( None , false ) ,
101
37
}
102
38
}
39
+ MacroCallId :: EagerMacro ( _id) => ( None , false ) ,
103
40
} ,
104
41
} ;
105
-
106
- let expansion = file_id. expansion_info ( db) ;
107
- let expansion = match expansion {
108
- None => {
109
- return Some ( self . 0 . alloc ( HygieneFrame {
110
- expansion : None ,
111
- local_inner,
112
- krate,
113
- call_site : None ,
114
- def_site : None ,
115
- } ) ) ;
116
- }
117
- Some ( it) => it,
118
- } ;
119
-
120
- let def_site = expansion. def . clone ( ) ;
121
- let call_site = expansion. arg . file_id ;
122
- let idx = self . 0 . alloc ( HygieneFrame {
123
- expansion : Some ( expansion) ,
124
- local_inner,
125
- krate,
126
- call_site : None ,
127
- def_site : None ,
128
- } ) ;
129
-
130
- self . 0 [ idx] . call_site = self . add ( db, call_site) ;
131
- self . 0 [ idx] . def_site = def_site. and_then ( |it| self . add ( db, it. file_id ) ) ;
132
-
133
- Some ( idx)
42
+ Hygiene { def_crate, local_inner }
134
43
}
135
44
136
- fn first ( & self ) -> Option < & HygieneFrame > {
137
- self . 0 . iter ( ) . next ( ) . map ( |it| it . 1 )
45
+ pub fn new_unhygienic ( ) -> Hygiene {
46
+ Hygiene { def_crate : None , local_inner : false }
138
47
}
139
48
140
- fn root_crate ( & self , name_ref : & ast:: NameRef ) -> Option < CrateId > {
141
- let mut token = name_ref. syntax ( ) . first_token ( ) ?;
142
- let first = self . first ( ) ?;
143
- let mut result = first. krate ;
144
- let mut current = Some ( first) ;
145
-
146
- while let Some ( ( frame, ( mapped, origin) ) ) =
147
- current. and_then ( |it| Some ( ( it, it. expansion . as_ref ( ) ?. map_token_up ( & token) ?) ) )
148
- {
149
- result = frame. krate ;
150
-
151
- let site = match origin {
152
- Origin :: Def => frame. def_site ,
153
- Origin :: Call => frame. call_site ,
154
- } ;
155
-
156
- let site = match site {
157
- None => break ,
158
- Some ( it) => it,
159
- } ;
160
-
161
- current = Some ( & self . 0 [ site] ) ;
162
- token = mapped. value ;
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
+ }
163
55
}
56
+ Either :: Left ( name_ref. as_name ( ) )
57
+ }
164
58
165
- result
59
+ pub fn local_inner_macros ( & self ) -> Option < CrateId > {
60
+ if self . local_inner {
61
+ self . def_crate
62
+ } else {
63
+ None
64
+ }
166
65
}
167
66
}
0 commit comments