@@ -10,7 +10,10 @@ use syntax::{
1010 match_ast, SyntaxNode ,
1111} ;
1212
13- use crate :: { display:: ToNav , FileId , NavigationTarget } ;
13+ use crate :: {
14+ display:: { ToNav , TryToNav } ,
15+ FileId , NavigationTarget ,
16+ } ;
1417
1518#[ derive( Debug , Clone ) ]
1619pub struct Runnable {
@@ -101,125 +104,109 @@ pub(crate) fn runnable(
101104 item : SyntaxNode ,
102105 file_id : FileId ,
103106) -> Option < Runnable > {
104- match_ast ! {
105- match item {
106- ast:: Struct ( it) => runnable_struct( sema, it, file_id) ,
107+ let runnable_item = match_ast ! {
108+ match ( item. clone( ) ) {
107109 ast:: Fn ( it) => runnable_fn( sema, it, file_id) ,
108110 ast:: Module ( it) => runnable_mod( sema, it) ,
109111 _ => None ,
110112 }
111- }
113+ } ;
114+ runnable_item. or_else ( || runnable_doctest ( sema, item) )
112115}
113116
114- fn runnable_fn (
115- sema : & Semantics < RootDatabase > ,
116- fn_def : ast:: Fn ,
117- file_id : FileId ,
118- ) -> Option < Runnable > {
119- let def = sema. to_def ( & fn_def) ?;
120- let name_string = fn_def. name ( ) ?. text ( ) . to_string ( ) ;
117+ fn runnable_fn ( sema : & Semantics < RootDatabase > , func : ast:: Fn , file_id : FileId ) -> Option < Runnable > {
118+ let def = sema. to_def ( & func) ?;
119+ let name_string = func. name ( ) ?. text ( ) . to_string ( ) ;
121120
122- let attrs = def. attrs ( sema. db ) ;
123121 let kind = if name_string == "main" {
124122 RunnableKind :: Bin
125123 } else {
126- let test_id = match sema. to_def ( & fn_def) . map ( |def| def. module ( sema. db ) ) {
127- Some ( module) => {
128- let def = sema. to_def ( & fn_def) ?;
129- let impl_trait_name = def. as_assoc_item ( sema. db ) . and_then ( |assoc_item| {
130- match assoc_item. container ( sema. db ) {
131- hir:: AssocItemContainer :: Trait ( trait_item) => {
132- Some ( trait_item. name ( sema. db ) . to_string ( ) )
133- }
134- hir:: AssocItemContainer :: Impl ( impl_def) => impl_def
135- . target_ty ( sema. db )
136- . as_adt ( )
137- . map ( |adt| adt. name ( sema. db ) . to_string ( ) ) ,
138- }
139- } ) ;
140-
141- let path_iter = module
142- . path_to_root ( sema. db )
143- . into_iter ( )
144- . rev ( )
145- . filter_map ( |it| it. name ( sema. db ) )
146- . map ( |name| name. to_string ( ) ) ;
147-
148- let path = if let Some ( impl_trait_name) = impl_trait_name {
149- path_iter
150- . chain ( std:: iter:: once ( impl_trait_name) )
151- . chain ( std:: iter:: once ( name_string) )
152- . join ( "::" )
153- } else {
154- path_iter. chain ( std:: iter:: once ( name_string) ) . join ( "::" )
155- } ;
156-
157- TestId :: Path ( path)
158- }
159- None => TestId :: Name ( name_string) ,
160- } ;
161-
162- if test_related_attribute ( & fn_def) . is_some ( ) {
163- let attr = TestAttr :: from_fn ( & fn_def) ;
124+ let canonical_path = sema. to_def ( & func) . and_then ( |def| {
125+ let def: hir:: ModuleDef = def. into ( ) ;
126+ def. canonical_path ( sema. db )
127+ } ) ;
128+ let test_id = canonical_path. map ( TestId :: Path ) . unwrap_or ( TestId :: Name ( name_string) ) ;
129+
130+ if test_related_attribute ( & func) . is_some ( ) {
131+ let attr = TestAttr :: from_fn ( & func) ;
164132 RunnableKind :: Test { test_id, attr }
165- } else if fn_def . has_atom_attr ( "bench" ) {
133+ } else if func . has_atom_attr ( "bench" ) {
166134 RunnableKind :: Bench { test_id }
167- } else if has_runnable_doc_test ( & attrs) {
168- RunnableKind :: DocTest { test_id }
169135 } else {
170136 return None ;
171137 }
172138 } ;
173139
174- let cfg = attrs. cfg ( ) ;
175-
176- let nav = if let RunnableKind :: DocTest { .. } = kind {
177- NavigationTarget :: from_doc_commented (
178- sema. db ,
179- InFile :: new ( file_id. into ( ) , & fn_def) ,
180- InFile :: new ( file_id. into ( ) , & fn_def) ,
181- )
182- } else {
183- NavigationTarget :: from_named ( sema. db , InFile :: new ( file_id. into ( ) , & fn_def) )
184- } ;
140+ let nav = NavigationTarget :: from_named ( sema. db , InFile :: new ( file_id. into ( ) , & func) ) ;
141+ let cfg = def. attrs ( sema. db ) . cfg ( ) ;
185142 Some ( Runnable { nav, kind, cfg } )
186143}
187144
188- fn runnable_struct (
189- sema : & Semantics < RootDatabase > ,
190- struct_def : ast:: Struct ,
191- file_id : FileId ,
192- ) -> Option < Runnable > {
193- let def = sema. to_def ( & struct_def) ?;
194- let name_string = struct_def. name ( ) ?. text ( ) . to_string ( ) ;
145+ fn runnable_doctest ( sema : & Semantics < RootDatabase > , item : SyntaxNode ) -> Option < Runnable > {
146+ match_ast ! {
147+ match item {
148+ ast:: Fn ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
149+ ast:: Struct ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
150+ ast:: Enum ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
151+ ast:: Union ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
152+ ast:: Trait ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
153+ ast:: Const ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
154+ ast:: Static ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
155+ ast:: TypeAlias ( it) => module_def_doctest( sema, sema. to_def( & it) ?. into( ) ) ,
156+ _ => None ,
157+ }
158+ }
159+ }
195160
196- let attrs = def. attrs ( sema. db ) ;
161+ fn module_def_doctest ( sema : & Semantics < RootDatabase > , def : hir:: ModuleDef ) -> Option < Runnable > {
162+ let attrs = match def {
163+ hir:: ModuleDef :: Module ( it) => it. attrs ( sema. db ) ,
164+ hir:: ModuleDef :: Function ( it) => it. attrs ( sema. db ) ,
165+ hir:: ModuleDef :: Adt ( it) => it. attrs ( sema. db ) ,
166+ hir:: ModuleDef :: EnumVariant ( it) => it. attrs ( sema. db ) ,
167+ hir:: ModuleDef :: Const ( it) => it. attrs ( sema. db ) ,
168+ hir:: ModuleDef :: Static ( it) => it. attrs ( sema. db ) ,
169+ hir:: ModuleDef :: Trait ( it) => it. attrs ( sema. db ) ,
170+ hir:: ModuleDef :: TypeAlias ( it) => it. attrs ( sema. db ) ,
171+ hir:: ModuleDef :: BuiltinType ( _) => return None ,
172+ } ;
197173 if !has_runnable_doc_test ( & attrs) {
198174 return None ;
199175 }
200- let cfg = attrs. cfg ( ) ;
201-
202- let test_id = match sema. to_def ( & struct_def) . map ( |def| def. module ( sema. db ) ) {
203- Some ( module) => {
204- let path_iter = module
205- . path_to_root ( sema. db )
206- . into_iter ( )
207- . rev ( )
208- . filter_map ( |it| it. name ( sema. db ) )
209- . map ( |name| name. to_string ( ) ) ;
210- let path = path_iter. chain ( std:: iter:: once ( name_string) ) . join ( "::" ) ;
211-
212- TestId :: Path ( path)
213- }
214- None => TestId :: Name ( name_string) ,
215- } ;
216-
217- let nav = NavigationTarget :: from_doc_commented (
218- sema. db ,
219- InFile :: new ( file_id. into ( ) , & struct_def) ,
220- InFile :: new ( file_id. into ( ) , & struct_def) ,
221- ) ;
222- Some ( Runnable { nav, kind : RunnableKind :: DocTest { test_id } , cfg } )
176+ let def_name = def. name ( sema. db ) . map ( |it| it. to_string ( ) ) ;
177+ let test_id = def
178+ . canonical_path ( sema. db )
179+ // This probably belongs to canonical path?
180+ . map ( |path| {
181+ let assoc_def = match def {
182+ hir:: ModuleDef :: Function ( it) => it. as_assoc_item ( sema. db ) ,
183+ hir:: ModuleDef :: Const ( it) => it. as_assoc_item ( sema. db ) ,
184+ hir:: ModuleDef :: TypeAlias ( it) => it. as_assoc_item ( sema. db ) ,
185+ _ => None ,
186+ } ;
187+ // FIXME: this also looks very wrong
188+ if let Some ( assoc_def) = assoc_def {
189+ if let hir:: AssocItemContainer :: Impl ( imp) = assoc_def. container ( sema. db ) {
190+ if let Some ( adt) = imp. target_ty ( sema. db ) . as_adt ( ) {
191+ let name = adt. name ( sema. db ) . to_string ( ) ;
192+ let idx = path. rfind ( ':' ) . unwrap_or ( 0 ) ;
193+ let ( prefix, suffix) = path. split_at ( idx) ;
194+ return format ! ( "{}{}::{}" , prefix, name, suffix) ;
195+ }
196+ }
197+ }
198+ path
199+ } )
200+ . map ( TestId :: Path )
201+ . or_else ( || def_name. clone ( ) . map ( TestId :: Name ) ) ?;
202+
203+ let mut nav = def. try_to_nav ( sema. db ) ?;
204+ nav. focus_range = None ;
205+ nav. description = None ;
206+ nav. docs = None ;
207+ nav. kind = syntax:: SyntaxKind :: COMMENT ;
208+ let res = Runnable { nav, kind : RunnableKind :: DocTest { test_id } , cfg : attrs. cfg ( ) } ;
209+ Some ( res)
223210}
224211
225212#[ derive( Debug , Copy , Clone ) ]
@@ -317,7 +304,7 @@ mod tests {
317304
318305 use crate :: fixture;
319306
320- use super :: { RunnableAction , BENCH , BIN , DOCTEST , TEST } ;
307+ use super :: * ;
321308
322309 fn check (
323310 ra_fixture : & str ,
@@ -546,7 +533,7 @@ struct StructWithRunnable(String);
546533 full_range: 15..74,
547534 focus_range: None,
548535 name: "should_have_runnable",
549- kind: FN ,
536+ kind: COMMENT ,
550537 container_name: None,
551538 description: None,
552539 docs: None,
@@ -566,7 +553,7 @@ struct StructWithRunnable(String);
566553 full_range: 76..148,
567554 focus_range: None,
568555 name: "should_have_runnable_1",
569- kind: FN ,
556+ kind: COMMENT ,
570557 container_name: None,
571558 description: None,
572559 docs: None,
@@ -586,7 +573,7 @@ struct StructWithRunnable(String);
586573 full_range: 150..254,
587574 focus_range: None,
588575 name: "should_have_runnable_2",
589- kind: FN ,
576+ kind: COMMENT ,
590577 container_name: None,
591578 description: None,
592579 docs: None,
@@ -606,7 +593,7 @@ struct StructWithRunnable(String);
606593 full_range: 756..821,
607594 focus_range: None,
608595 name: "StructWithRunnable",
609- kind: STRUCT ,
596+ kind: COMMENT ,
610597 container_name: None,
611598 description: None,
612599 docs: None,
@@ -668,7 +655,7 @@ impl Data {
668655 full_range: 44..98,
669656 focus_range: None,
670657 name: "foo",
671- kind: FN ,
658+ kind: COMMENT ,
672659 container_name: None,
673660 description: None,
674661 docs: None,
0 commit comments