diff options
Diffstat (limited to 'crates/ra_hir/src/ids.rs')
-rw-r--r-- | crates/ra_hir/src/ids.rs | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 262047849..4b4e07e58 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -16,10 +16,10 @@ use crate::{ | |||
16 | pub struct HirInterner { | 16 | pub struct HirInterner { |
17 | defs: LocationIntener<DefLoc, DefId>, | 17 | defs: LocationIntener<DefLoc, DefId>, |
18 | macros: LocationIntener<MacroCallLoc, MacroCallId>, | 18 | macros: LocationIntener<MacroCallLoc, MacroCallId>, |
19 | pub(crate) fns: LocationIntener<ItemLoc<ast::FnDef>, FunctionId>, | 19 | fns: LocationIntener<ItemLoc<ast::FnDef>, FunctionId>, |
20 | pub(crate) structs: LocationIntener<ItemLoc<ast::StructDef>, StructId>, | 20 | structs: LocationIntener<ItemLoc<ast::StructDef>, StructId>, |
21 | pub(crate) enums: LocationIntener<ItemLoc<ast::EnumDef>, EnumId>, | 21 | enums: LocationIntener<ItemLoc<ast::EnumDef>, EnumId>, |
22 | pub(crate) enum_variants: LocationIntener<ItemLoc<ast::EnumVariant>, EnumVariantId>, | 22 | enum_variants: LocationIntener<ItemLoc<ast::EnumVariant>, EnumVariantId>, |
23 | } | 23 | } |
24 | 24 | ||
25 | impl HirInterner { | 25 | impl HirInterner { |
@@ -144,50 +144,64 @@ pub struct ItemLoc<N: AstNode> { | |||
144 | _ty: PhantomData<N>, | 144 | _ty: PhantomData<N>, |
145 | } | 145 | } |
146 | 146 | ||
147 | impl<N: AstNode> ItemLoc<N> { | 147 | impl<N: AstNode> Clone for ItemLoc<N> { |
148 | pub(crate) fn from_ast( | 148 | fn clone(&self) -> ItemLoc<N> { |
149 | db: &impl HirDatabase, | ||
150 | module: Module, | ||
151 | file_id: HirFileId, | ||
152 | ast: &N, | ||
153 | ) -> ItemLoc<N> { | ||
154 | let items = db.file_items(file_id); | ||
155 | let raw = SourceItemId { | ||
156 | file_id, | ||
157 | item_id: Some(items.id_of(file_id, ast.syntax())), | ||
158 | }; | ||
159 | ItemLoc { | 149 | ItemLoc { |
160 | module, | 150 | module: self.module, |
161 | raw, | 151 | raw: self.raw, |
162 | _ty: PhantomData, | 152 | _ty: PhantomData, |
163 | } | 153 | } |
164 | } | 154 | } |
155 | } | ||
165 | 156 | ||
166 | pub(crate) fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) { | 157 | #[derive(Clone, Copy)] |
167 | let syntax = db.file_item(self.raw); | 158 | pub(crate) struct LocationCtx<DB> { |
168 | let ast = N::cast(&syntax) | 159 | db: DB, |
169 | .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", self.raw)) | 160 | module: Module, |
170 | .to_owned(); | 161 | file_id: HirFileId, |
171 | (self.raw.file_id, ast) | ||
172 | } | ||
173 | } | 162 | } |
174 | 163 | ||
175 | impl<N: AstNode> Clone for ItemLoc<N> { | 164 | impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { |
176 | fn clone(&self) -> ItemLoc<N> { | 165 | pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { |
177 | ItemLoc { | 166 | LocationCtx { |
178 | module: self.module, | 167 | db, |
179 | raw: self.raw, | 168 | module, |
180 | _ty: PhantomData, | 169 | file_id, |
181 | } | 170 | } |
182 | } | 171 | } |
172 | pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF | ||
173 | where | ||
174 | N: AstNode + Eq + Hash, | ||
175 | DEF: AstItemDef<N>, | ||
176 | { | ||
177 | DEF::from_ast(self, ast) | ||
178 | } | ||
183 | } | 179 | } |
184 | 180 | ||
185 | pub(crate) trait AstItemDef<N: AstNode + Eq + Hash>: ArenaId + Clone { | 181 | pub(crate) trait AstItemDef<N: AstNode + Eq + Hash>: ArenaId + Clone { |
186 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>; | 182 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>; |
183 | fn from_ast(ctx: LocationCtx<&impl HirDatabase>, ast: &N) -> Self { | ||
184 | let items = ctx.db.file_items(ctx.file_id); | ||
185 | let raw = SourceItemId { | ||
186 | file_id: ctx.file_id, | ||
187 | item_id: Some(items.id_of(ctx.file_id, ast.syntax())), | ||
188 | }; | ||
189 | let loc = ItemLoc { | ||
190 | module: ctx.module, | ||
191 | raw, | ||
192 | _ty: PhantomData, | ||
193 | }; | ||
194 | |||
195 | Self::interner(ctx.db.as_ref()).loc2id(&loc) | ||
196 | } | ||
187 | fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) { | 197 | fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) { |
188 | let int = Self::interner(db.as_ref()); | 198 | let int = Self::interner(db.as_ref()); |
189 | let loc = int.id2loc(self); | 199 | let loc = int.id2loc(self); |
190 | loc.source(db) | 200 | let syntax = db.file_item(loc.raw); |
201 | let ast = N::cast(&syntax) | ||
202 | .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)) | ||
203 | .to_owned(); | ||
204 | (loc.raw.file_id, ast) | ||
191 | } | 205 | } |
192 | fn module(self, db: &impl HirDatabase) -> Module { | 206 | fn module(self, db: &impl HirDatabase) -> Module { |
193 | let int = Self::interner(db.as_ref()); | 207 | let int = Self::interner(db.as_ref()); |