diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-19 21:20:43 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-19 21:20:43 +0000 |
commit | 8b16af590dd3d241bec07f69f4d4dadae9a4b523 (patch) | |
tree | 79729a2efc6d2cdb2557cd313ee79a25245983d3 /crates | |
parent | fc21640a65b5caef8dbbc9e85e9616b843847fb4 (diff) | |
parent | 636de3c709a7c86a1d3a870dc5dc3566310e9d92 (diff) |
Merge #8112
8112: Revamp `hir_def` attribute API r=Veykril a=jonas-schievink
This adds `AttrsWithOwner`, which can construct an accurate `AttrSourceMap` without requiring additional information from the caller.
r? @Veykril
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/attrs.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/attr.rs | 312 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 73 | ||||
-rw-r--r-- | crates/syntax/src/ast.rs | 4 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 30 |
7 files changed, 248 insertions, 187 deletions
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index dab8da7bb..4a11622fc 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Attributes & documentation for hir types. | 1 | //! Attributes & documentation for hir types. |
2 | use hir_def::{ | 2 | use hir_def::{ |
3 | attr::{Attrs, Documentation}, | 3 | attr::{AttrsWithOwner, Documentation}, |
4 | path::ModPath, | 4 | path::ModPath, |
5 | per_ns::PerNs, | 5 | per_ns::PerNs, |
6 | resolver::HasResolver, | 6 | resolver::HasResolver, |
@@ -16,7 +16,7 @@ use crate::{ | |||
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub trait HasAttrs { | 18 | pub trait HasAttrs { |
19 | fn attrs(self, db: &dyn HirDatabase) -> Attrs; | 19 | fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner; |
20 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>; | 20 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>; |
21 | fn resolve_doc_path( | 21 | fn resolve_doc_path( |
22 | self, | 22 | self, |
@@ -36,7 +36,7 @@ pub enum Namespace { | |||
36 | macro_rules! impl_has_attrs { | 36 | macro_rules! impl_has_attrs { |
37 | ($(($def:ident, $def_id:ident),)*) => {$( | 37 | ($(($def:ident, $def_id:ident),)*) => {$( |
38 | impl HasAttrs for $def { | 38 | impl HasAttrs for $def { |
39 | fn attrs(self, db: &dyn HirDatabase) -> Attrs { | 39 | fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { |
40 | let def = AttrDefId::$def_id(self.into()); | 40 | let def = AttrDefId::$def_id(self.into()); |
41 | db.attrs(def) | 41 | db.attrs(def) |
42 | } | 42 | } |
@@ -70,7 +70,7 @@ impl_has_attrs![ | |||
70 | macro_rules! impl_has_attrs_enum { | 70 | macro_rules! impl_has_attrs_enum { |
71 | ($($variant:ident),* for $enum:ident) => {$( | 71 | ($($variant:ident),* for $enum:ident) => {$( |
72 | impl HasAttrs for $variant { | 72 | impl HasAttrs for $variant { |
73 | fn attrs(self, db: &dyn HirDatabase) -> Attrs { | 73 | fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { |
74 | $enum::$variant(self).attrs(db) | 74 | $enum::$variant(self).attrs(db) |
75 | } | 75 | } |
76 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> { | 76 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> { |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5ebd0a3b8..300087f1f 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -89,7 +89,7 @@ pub use crate::{ | |||
89 | pub use { | 89 | pub use { |
90 | hir_def::{ | 90 | hir_def::{ |
91 | adt::StructKind, | 91 | adt::StructKind, |
92 | attr::{Attr, Attrs, Documentation}, | 92 | attr::{Attr, Attrs, AttrsWithOwner, Documentation}, |
93 | body::scope::ExprScopes, | 93 | body::scope::ExprScopes, |
94 | find_path::PrefixKind, | 94 | find_path::PrefixKind, |
95 | import_map, | 95 | import_map, |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index beeaaf117..2c10f46d8 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | item_tree::{ItemTreeId, ItemTreeNode}, | 21 | item_tree::{ItemTreeId, ItemTreeNode}, |
22 | nameres::ModuleSource, | 22 | nameres::ModuleSource, |
23 | path::{ModPath, PathKind}, | 23 | path::{ModPath, PathKind}, |
24 | src::HasChildSource, | 24 | src::{HasChildSource, HasSource}, |
25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, | 25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, |
26 | VariantId, | 26 | VariantId, |
27 | }; | 27 | }; |
@@ -51,6 +51,12 @@ pub(crate) struct RawAttrs { | |||
51 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 51 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
52 | pub struct Attrs(RawAttrs); | 52 | pub struct Attrs(RawAttrs); |
53 | 53 | ||
54 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
55 | pub struct AttrsWithOwner { | ||
56 | attrs: Attrs, | ||
57 | owner: AttrDefId, | ||
58 | } | ||
59 | |||
54 | impl ops::Deref for RawAttrs { | 60 | impl ops::Deref for RawAttrs { |
55 | type Target = [Attr]; | 61 | type Target = [Attr]; |
56 | 62 | ||
@@ -73,6 +79,14 @@ impl ops::Deref for Attrs { | |||
73 | } | 79 | } |
74 | } | 80 | } |
75 | 81 | ||
82 | impl ops::Deref for AttrsWithOwner { | ||
83 | type Target = Attrs; | ||
84 | |||
85 | fn deref(&self) -> &Attrs { | ||
86 | &self.attrs | ||
87 | } | ||
88 | } | ||
89 | |||
76 | impl RawAttrs { | 90 | impl RawAttrs { |
77 | pub(crate) const EMPTY: Self = Self { entries: None }; | 91 | pub(crate) const EMPTY: Self = Self { entries: None }; |
78 | 92 | ||
@@ -169,78 +183,6 @@ impl RawAttrs { | |||
169 | impl Attrs { | 183 | impl Attrs { |
170 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); | 184 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); |
171 | 185 | ||
172 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | ||
173 | let raw_attrs = match def { | ||
174 | AttrDefId::ModuleId(module) => { | ||
175 | let def_map = module.def_map(db); | ||
176 | let mod_data = &def_map[module.local_id]; | ||
177 | match mod_data.declaration_source(db) { | ||
178 | Some(it) => { | ||
179 | let raw_attrs = RawAttrs::from_attrs_owner( | ||
180 | db, | ||
181 | it.as_ref().map(|it| it as &dyn ast::AttrsOwner), | ||
182 | ); | ||
183 | match mod_data.definition_source(db) { | ||
184 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
185 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
186 | _ => raw_attrs, | ||
187 | } | ||
188 | } | ||
189 | None => RawAttrs::from_attrs_owner( | ||
190 | db, | ||
191 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
192 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, | ||
193 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, | ||
194 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, | ||
195 | }), | ||
196 | ), | ||
197 | } | ||
198 | } | ||
199 | AttrDefId::FieldId(it) => { | ||
200 | return db.fields_attrs(it.parent)[it.local_id].clone(); | ||
201 | } | ||
202 | AttrDefId::EnumVariantId(it) => { | ||
203 | return db.variants_attrs(it.parent)[it.local_id].clone(); | ||
204 | } | ||
205 | AttrDefId::AdtId(it) => match it { | ||
206 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
207 | AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
208 | AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
209 | }, | ||
210 | AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
211 | AttrDefId::MacroDefId(it) => it | ||
212 | .ast_id() | ||
213 | .left() | ||
214 | .map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)), | ||
215 | AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
216 | AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
217 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
218 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
219 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
220 | AttrDefId::GenericParamId(it) => match it { | ||
221 | GenericParamId::TypeParamId(it) => { | ||
222 | let src = it.parent.child_source(db); | ||
223 | RawAttrs::from_attrs_owner( | ||
224 | db, | ||
225 | src.with_value( | ||
226 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
227 | ), | ||
228 | ) | ||
229 | } | ||
230 | GenericParamId::LifetimeParamId(it) => { | ||
231 | let src = it.parent.child_source(db); | ||
232 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
233 | } | ||
234 | GenericParamId::ConstParamId(it) => { | ||
235 | let src = it.parent.child_source(db); | ||
236 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
237 | } | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | raw_attrs.filter(db, def.krate(db)) | ||
242 | } | ||
243 | |||
244 | pub(crate) fn variants_attrs_query( | 186 | pub(crate) fn variants_attrs_query( |
245 | db: &dyn DefDatabase, | 187 | db: &dyn DefDatabase, |
246 | e: EnumId, | 188 | e: EnumId, |
@@ -281,56 +223,6 @@ impl Attrs { | |||
281 | Arc::new(res) | 223 | Arc::new(res) |
282 | } | 224 | } |
283 | 225 | ||
284 | /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes. | ||
285 | /// | ||
286 | /// `owner` must be the original owner of the attributes. | ||
287 | // FIXME: figure out a better api that doesnt require the for_module hack | ||
288 | pub fn source_map(&self, owner: InFile<&dyn ast::AttrsOwner>) -> AttrSourceMap { | ||
289 | // FIXME: This doesn't work correctly for modules, as the attributes there can have up to | ||
290 | // two different owners | ||
291 | AttrSourceMap { | ||
292 | attrs: collect_attrs(owner.value) | ||
293 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
294 | .collect(), | ||
295 | } | ||
296 | } | ||
297 | |||
298 | pub fn source_map_for_module( | ||
299 | &self, | ||
300 | db: &dyn DefDatabase, | ||
301 | module: crate::ModuleId, | ||
302 | ) -> AttrSourceMap { | ||
303 | let def_map = module.def_map(db); | ||
304 | let mod_data = &def_map[module.local_id]; | ||
305 | let attrs = match mod_data.declaration_source(db) { | ||
306 | Some(it) => { | ||
307 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | ||
308 | .map(|attr| InFile::new(it.file_id, attr)) | ||
309 | .collect(); | ||
310 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | ||
311 | mod_data.definition_source(db) | ||
312 | { | ||
313 | attrs.extend( | ||
314 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
315 | .map(|attr| InFile::new(file_id, attr)), | ||
316 | ) | ||
317 | } | ||
318 | attrs | ||
319 | } | ||
320 | None => { | ||
321 | let InFile { file_id, value } = mod_data.definition_source(db); | ||
322 | match &value { | ||
323 | ModuleSource::SourceFile(file) => collect_attrs(file as &dyn ast::AttrsOwner), | ||
324 | ModuleSource::Module(module) => collect_attrs(module as &dyn ast::AttrsOwner), | ||
325 | ModuleSource::BlockExpr(block) => collect_attrs(block as &dyn ast::AttrsOwner), | ||
326 | } | ||
327 | .map(|attr| InFile::new(file_id, attr)) | ||
328 | .collect() | ||
329 | } | ||
330 | }; | ||
331 | AttrSourceMap { attrs } | ||
332 | } | ||
333 | |||
334 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 226 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
335 | AttrQuery { attrs: self, key } | 227 | AttrQuery { attrs: self, key } |
336 | } | 228 | } |
@@ -387,6 +279,180 @@ impl Attrs { | |||
387 | } | 279 | } |
388 | } | 280 | } |
389 | 281 | ||
282 | impl AttrsWithOwner { | ||
283 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Self { | ||
284 | // FIXME: this should use `Trace` to avoid duplication in `source_map` below | ||
285 | let raw_attrs = match def { | ||
286 | AttrDefId::ModuleId(module) => { | ||
287 | let def_map = module.def_map(db); | ||
288 | let mod_data = &def_map[module.local_id]; | ||
289 | match mod_data.declaration_source(db) { | ||
290 | Some(it) => { | ||
291 | let raw_attrs = RawAttrs::from_attrs_owner( | ||
292 | db, | ||
293 | it.as_ref().map(|it| it as &dyn ast::AttrsOwner), | ||
294 | ); | ||
295 | match mod_data.definition_source(db) { | ||
296 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
297 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
298 | _ => raw_attrs, | ||
299 | } | ||
300 | } | ||
301 | None => RawAttrs::from_attrs_owner( | ||
302 | db, | ||
303 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
304 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, | ||
305 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, | ||
306 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, | ||
307 | }), | ||
308 | ), | ||
309 | } | ||
310 | } | ||
311 | AttrDefId::FieldId(it) => { | ||
312 | return Self { attrs: db.fields_attrs(it.parent)[it.local_id].clone(), owner: def }; | ||
313 | } | ||
314 | AttrDefId::EnumVariantId(it) => { | ||
315 | return Self { | ||
316 | attrs: db.variants_attrs(it.parent)[it.local_id].clone(), | ||
317 | owner: def, | ||
318 | }; | ||
319 | } | ||
320 | AttrDefId::AdtId(it) => match it { | ||
321 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
322 | AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
323 | AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
324 | }, | ||
325 | AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
326 | AttrDefId::MacroDefId(it) => it | ||
327 | .ast_id() | ||
328 | .left() | ||
329 | .map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)), | ||
330 | AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
331 | AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
332 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
333 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
334 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
335 | AttrDefId::GenericParamId(it) => match it { | ||
336 | GenericParamId::TypeParamId(it) => { | ||
337 | let src = it.parent.child_source(db); | ||
338 | RawAttrs::from_attrs_owner( | ||
339 | db, | ||
340 | src.with_value( | ||
341 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
342 | ), | ||
343 | ) | ||
344 | } | ||
345 | GenericParamId::LifetimeParamId(it) => { | ||
346 | let src = it.parent.child_source(db); | ||
347 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
348 | } | ||
349 | GenericParamId::ConstParamId(it) => { | ||
350 | let src = it.parent.child_source(db); | ||
351 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
352 | } | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | let attrs = raw_attrs.filter(db, def.krate(db)); | ||
357 | Self { attrs, owner: def } | ||
358 | } | ||
359 | |||
360 | pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap { | ||
361 | let owner = match self.owner { | ||
362 | AttrDefId::ModuleId(module) => { | ||
363 | // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself). | ||
364 | |||
365 | let def_map = module.def_map(db); | ||
366 | let mod_data = &def_map[module.local_id]; | ||
367 | let attrs = match mod_data.declaration_source(db) { | ||
368 | Some(it) => { | ||
369 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | ||
370 | .map(|attr| InFile::new(it.file_id, attr)) | ||
371 | .collect(); | ||
372 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | ||
373 | mod_data.definition_source(db) | ||
374 | { | ||
375 | attrs.extend( | ||
376 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
377 | .map(|attr| InFile::new(file_id, attr)), | ||
378 | ) | ||
379 | } | ||
380 | attrs | ||
381 | } | ||
382 | None => { | ||
383 | let InFile { file_id, value } = mod_data.definition_source(db); | ||
384 | match &value { | ||
385 | ModuleSource::SourceFile(file) => { | ||
386 | collect_attrs(file as &dyn ast::AttrsOwner) | ||
387 | } | ||
388 | ModuleSource::Module(module) => { | ||
389 | collect_attrs(module as &dyn ast::AttrsOwner) | ||
390 | } | ||
391 | ModuleSource::BlockExpr(block) => { | ||
392 | collect_attrs(block as &dyn ast::AttrsOwner) | ||
393 | } | ||
394 | } | ||
395 | .map(|attr| InFile::new(file_id, attr)) | ||
396 | .collect() | ||
397 | } | ||
398 | }; | ||
399 | return AttrSourceMap { attrs }; | ||
400 | } | ||
401 | AttrDefId::FieldId(id) => { | ||
402 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | ||
403 | Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), | ||
404 | Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), | ||
405 | }) | ||
406 | } | ||
407 | AttrDefId::AdtId(adt) => match adt { | ||
408 | AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
409 | AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
410 | AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
411 | }, | ||
412 | AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
413 | AttrDefId::EnumVariantId(id) => id | ||
414 | .parent | ||
415 | .child_source(db) | ||
416 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
417 | AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
418 | AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
419 | AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
420 | AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
421 | AttrDefId::MacroDefId(id) => match id.ast_id() { | ||
422 | Either::Left(it) => { | ||
423 | it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))) | ||
424 | } | ||
425 | Either::Right(it) => { | ||
426 | it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))) | ||
427 | } | ||
428 | }, | ||
429 | AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
430 | AttrDefId::GenericParamId(id) => match id { | ||
431 | GenericParamId::TypeParamId(id) => { | ||
432 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | ||
433 | Either::Left(id) => ast::AttrsOwnerNode::new(id.clone()), | ||
434 | Either::Right(id) => ast::AttrsOwnerNode::new(id.clone()), | ||
435 | }) | ||
436 | } | ||
437 | GenericParamId::LifetimeParamId(id) => id | ||
438 | .parent | ||
439 | .child_source(db) | ||
440 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
441 | GenericParamId::ConstParamId(id) => id | ||
442 | .parent | ||
443 | .child_source(db) | ||
444 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
445 | }, | ||
446 | }; | ||
447 | |||
448 | AttrSourceMap { | ||
449 | attrs: collect_attrs(&owner.value) | ||
450 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
451 | .collect(), | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | |||
390 | fn inner_attributes( | 456 | fn inner_attributes( |
391 | syntax: &SyntaxNode, | 457 | syntax: &SyntaxNode, |
392 | ) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> { | 458 | ) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> { |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 276caf5b3..53df85089 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -8,7 +8,7 @@ use syntax::SmolStr; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
11 | attr::Attrs, | 11 | attr::{Attrs, AttrsWithOwner}, |
12 | body::{scope::ExprScopes, Body, BodySourceMap}, | 12 | body::{scope::ExprScopes, Body, BodySourceMap}, |
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | generics::GenericParams, | 14 | generics::GenericParams, |
@@ -120,8 +120,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
120 | #[salsa::invoke(Attrs::fields_attrs_query)] | 120 | #[salsa::invoke(Attrs::fields_attrs_query)] |
121 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | 121 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; |
122 | 122 | ||
123 | #[salsa::invoke(Attrs::attrs_query)] | 123 | #[salsa::invoke(AttrsWithOwner::attrs_query)] |
124 | fn attrs(&self, def: AttrDefId) -> Attrs; | 124 | fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; |
125 | 125 | ||
126 | #[salsa::invoke(LangItems::crate_lang_items_query)] | 126 | #[salsa::invoke(LangItems::crate_lang_items_query)] |
127 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; | 127 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; |
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 5722dea3a..00493a6b5 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -6,7 +6,7 @@ use either::Either; | |||
6 | use hir::{HasAttrs, InFile, Semantics}; | 6 | use hir::{HasAttrs, InFile, Semantics}; |
7 | use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; | 7 | use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; |
8 | use syntax::{ | 8 | use syntax::{ |
9 | ast::{self, AstNode, AttrsOwner, DocCommentsOwner}, | 9 | ast::{self, AstNode}, |
10 | match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, | 10 | match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, |
11 | }; | 11 | }; |
12 | 12 | ||
@@ -89,57 +89,27 @@ const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ | |||
89 | "edition2021", | 89 | "edition2021", |
90 | ]; | 90 | ]; |
91 | 91 | ||
92 | // Basically an owned dyn AttrsOwner without extra Boxing | ||
93 | struct AttrsOwnerNode { | ||
94 | node: SyntaxNode, | ||
95 | } | ||
96 | |||
97 | impl AttrsOwnerNode { | ||
98 | fn new<N: DocCommentsOwner>(node: N) -> Self { | ||
99 | AttrsOwnerNode { node: node.syntax().clone() } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | impl AttrsOwner for AttrsOwnerNode {} | ||
104 | impl AstNode for AttrsOwnerNode { | ||
105 | fn can_cast(_: syntax::SyntaxKind) -> bool | ||
106 | where | ||
107 | Self: Sized, | ||
108 | { | ||
109 | false | ||
110 | } | ||
111 | fn cast(_: SyntaxNode) -> Option<Self> | ||
112 | where | ||
113 | Self: Sized, | ||
114 | { | ||
115 | None | ||
116 | } | ||
117 | fn syntax(&self) -> &SyntaxNode { | ||
118 | &self.node | ||
119 | } | ||
120 | } | ||
121 | |||
122 | fn doc_attributes<'node>( | 92 | fn doc_attributes<'node>( |
123 | sema: &Semantics<RootDatabase>, | 93 | sema: &Semantics<RootDatabase>, |
124 | node: &'node SyntaxNode, | 94 | node: &'node SyntaxNode, |
125 | ) -> Option<(AttrsOwnerNode, hir::Attrs, Definition)> { | 95 | ) -> Option<(hir::AttrsWithOwner, Definition)> { |
126 | match_ast! { | 96 | match_ast! { |
127 | match node { | 97 | match node { |
128 | ast::SourceFile(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), | 98 | ast::SourceFile(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), |
129 | ast::Module(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), | 99 | ast::Module(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), |
130 | ast::Fn(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))), | 100 | ast::Fn(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))), |
131 | ast::Struct(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))), | 101 | ast::Struct(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))), |
132 | ast::Union(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))), | 102 | ast::Union(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))), |
133 | ast::Enum(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))), | 103 | ast::Enum(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))), |
134 | ast::Variant(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))), | 104 | ast::Variant(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))), |
135 | ast::Trait(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))), | 105 | ast::Trait(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))), |
136 | ast::Static(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))), | 106 | ast::Static(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))), |
137 | ast::Const(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))), | 107 | ast::Const(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))), |
138 | ast::TypeAlias(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))), | 108 | ast::TypeAlias(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))), |
139 | ast::Impl(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::SelfType(def))), | 109 | ast::Impl(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::SelfType(def))), |
140 | ast::RecordField(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Field(def))), | 110 | ast::RecordField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))), |
141 | ast::TupleField(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Field(def))), | 111 | ast::TupleField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))), |
142 | ast::MacroRules(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Macro(def))), | 112 | ast::MacroRules(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Macro(def))), |
143 | // ast::MacroDef(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), | 113 | // ast::MacroDef(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), |
144 | // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), | 114 | // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), |
145 | _ => return None | 115 | _ => return None |
@@ -153,7 +123,7 @@ pub(super) fn doc_comment( | |||
153 | sema: &Semantics<RootDatabase>, | 123 | sema: &Semantics<RootDatabase>, |
154 | node: InFile<&SyntaxNode>, | 124 | node: InFile<&SyntaxNode>, |
155 | ) { | 125 | ) { |
156 | let (owner, attributes, def) = match doc_attributes(sema, node.value) { | 126 | let (attributes, def) = match doc_attributes(sema, node.value) { |
157 | Some(it) => it, | 127 | Some(it) => it, |
158 | None => return, | 128 | None => return, |
159 | }; | 129 | }; |
@@ -161,12 +131,7 @@ pub(super) fn doc_comment( | |||
161 | let mut inj = Injector::default(); | 131 | let mut inj = Injector::default(); |
162 | inj.add_unmapped("fn doctest() {\n"); | 132 | inj.add_unmapped("fn doctest() {\n"); |
163 | 133 | ||
164 | let attrs_source_map = match def { | 134 | let attrs_source_map = attributes.source_map(sema.db); |
165 | Definition::ModuleDef(hir::ModuleDef::Module(module)) => { | ||
166 | attributes.source_map_for_module(sema.db, module.into()) | ||
167 | } | ||
168 | _ => attributes.source_map(node.with_value(&owner)), | ||
169 | }; | ||
170 | 135 | ||
171 | let mut is_codeblock = false; | 136 | let mut is_codeblock = false; |
172 | let mut is_doctest = false; | 137 | let mut is_doctest = false; |
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 38e0b04ef..7f472d4db 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs | |||
@@ -20,8 +20,8 @@ pub use self::{ | |||
20 | expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, | 20 | expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, |
21 | generated::{nodes::*, tokens::*}, | 21 | generated::{nodes::*, tokens::*}, |
22 | node_ext::{ | 22 | node_ext::{ |
23 | AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, | 23 | AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, |
24 | SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, | 24 | SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, |
25 | }, | 25 | }, |
26 | token_ext::*, | 26 | token_ext::*, |
27 | traits::*, | 27 | traits::*, |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 5a9834cbb..01f580a40 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -90,6 +90,36 @@ impl NameOwner for Macro { | |||
90 | 90 | ||
91 | impl AttrsOwner for Macro {} | 91 | impl AttrsOwner for Macro {} |
92 | 92 | ||
93 | /// Basically an owned `dyn AttrsOwner` without extra boxing. | ||
94 | pub struct AttrsOwnerNode { | ||
95 | node: SyntaxNode, | ||
96 | } | ||
97 | |||
98 | impl AttrsOwnerNode { | ||
99 | pub fn new<N: AttrsOwner>(node: N) -> Self { | ||
100 | AttrsOwnerNode { node: node.syntax().clone() } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | impl AttrsOwner for AttrsOwnerNode {} | ||
105 | impl AstNode for AttrsOwnerNode { | ||
106 | fn can_cast(_: SyntaxKind) -> bool | ||
107 | where | ||
108 | Self: Sized, | ||
109 | { | ||
110 | false | ||
111 | } | ||
112 | fn cast(_: SyntaxNode) -> Option<Self> | ||
113 | where | ||
114 | Self: Sized, | ||
115 | { | ||
116 | None | ||
117 | } | ||
118 | fn syntax(&self) -> &SyntaxNode { | ||
119 | &self.node | ||
120 | } | ||
121 | } | ||
122 | |||
93 | #[derive(Debug, Clone, PartialEq, Eq)] | 123 | #[derive(Debug, Clone, PartialEq, Eq)] |
94 | pub enum AttrKind { | 124 | pub enum AttrKind { |
95 | Inner, | 125 | Inner, |