@@ -8,11 +8,11 @@ use hir::{
8
8
use ra_db:: { FilesDatabase , SourceRoot , SourceRootId , SyntaxDatabase } ;
9
9
use ra_editor:: { self , find_node_at_offset, LocalEdit , Severity } ;
10
10
use ra_syntax:: {
11
- algo:: find_covering_node,
11
+ algo:: { find_covering_node, visit :: { visitor , Visitor } } ,
12
12
ast:: { self , ArgListOwner , Expr , FnDef , NameOwner } ,
13
13
AstNode , SourceFileNode ,
14
14
SyntaxKind :: * ,
15
- SyntaxNodeRef , TextRange , TextUnit ,
15
+ SyntaxNode , SyntaxNodeRef , TextRange , TextUnit ,
16
16
} ;
17
17
18
18
use crate :: {
@@ -116,12 +116,13 @@ impl db::RootDatabase {
116
116
} ;
117
117
let decl = decl. borrowed ( ) ;
118
118
let decl_name = decl. name ( ) . unwrap ( ) ;
119
- let symbol = FileSymbol {
119
+ Ok ( vec ! [ NavigationTarget {
120
+ file_id,
120
121
name: decl_name. text( ) ,
121
- node_range : decl_name. syntax ( ) . range ( ) ,
122
+ range : decl_name. syntax( ) . range( ) ,
122
123
kind: MODULE ,
123
- } ;
124
- Ok ( vec ! [ NavigationTarget { file_id , symbol } ] )
124
+ ptr : None ,
125
+ } ] )
125
126
}
126
127
/// Returns `Vec` for the same reason as `parent_module`
127
128
pub ( crate ) fn crate_for ( & self , file_id : FileId ) -> Cancelable < Vec < CrateId > > {
@@ -153,14 +154,13 @@ impl db::RootDatabase {
153
154
let scope = fn_descr. scopes ( self ) ;
154
155
// First try to resolve the symbol locally
155
156
if let Some ( entry) = scope. resolve_local_name ( name_ref) {
156
- rr. add_resolution (
157
- position. file_id ,
158
- FileSymbol {
159
- name : entry. name ( ) . to_string ( ) . into ( ) ,
160
- node_range : entry. ptr ( ) . range ( ) ,
161
- kind : NAME ,
162
- } ,
163
- ) ;
157
+ rr. resolves_to . push ( NavigationTarget {
158
+ file_id : position. file_id ,
159
+ name : entry. name ( ) . to_string ( ) . into ( ) ,
160
+ range : entry. ptr ( ) . range ( ) ,
161
+ kind : NAME ,
162
+ ptr : None ,
163
+ } ) ;
164
164
return Ok ( Some ( rr) ) ;
165
165
} ;
166
166
}
@@ -182,12 +182,14 @@ impl db::RootDatabase {
182
182
Some ( name) => name. to_string ( ) . into ( ) ,
183
183
None => "" . into ( ) ,
184
184
} ;
185
- let symbol = FileSymbol {
185
+ let symbol = NavigationTarget {
186
+ file_id,
186
187
name,
187
- node_range : TextRange :: offset_len ( 0 . into ( ) , 0 . into ( ) ) ,
188
+ range : TextRange :: offset_len ( 0 . into ( ) , 0 . into ( ) ) ,
188
189
kind : MODULE ,
190
+ ptr : None ,
189
191
} ;
190
- rr. add_resolution ( file_id , symbol) ;
192
+ rr. resolves_to . push ( symbol) ;
191
193
return Ok ( Some ( rr) ) ;
192
194
}
193
195
}
@@ -253,8 +255,7 @@ impl db::RootDatabase {
253
255
}
254
256
}
255
257
pub ( crate ) fn doc_text_for ( & self , nav : NavigationTarget ) -> Cancelable < Option < String > > {
256
- let file = self . source_file ( nav. file_id ) ;
257
- let result = match ( nav. symbol . description ( & file) , nav. symbol . docs ( & file) ) {
258
+ let result = match ( nav. description ( self ) , nav. docs ( self ) ) {
258
259
( Some ( desc) , Some ( docs) ) => {
259
260
Some ( "```rust\n " . to_string ( ) + & * desc + "\n ```\n \n " + & * docs)
260
261
}
@@ -362,52 +363,52 @@ impl db::RootDatabase {
362
363
// Resolve the function's NameRef (NOTE: this isn't entirely accurate).
363
364
let file_symbols = self . index_resolve ( name_ref) ?;
364
365
for ( fn_file_id, fs) in file_symbols {
365
- if fs. kind == FN_DEF {
366
+ if fs. ptr . kind ( ) == FN_DEF {
366
367
let fn_file = self . source_file ( fn_file_id) ;
367
- if let Some ( fn_def) = find_node_at_offset ( fn_file. syntax ( ) , fs. node_range . start ( ) ) {
368
- let descr = ctry ! ( source_binder:: function_from_source(
369
- self , fn_file_id, fn_def
370
- ) ?) ;
371
- if let Some ( descriptor) = descr. signature_info ( self ) {
372
- // If we have a calling expression let's find which argument we are on
373
- let mut current_parameter = None ;
374
-
375
- let num_params = descriptor. params . len ( ) ;
376
- let has_self = fn_def. param_list ( ) . and_then ( |l| l. self_param ( ) ) . is_some ( ) ;
377
-
378
- if num_params == 1 {
379
- if !has_self {
380
- current_parameter = Some ( 0 ) ;
381
- }
382
- } else if num_params > 1 {
383
- // Count how many parameters into the call we are.
384
- // TODO: This is best effort for now and should be fixed at some point.
385
- // It may be better to see where we are in the arg_list and then check
386
- // where offset is in that list (or beyond).
387
- // Revisit this after we get documentation comments in.
388
- if let Some ( ref arg_list) = calling_node. arg_list ( ) {
389
- let start = arg_list. syntax ( ) . range ( ) . start ( ) ;
390
-
391
- let range_search = TextRange :: from_to ( start, position. offset ) ;
392
- let mut commas: usize = arg_list
393
- . syntax ( )
394
- . text ( )
395
- . slice ( range_search)
396
- . to_string ( )
397
- . matches ( ',' )
398
- . count ( ) ;
399
-
400
- // If we have a method call eat the first param since it's just self.
401
- if has_self {
402
- commas += 1 ;
403
- }
404
-
405
- current_parameter = Some ( commas) ;
406
- }
368
+ let fn_def = fs. ptr . resolve ( & fn_file) ;
369
+ let fn_def = ast:: FnDef :: cast ( fn_def. borrowed ( ) ) . unwrap ( ) ;
370
+ let descr = ctry ! ( source_binder:: function_from_source(
371
+ self , fn_file_id, fn_def
372
+ ) ?) ;
373
+ if let Some ( descriptor) = descr. signature_info ( self ) {
374
+ // If we have a calling expression let's find which argument we are on
375
+ let mut current_parameter = None ;
376
+
377
+ let num_params = descriptor. params . len ( ) ;
378
+ let has_self = fn_def. param_list ( ) . and_then ( |l| l. self_param ( ) ) . is_some ( ) ;
379
+
380
+ if num_params == 1 {
381
+ if !has_self {
382
+ current_parameter = Some ( 0 ) ;
407
383
}
384
+ } else if num_params > 1 {
385
+ // Count how many parameters into the call we are.
386
+ // TODO: This is best effort for now and should be fixed at some point.
387
+ // It may be better to see where we are in the arg_list and then check
388
+ // where offset is in that list (or beyond).
389
+ // Revisit this after we get documentation comments in.
390
+ if let Some ( ref arg_list) = calling_node. arg_list ( ) {
391
+ let start = arg_list. syntax ( ) . range ( ) . start ( ) ;
392
+
393
+ let range_search = TextRange :: from_to ( start, position. offset ) ;
394
+ let mut commas: usize = arg_list
395
+ . syntax ( )
396
+ . text ( )
397
+ . slice ( range_search)
398
+ . to_string ( )
399
+ . matches ( ',' )
400
+ . count ( ) ;
401
+
402
+ // If we have a method call eat the first param since it's just self.
403
+ if has_self {
404
+ commas += 1 ;
405
+ }
408
406
409
- return Ok ( Some ( ( descriptor, current_parameter) ) ) ;
407
+ current_parameter = Some ( commas) ;
408
+ }
410
409
}
410
+
411
+ return Ok ( Some ( ( descriptor, current_parameter) ) ) ;
411
412
}
412
413
}
413
414
}
@@ -511,3 +512,91 @@ impl<'a> FnCallNode<'a> {
511
512
}
512
513
}
513
514
}
515
+
516
+ impl NavigationTarget {
517
+ fn node ( & self , db : & db:: RootDatabase ) -> Option < SyntaxNode > {
518
+ let source_file = db. source_file ( self . file_id ) ;
519
+ let source_file = source_file. syntax ( ) ;
520
+ let node = source_file
521
+ . descendants ( )
522
+ . find ( |node| node. kind ( ) == self . kind && node. range ( ) == self . range ) ?
523
+ . owned ( ) ;
524
+ Some ( node)
525
+ }
526
+
527
+ fn docs ( & self , db : & db:: RootDatabase ) -> Option < String > {
528
+ let node = self . node ( db) ?;
529
+ let node = node. borrowed ( ) ;
530
+ fn doc_comments < ' a , N : ast:: DocCommentsOwner < ' a > > ( node : N ) -> Option < String > {
531
+ let comments = node. doc_comment_text ( ) ;
532
+ if comments. is_empty ( ) {
533
+ None
534
+ } else {
535
+ Some ( comments)
536
+ }
537
+ }
538
+
539
+ visitor ( )
540
+ . visit ( doc_comments :: < ast:: FnDef > )
541
+ . visit ( doc_comments :: < ast:: StructDef > )
542
+ . visit ( doc_comments :: < ast:: EnumDef > )
543
+ . visit ( doc_comments :: < ast:: TraitDef > )
544
+ . visit ( doc_comments :: < ast:: Module > )
545
+ . visit ( doc_comments :: < ast:: TypeDef > )
546
+ . visit ( doc_comments :: < ast:: ConstDef > )
547
+ . visit ( doc_comments :: < ast:: StaticDef > )
548
+ . accept ( node) ?
549
+ }
550
+
551
+ /// Get a description of this node.
552
+ ///
553
+ /// e.g. `struct Name`, `enum Name`, `fn Name`
554
+ fn description ( & self , db : & db:: RootDatabase ) -> Option < String > {
555
+ // TODO: After type inference is done, add type information to improve the output
556
+ let node = self . node ( db) ?;
557
+ let node = node. borrowed ( ) ;
558
+ // TODO: Refactor to be have less repetition
559
+ visitor ( )
560
+ . visit ( |node : ast:: FnDef | {
561
+ let mut string = "fn " . to_string ( ) ;
562
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
563
+ Some ( string)
564
+ } )
565
+ . visit ( |node : ast:: StructDef | {
566
+ let mut string = "struct " . to_string ( ) ;
567
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
568
+ Some ( string)
569
+ } )
570
+ . visit ( |node : ast:: EnumDef | {
571
+ let mut string = "enum " . to_string ( ) ;
572
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
573
+ Some ( string)
574
+ } )
575
+ . visit ( |node : ast:: TraitDef | {
576
+ let mut string = "trait " . to_string ( ) ;
577
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
578
+ Some ( string)
579
+ } )
580
+ . visit ( |node : ast:: Module | {
581
+ let mut string = "mod " . to_string ( ) ;
582
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
583
+ Some ( string)
584
+ } )
585
+ . visit ( |node : ast:: TypeDef | {
586
+ let mut string = "type " . to_string ( ) ;
587
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
588
+ Some ( string)
589
+ } )
590
+ . visit ( |node : ast:: ConstDef | {
591
+ let mut string = "const " . to_string ( ) ;
592
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
593
+ Some ( string)
594
+ } )
595
+ . visit ( |node : ast:: StaticDef | {
596
+ let mut string = "static " . to_string ( ) ;
597
+ node. name ( ) ?. syntax ( ) . text ( ) . push_to ( & mut string) ;
598
+ Some ( string)
599
+ } )
600
+ . accept ( node) ?
601
+ }
602
+ }
0 commit comments