diff options
author | Lukas Wirth <[email protected]> | 2021-03-17 10:22:40 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2021-03-17 10:22:40 +0000 |
commit | cdfb5c353f09138540ae66a2eb80a6a81802bbd6 (patch) | |
tree | 3fac436573b616e090565c38e232e49ad6f2b8d7 | |
parent | c766492d2625dba65c3bd933841c71938f6dc747 (diff) |
Remove quadratic attr source lookup
-rw-r--r-- | crates/hir_def/src/attr.rs | 25 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 3 |
2 files changed, 27 insertions, 1 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index e7019e0c9..7a6a41dc2 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -294,6 +294,13 @@ impl Attrs { | |||
294 | Arc::new(res) | 294 | Arc::new(res) |
295 | } | 295 | } |
296 | 296 | ||
297 | /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes. | ||
298 | /// | ||
299 | /// `owner` must be the original owner of the attributes. | ||
300 | pub fn source_map(&self, owner: &dyn AttrsOwner) -> AttrSourceMap { | ||
301 | AttrSourceMap { attrs: collect_attrs(owner).collect() } | ||
302 | } | ||
303 | |||
297 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 304 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
298 | AttrQuery { attrs: self, key } | 305 | AttrQuery { attrs: self, key } |
299 | } | 306 | } |
@@ -366,6 +373,24 @@ fn inner_attributes( | |||
366 | Some((attrs, docs)) | 373 | Some((attrs, docs)) |
367 | } | 374 | } |
368 | 375 | ||
376 | pub struct AttrSourceMap { | ||
377 | attrs: Vec<Either<ast::Attr, ast::Comment>>, | ||
378 | } | ||
379 | |||
380 | impl AttrSourceMap { | ||
381 | /// Maps the lowered `Attr` back to its original syntax node. | ||
382 | /// | ||
383 | /// `attr` must come from the `owner` used for AttrSourceMap | ||
384 | /// | ||
385 | /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of | ||
386 | /// the attribute represented by `Attr`. | ||
387 | pub fn source_of(&self, attr: &Attr) -> &Either<ast::Attr, ast::Comment> { | ||
388 | self.attrs | ||
389 | .get(attr.index as usize) | ||
390 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) | ||
391 | } | ||
392 | } | ||
393 | |||
369 | #[derive(Debug, Clone, PartialEq, Eq)] | 394 | #[derive(Debug, Clone, PartialEq, Eq)] |
370 | pub struct Attr { | 395 | pub struct Attr { |
371 | index: u32, | 396 | index: u32, |
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 0f1de4fb8..d4c367f66 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -153,6 +153,7 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n | |||
153 | if attributes.docs().map_or(true, |docs| !String::from(docs).contains(RUSTDOC_FENCE)) { | 153 | if attributes.docs().map_or(true, |docs| !String::from(docs).contains(RUSTDOC_FENCE)) { |
154 | return; | 154 | return; |
155 | } | 155 | } |
156 | let attrs_source_map = attributes.source_map(&owner); | ||
156 | 157 | ||
157 | let mut inj = Injector::default(); | 158 | let mut inj = Injector::default(); |
158 | inj.add_unmapped("fn doctest() {\n"); | 159 | inj.add_unmapped("fn doctest() {\n"); |
@@ -165,7 +166,7 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n | |||
165 | let mut new_comments = Vec::new(); | 166 | let mut new_comments = Vec::new(); |
166 | let mut string; | 167 | let mut string; |
167 | for attr in attributes.by_key("doc").attrs() { | 168 | for attr in attributes.by_key("doc").attrs() { |
168 | let src = attr.to_src(&owner); | 169 | let src = attrs_source_map.source_of(&attr); |
169 | let (line, range, prefix) = match &src { | 170 | let (line, range, prefix) = match &src { |
170 | Either::Left(it) => { | 171 | Either::Left(it) => { |
171 | string = match find_doc_string_in_attr(attr, it) { | 172 | string = match find_doc_string_in_attr(attr, it) { |