Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_def/src/attr.rs')
-rw-r--r--crates/hir_def/src/attr.rs30
1 files changed, 27 insertions, 3 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index ef86572fe5..70fa249a5b 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -17,7 +17,7 @@ use la_arena::ArenaMap;
use mbe::{syntax_node_to_token_tree, DelimiterKind};
use smallvec::{smallvec, SmallVec};
use syntax::{
- ast::{self, AstNode, AttrsOwner},
+ ast::{self, AstNode, AttrsOwner, IsString},
match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
};
use tt::Subtree;
@@ -610,6 +610,7 @@ pub struct DocsRangeMap {
}
impl DocsRangeMap {
+ /// Maps a [`TextRange`] relative to the documentation string back to its AST range
pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> {
let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?;
let (line_docs_range, idx, original_line_src_range) = self.mapping[found];
@@ -621,8 +622,15 @@ impl DocsRangeMap {
let InFile { file_id, value: source } = self.source_map.source_of_id(idx);
match source {
- Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here
- // as well as for whats done in syntax highlight doc injection
+ Either::Left(attr) => {
+ let string = get_doc_string_in_attr(&attr)?;
+ let text_range = string.open_quote_text_range()?;
+ let range = TextRange::at(
+ text_range.end() + original_line_src_range.start() + relative_range.start(),
+ string.syntax().text_range().len().min(range.len()),
+ );
+ Some(InFile { file_id, value: range })
+ }
Either::Right(comment) => {
let text_range = comment.syntax().text_range();
let range = TextRange::at(
@@ -638,6 +646,22 @@ impl DocsRangeMap {
}
}
+fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
+ match it.expr() {
+ // #[doc = lit]
+ Some(ast::Expr::Literal(lit)) => match lit.kind() {
+ ast::LiteralKind::String(it) => Some(it),
+ _ => None,
+ },
+ // #[cfg_attr(..., doc = "", ...)]
+ None => {
+ // FIXME: See highlight injection for what to do here
+ None
+ }
+ _ => None,
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct AttrId {
is_doc_comment: bool,