aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-01-11 13:24:50 +0000
committerAleksey Kladov <[email protected]>2021-01-11 13:24:50 +0000
commit8adf5cc0e364376183c0b8009b65bc9e46fa3e36 (patch)
tree58ec94a29bf262f2f90eaa9e63ca409d786fa01a /crates/ide/src
parent8c33ffecc1feea732f2ea18b3701c145adc73928 (diff)
Goto for inner doc links works for module inner doc comments
Diffstat (limited to 'crates/ide/src')
-rw-r--r--crates/ide/src/goto_definition.rs57
-rw-r--r--crates/ide/src/runnables.rs37
2 files changed, 54 insertions, 40 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index c20185b16..cd4afc804 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -6,15 +6,13 @@ use ide_db::{
6 symbol_index, RootDatabase, 6 symbol_index, RootDatabase,
7}; 7};
8use syntax::{ 8use syntax::{
9 ast::{self, NameOwner}, 9 ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T,
10 match_ast, AstNode, AstToken,
11 SyntaxKind::*,
12 SyntaxToken, TextSize, TokenAtOffset, T,
13}; 10};
14 11
15use crate::{ 12use crate::{
16 display::{ToNav, TryToNav}, 13 display::{ToNav, TryToNav},
17 doc_links::extract_definitions_from_markdown, 14 doc_links::extract_definitions_from_markdown,
15 runnables::doc_owner_to_def,
18 FilePosition, NavigationTarget, RangeInfo, SymbolKind, 16 FilePosition, NavigationTarget, RangeInfo, SymbolKind,
19}; 17};
20 18
@@ -84,31 +82,23 @@ fn def_for_doc_comment(
84 doc_comment: &ast::Comment, 82 doc_comment: &ast::Comment,
85) -> Option<hir::ModuleDef> { 83) -> Option<hir::ModuleDef> {
86 let parent = doc_comment.syntax().parent(); 84 let parent = doc_comment.syntax().parent();
87 let db = sema.db;
88 let (link, ns) = extract_positioned_link_from_comment(position, doc_comment)?; 85 let (link, ns) = extract_positioned_link_from_comment(position, doc_comment)?;
89 let link = &link; 86
90 let name = match_ast! { 87 let def = doc_owner_to_def(sema, parent)?;
91 match parent { 88 match def {
92 ast::Name(name) => Some(name),
93 ast::Fn(func) => func.name(),
94 _ => None,
95 }
96 }?;
97 let definition = NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db))?;
98 match definition {
99 Definition::ModuleDef(def) => match def { 89 Definition::ModuleDef(def) => match def {
100 ModuleDef::Module(it) => it.resolve_doc_path(db, link, ns), 90 ModuleDef::Module(it) => it.resolve_doc_path(sema.db, &link, ns),
101 ModuleDef::Function(it) => it.resolve_doc_path(db, link, ns), 91 ModuleDef::Function(it) => it.resolve_doc_path(sema.db, &link, ns),
102 ModuleDef::Adt(it) => it.resolve_doc_path(db, link, ns), 92 ModuleDef::Adt(it) => it.resolve_doc_path(sema.db, &link, ns),
103 ModuleDef::Variant(it) => it.resolve_doc_path(db, link, ns), 93 ModuleDef::Variant(it) => it.resolve_doc_path(sema.db, &link, ns),
104 ModuleDef::Const(it) => it.resolve_doc_path(db, link, ns), 94 ModuleDef::Const(it) => it.resolve_doc_path(sema.db, &link, ns),
105 ModuleDef::Static(it) => it.resolve_doc_path(db, link, ns), 95 ModuleDef::Static(it) => it.resolve_doc_path(sema.db, &link, ns),
106 ModuleDef::Trait(it) => it.resolve_doc_path(db, link, ns), 96 ModuleDef::Trait(it) => it.resolve_doc_path(sema.db, &link, ns),
107 ModuleDef::TypeAlias(it) => it.resolve_doc_path(db, link, ns), 97 ModuleDef::TypeAlias(it) => it.resolve_doc_path(sema.db, &link, ns),
108 ModuleDef::BuiltinType(_) => return None, 98 ModuleDef::BuiltinType(_) => return None,
109 }, 99 },
110 Definition::Macro(it) => it.resolve_doc_path(db, link, ns), 100 Definition::Macro(it) => it.resolve_doc_path(sema.db, &link, ns),
111 Definition::Field(it) => it.resolve_doc_path(db, link, ns), 101 Definition::Field(it) => it.resolve_doc_path(sema.db, &link, ns),
112 Definition::SelfType(_) 102 Definition::SelfType(_)
113 | Definition::Local(_) 103 | Definition::Local(_)
114 | Definition::GenericParam(_) 104 | Definition::GenericParam(_)
@@ -1212,7 +1202,7 @@ fn foo<'foo>(_: &'foo ()) {
1212 } 1202 }
1213 1203
1214 #[test] 1204 #[test]
1215 fn goto_def_for_intra_rustdoc_link_same_file() { 1205 fn goto_def_for_intra_doc_link_same_file() {
1216 check( 1206 check(
1217 r#" 1207 r#"
1218/// Blah, [`bar`](bar) .. [`foo`](foo)$0 has [`bar`](bar) 1208/// Blah, [`bar`](bar) .. [`foo`](foo)$0 has [`bar`](bar)
@@ -1225,4 +1215,19 @@ pub fn foo() { }
1225}"#, 1215}"#,
1226 ) 1216 )
1227 } 1217 }
1218
1219 #[test]
1220 fn goto_def_for_intra_doc_link_inner() {
1221 check(
1222 r#"
1223//- /main.rs
1224mod m;
1225struct S;
1226 //^
1227
1228//- /m.rs
1229//! [`super::S$0`]
1230"#,
1231 )
1232 }
1228} 1233}
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 3a1e204db..f5ee7de86 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -3,7 +3,7 @@ use std::fmt;
3use assists::utils::test_related_attribute; 3use assists::utils::test_related_attribute;
4use cfg::CfgExpr; 4use cfg::CfgExpr;
5use hir::{AsAssocItem, HasAttrs, HasSource, Semantics}; 5use hir::{AsAssocItem, HasAttrs, HasSource, Semantics};
6use ide_db::RootDatabase; 6use ide_db::{defs::Definition, RootDatabase};
7use itertools::Itertools; 7use itertools::Itertools;
8use syntax::{ 8use syntax::{
9 ast::{self, AstNode, AttrsOwner, ModuleItemOwner}, 9 ast::{self, AstNode, AttrsOwner, ModuleItemOwner},
@@ -110,7 +110,10 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
110 _ => None, 110 _ => None,
111 } 111 }
112 }; 112 };
113 runnable.or_else(|| runnable_doctest(&sema, item)) 113 runnable.or_else(|| match doc_owner_to_def(&sema, item)? {
114 Definition::ModuleDef(def) => module_def_doctest(&sema, def),
115 _ => None,
116 })
114 }) 117 })
115 .collect() 118 .collect()
116} 119}
@@ -170,20 +173,26 @@ pub(crate) fn runnable_mod(
170 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg }) 173 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg })
171} 174}
172 175
173fn runnable_doctest(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> { 176// FIXME: figure out a proper API here.
174 match_ast! { 177pub(crate) fn doc_owner_to_def(
178 sema: &Semantics<RootDatabase>,
179 item: SyntaxNode,
180) -> Option<Definition> {
181 let res: hir::ModuleDef = match_ast! {
175 match item { 182 match item {
176 ast::Fn(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 183 ast::SourceFile(it) => sema.scope(&item).module()?.into(),
177 ast::Struct(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 184 ast::Fn(it) => sema.to_def(&it)?.into(),
178 ast::Enum(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 185 ast::Struct(it) => sema.to_def(&it)?.into(),
179 ast::Union(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 186 ast::Enum(it) => sema.to_def(&it)?.into(),
180 ast::Trait(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 187 ast::Union(it) => sema.to_def(&it)?.into(),
181 ast::Const(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 188 ast::Trait(it) => sema.to_def(&it)?.into(),
182 ast::Static(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 189 ast::Const(it) => sema.to_def(&it)?.into(),
183 ast::TypeAlias(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), 190 ast::Static(it) => sema.to_def(&it)?.into(),
184 _ => None, 191 ast::TypeAlias(it) => sema.to_def(&it)?.into(),
192 _ => return None,
185 } 193 }
186 } 194 };
195 Some(Definition::ModuleDef(res))
187} 196}
188 197
189fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> { 198fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> {