@@ -18,47 +18,89 @@ use rustc_hash::FxHasher;
18
18
use syntax:: { ast, AstNode , AstPtr , SyntaxNode , SyntaxNodePtr } ;
19
19
20
20
/// `AstId` points to an AST node in a specific file.
21
- pub struct FileAstId < N : AstNode > {
21
+ pub struct FileAstId < N : AstIdNode > {
22
22
raw : ErasedFileAstId ,
23
23
covariant : PhantomData < fn ( ) -> N > ,
24
24
}
25
25
26
- impl < N : AstNode > Clone for FileAstId < N > {
26
+ impl < N : AstIdNode > Clone for FileAstId < N > {
27
27
fn clone ( & self ) -> FileAstId < N > {
28
28
* self
29
29
}
30
30
}
31
- impl < N : AstNode > Copy for FileAstId < N > { }
31
+ impl < N : AstIdNode > Copy for FileAstId < N > { }
32
32
33
- impl < N : AstNode > PartialEq for FileAstId < N > {
33
+ impl < N : AstIdNode > PartialEq for FileAstId < N > {
34
34
fn eq ( & self , other : & Self ) -> bool {
35
35
self . raw == other. raw
36
36
}
37
37
}
38
- impl < N : AstNode > Eq for FileAstId < N > { }
39
- impl < N : AstNode > Hash for FileAstId < N > {
38
+ impl < N : AstIdNode > Eq for FileAstId < N > { }
39
+ impl < N : AstIdNode > Hash for FileAstId < N > {
40
40
fn hash < H : Hasher > ( & self , hasher : & mut H ) {
41
41
self . raw . hash ( hasher) ;
42
42
}
43
43
}
44
44
45
- impl < N : AstNode > fmt:: Debug for FileAstId < N > {
45
+ impl < N : AstIdNode > fmt:: Debug for FileAstId < N > {
46
46
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
47
47
write ! ( f, "FileAstId::<{}>({})" , type_name:: <N >( ) , self . raw. into_raw( ) )
48
48
}
49
49
}
50
50
51
- impl < N : AstNode > FileAstId < N > {
51
+ impl < N : AstIdNode > FileAstId < N > {
52
52
// Can't make this a From implementation because of coherence
53
- pub fn upcast < M : AstNode > ( self ) -> FileAstId < M >
53
+ pub fn upcast < M : AstIdNode > ( self ) -> FileAstId < M >
54
54
where
55
55
N : Into < M > ,
56
56
{
57
57
FileAstId { raw : self . raw , covariant : PhantomData }
58
58
}
59
+
60
+ pub fn erase ( self ) -> ErasedFileAstId {
61
+ self . raw
62
+ }
59
63
}
60
64
61
- type ErasedFileAstId = Idx < SyntaxNodePtr > ;
65
+ pub type ErasedFileAstId = Idx < SyntaxNodePtr > ;
66
+
67
+ pub trait AstIdNode : AstNode { }
68
+ macro_rules! register_ast_id_node {
69
+ ( impl AstIdNode for $( $ident: ident) ,+ ) => {
70
+ $(
71
+ impl AstIdNode for ast:: $ident { }
72
+ ) +
73
+ fn should_alloc_id( kind: syntax:: SyntaxKind ) -> bool {
74
+ $(
75
+ ast:: $ident:: can_cast( kind)
76
+ ) ||+
77
+ }
78
+ } ;
79
+ }
80
+ register_ast_id_node ! {
81
+ impl AstIdNode for
82
+ Item ,
83
+ Adt ,
84
+ Enum ,
85
+ Struct ,
86
+ Union ,
87
+ Const ,
88
+ ExternBlock ,
89
+ ExternCrate ,
90
+ Fn ,
91
+ Impl ,
92
+ Macro ,
93
+ MacroDef ,
94
+ MacroRules ,
95
+ MacroCall ,
96
+ Module ,
97
+ Static ,
98
+ Trait ,
99
+ TraitAlias ,
100
+ TypeAlias ,
101
+ Use ,
102
+ AssocItem , BlockExpr , Variant , RecordField , TupleField , ConstArg
103
+ }
62
104
63
105
/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
64
106
#[ derive( Default ) ]
@@ -92,14 +134,7 @@ impl AstIdMap {
92
134
// change parent's id. This means that, say, adding a new function to a
93
135
// trait does not change ids of top-level items, which helps caching.
94
136
bdfs ( node, |it| {
95
- let kind = it. kind ( ) ;
96
- if ast:: Item :: can_cast ( kind)
97
- || ast:: BlockExpr :: can_cast ( kind)
98
- || ast:: Variant :: can_cast ( kind)
99
- || ast:: RecordField :: can_cast ( kind)
100
- || ast:: TupleField :: can_cast ( kind)
101
- || ast:: ConstArg :: can_cast ( kind)
102
- {
137
+ if should_alloc_id ( it. kind ( ) ) {
103
138
res. alloc ( & it) ;
104
139
true
105
140
} else {
@@ -120,15 +155,19 @@ impl AstIdMap {
120
155
res
121
156
}
122
157
123
- pub fn ast_id < N : AstNode > ( & self , item : & N ) -> FileAstId < N > {
158
+ pub fn ast_id < N : AstIdNode > ( & self , item : & N ) -> FileAstId < N > {
124
159
let raw = self . erased_ast_id ( item. syntax ( ) ) ;
125
160
FileAstId { raw, covariant : PhantomData }
126
161
}
127
162
128
- pub fn get < N : AstNode > ( & self , id : FileAstId < N > ) -> AstPtr < N > {
163
+ pub fn get < N : AstIdNode > ( & self , id : FileAstId < N > ) -> AstPtr < N > {
129
164
AstPtr :: try_from_raw ( self . arena [ id. raw ] . clone ( ) ) . unwrap ( )
130
165
}
131
166
167
+ pub ( crate ) fn get_raw ( & self , id : ErasedFileAstId ) -> SyntaxNodePtr {
168
+ self . arena [ id] . clone ( )
169
+ }
170
+
132
171
fn erased_ast_id ( & self , item : & SyntaxNode ) -> ErasedFileAstId {
133
172
let ptr = SyntaxNodePtr :: new ( item) ;
134
173
let hash = hash_ptr ( & ptr) ;
0 commit comments