aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/attrs.rs8
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/hir_def/src/attr.rs312
-rw-r--r--crates/hir_def/src/db.rs6
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs73
-rw-r--r--crates/syntax/src/ast.rs4
-rw-r--r--crates/syntax/src/ast/node_ext.rs30
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.
2use hir_def::{ 2use 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
18pub trait HasAttrs { 18pub 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 {
36macro_rules! impl_has_attrs { 36macro_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![
70macro_rules! impl_has_attrs_enum { 70macro_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::{
89pub use { 89pub 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)]
52pub struct Attrs(RawAttrs); 52pub struct Attrs(RawAttrs);
53 53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct AttrsWithOwner {
56 attrs: Attrs,
57 owner: AttrDefId,
58}
59
54impl ops::Deref for RawAttrs { 60impl 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
82impl ops::Deref for AttrsWithOwner {
83 type Target = Attrs;
84
85 fn deref(&self) -> &Attrs {
86 &self.attrs
87 }
88}
89
76impl RawAttrs { 90impl 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 {
169impl Attrs { 183impl 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
282impl 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
390fn inner_attributes( 456fn 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
9use crate::{ 9use 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;
6use hir::{HasAttrs, InFile, Semantics}; 6use hir::{HasAttrs, InFile, Semantics};
7use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; 7use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind};
8use syntax::{ 8use 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
93struct AttrsOwnerNode {
94 node: SyntaxNode,
95}
96
97impl AttrsOwnerNode {
98 fn new<N: DocCommentsOwner>(node: N) -> Self {
99 AttrsOwnerNode { node: node.syntax().clone() }
100 }
101}
102
103impl AttrsOwner for AttrsOwnerNode {}
104impl 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
122fn doc_attributes<'node>( 92fn 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
91impl AttrsOwner for Macro {} 91impl AttrsOwner for Macro {}
92 92
93/// Basically an owned `dyn AttrsOwner` without extra boxing.
94pub struct AttrsOwnerNode {
95 node: SyntaxNode,
96}
97
98impl AttrsOwnerNode {
99 pub fn new<N: AttrsOwner>(node: N) -> Self {
100 AttrsOwnerNode { node: node.syntax().clone() }
101 }
102}
103
104impl AttrsOwner for AttrsOwnerNode {}
105impl 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)]
94pub enum AttrKind { 124pub enum AttrKind {
95 Inner, 125 Inner,