diff options
Diffstat (limited to 'crates/ide/src/syntax_highlighting/inject.rs')
-rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 086db40e5..0f1de4fb8 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -5,7 +5,7 @@ use hir::{HasAttrs, Semantics}; | |||
5 | use ide_db::call_info::ActiveParameter; | 5 | use ide_db::call_info::ActiveParameter; |
6 | use syntax::{ | 6 | use syntax::{ |
7 | ast::{self, AstNode, AttrsOwner, DocCommentsOwner}, | 7 | ast::{self, AstNode, AttrsOwner, DocCommentsOwner}, |
8 | match_ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize, | 8 | match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{Analysis, HlMod, HlRange, HlTag, RootDatabase}; | 11 | use crate::{Analysis, HlMod, HlRange, HlTag, RootDatabase}; |
@@ -153,7 +153,6 @@ 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 doc_comments = attributes.by_key("doc").attrs().map(|attr| attr.to_src(&owner)); | ||
157 | 156 | ||
158 | let mut inj = Injector::default(); | 157 | let mut inj = Injector::default(); |
159 | inj.add_unmapped("fn doctest() {\n"); | 158 | inj.add_unmapped("fn doctest() {\n"); |
@@ -164,13 +163,28 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n | |||
164 | // Replace the original, line-spanning comment ranges by new, only comment-prefix | 163 | // Replace the original, line-spanning comment ranges by new, only comment-prefix |
165 | // spanning comment ranges. | 164 | // spanning comment ranges. |
166 | let mut new_comments = Vec::new(); | 165 | let mut new_comments = Vec::new(); |
167 | for comment in doc_comments { | 166 | let mut string; |
168 | let (line, range, prefix) = match &comment { | 167 | for attr in attributes.by_key("doc").attrs() { |
169 | Either::Left(_) => continue, // FIXME | 168 | let src = attr.to_src(&owner); |
169 | let (line, range, prefix) = match &src { | ||
170 | Either::Left(it) => { | ||
171 | string = match find_doc_string_in_attr(attr, it) { | ||
172 | Some(it) => it, | ||
173 | None => continue, | ||
174 | }; | ||
175 | let text_range = string.syntax().text_range(); | ||
176 | let text_range = TextRange::new( | ||
177 | text_range.start() + TextSize::from(1), | ||
178 | text_range.end() - TextSize::from(1), | ||
179 | ); | ||
180 | let text = string.text(); | ||
181 | (&text[1..text.len() - 1], text_range, "") | ||
182 | } | ||
170 | Either::Right(comment) => { | 183 | Either::Right(comment) => { |
171 | (comment.text(), comment.syntax().text_range(), comment.prefix()) | 184 | (comment.text(), comment.syntax().text_range(), comment.prefix()) |
172 | } | 185 | } |
173 | }; | 186 | }; |
187 | |||
174 | match line.find(RUSTDOC_FENCE) { | 188 | match line.find(RUSTDOC_FENCE) { |
175 | Some(idx) => { | 189 | Some(idx) => { |
176 | is_codeblock = !is_codeblock; | 190 | is_codeblock = !is_codeblock; |
@@ -222,3 +236,27 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n | |||
222 | }); | 236 | }); |
223 | } | 237 | } |
224 | } | 238 | } |
239 | |||
240 | fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::String> { | ||
241 | match it.literal() { | ||
242 | // #[doc = lit] | ||
243 | Some(lit) => match lit.kind() { | ||
244 | ast::LiteralKind::String(it) => Some(it), | ||
245 | _ => None, | ||
246 | }, | ||
247 | // #[cfg_attr(..., doc = "", ...)] | ||
248 | None => { | ||
249 | // We gotta hunt the string token manually here | ||
250 | let text = attr.string_value()?; | ||
251 | // FIXME: We just pick the first string literal that has the same text as the doc attribute | ||
252 | // This means technically we might highlight the wrong one | ||
253 | it.syntax() | ||
254 | .descendants_with_tokens() | ||
255 | .filter_map(NodeOrToken::into_token) | ||
256 | .filter_map(ast::String::cast) | ||
257 | .find(|string| { | ||
258 | string.text().get(1..string.text().len() - 1).map_or(false, |it| it == text) | ||
259 | }) | ||
260 | } | ||
261 | } | ||
262 | } | ||