@@ -5,15 +5,17 @@ use lsp_types::{
5
5
FoldingRangeKind , FoldingRangeParams , Hover , HoverContents , Location , MarkupContent ,
6
6
MarkupKind , ParameterInformation , ParameterLabel , Position , PrepareRenameResponse , Range ,
7
7
RenameParams , SignatureInformation , SymbolInformation , TextDocumentIdentifier , TextEdit ,
8
- WorkspaceEdit
8
+ WorkspaceEdit ,
9
9
} ;
10
10
use ra_ide_api:: {
11
11
FileId , FilePosition , FileRange , FoldKind , Query , RangeInfo , RunnableKind , Severity , Cancelable ,
12
12
} ;
13
- use ra_syntax:: { AstNode , TextUnit } ;
13
+ use ra_syntax:: { AstNode , SyntaxKind , TextUnit } ;
14
14
use rustc_hash:: FxHashMap ;
15
+ use serde:: { Serialize , Deserialize } ;
15
16
use serde_json:: to_value;
16
17
use std:: io:: Write ;
18
+ use url_serde:: Ser ;
17
19
18
20
use crate :: {
19
21
cargo_target_spec:: { runnable_args, CargoTargetSpec } ,
@@ -596,6 +598,10 @@ pub fn handle_code_action(
596
598
for source_edit in assists. chain ( fixes) {
597
599
let title = source_edit. label . clone ( ) ;
598
600
let edit = source_edit. try_conv_with ( & world) ?;
601
+
602
+ // We cannot use the 'editor.action.showReferences' command directly
603
+ // because that command requires vscode types which we convert in the handler
604
+ // on the client side.
599
605
let cmd = Command {
600
606
title,
601
607
command : "rust-analyzer.applySourceChange" . to_string ( ) ,
@@ -616,6 +622,7 @@ pub fn handle_code_lens(
616
622
617
623
let mut lenses: Vec < CodeLens > = Default :: default ( ) ;
618
624
625
+ // Gather runnables
619
626
for runnable in world. analysis ( ) . runnables ( file_id) ? {
620
627
let title = match & runnable. kind {
621
628
RunnableKind :: Test { name : _ } | RunnableKind :: TestMod { path : _ } => {
@@ -652,9 +659,87 @@ pub fn handle_code_lens(
652
659
}
653
660
}
654
661
662
+ // Handle impls
663
+ lenses. extend (
664
+ world
665
+ . analysis ( )
666
+ . file_structure ( file_id)
667
+ . into_iter ( )
668
+ . filter ( |it| match it. kind {
669
+ SyntaxKind :: TRAIT_DEF | SyntaxKind :: STRUCT_DEF | SyntaxKind :: ENUM_DEF => true ,
670
+ _ => false ,
671
+ } )
672
+ . map ( |it| {
673
+ let range = it. node_range . conv_with ( & line_index) ;
674
+ let pos = range. start ;
675
+ let lens_params =
676
+ req:: TextDocumentPositionParams :: new ( params. text_document . clone ( ) , pos) ;
677
+ CodeLens {
678
+ range,
679
+ command : None ,
680
+ data : Some ( to_value ( CodeLensResolveData :: Impls ( lens_params) ) . unwrap ( ) ) ,
681
+ }
682
+ } ) ,
683
+ ) ;
684
+
655
685
return Ok ( Some ( lenses) ) ;
656
686
}
657
687
688
+ #[ derive( Debug , Serialize , Deserialize ) ]
689
+ #[ serde( rename_all = "camelCase" ) ]
690
+ enum CodeLensResolveData {
691
+ Impls ( req:: TextDocumentPositionParams ) ,
692
+ }
693
+
694
+ pub fn handle_code_lens_resolve ( world : ServerWorld , code_lens : CodeLens ) -> Result < CodeLens > {
695
+ let data = code_lens. data . unwrap ( ) ;
696
+ let resolve = serde_json:: from_value ( data) ?;
697
+ match resolve {
698
+ Some ( CodeLensResolveData :: Impls ( lens_params) ) => {
699
+ let locations: Vec < Location > =
700
+ match handle_goto_implementation ( world, lens_params. clone ( ) ) ? {
701
+ Some ( req:: GotoDefinitionResponse :: Scalar ( loc) ) => vec ! [ loc] ,
702
+ Some ( req:: GotoDefinitionResponse :: Array ( locs) ) => locs,
703
+ Some ( req:: GotoDefinitionResponse :: Link ( links) ) => links
704
+ . into_iter ( )
705
+ . map ( |link| Location :: new ( link. target_uri , link. target_selection_range ) )
706
+ . collect ( ) ,
707
+ _ => vec ! [ ] ,
708
+ } ;
709
+
710
+ let title = if locations. len ( ) == 1 {
711
+ "1 implementation" . into ( )
712
+ } else {
713
+ format ! ( "{} implementations" , locations. len( ) )
714
+ } ;
715
+
716
+ return Ok ( CodeLens {
717
+ range : code_lens. range ,
718
+ command : Some ( Command {
719
+ title,
720
+ command : "rust-analyzer.showReferences" . into ( ) ,
721
+ arguments : Some ( vec ! [
722
+ to_value( & Ser :: new( & lens_params. text_document. uri) ) . unwrap( ) ,
723
+ to_value( code_lens. range. start) . unwrap( ) ,
724
+ to_value( locations) . unwrap( ) ,
725
+ ] ) ,
726
+ } ) ,
727
+ data : None ,
728
+ } ) ;
729
+ }
730
+ _ => {
731
+ return Ok ( CodeLens {
732
+ range : code_lens. range ,
733
+ command : Some ( Command {
734
+ title : "Error" . into ( ) ,
735
+ ..Default :: default ( )
736
+ } ) ,
737
+ data : None ,
738
+ } ) ;
739
+ }
740
+ }
741
+ }
742
+
658
743
pub fn handle_document_highlight (
659
744
world : ServerWorld ,
660
745
params : req:: TextDocumentPositionParams ,
0 commit comments