@@ -120,7 +120,7 @@ impl LanguageClient {
120120 selectionUI_autoOpen,
121121 use_virtual_text,
122122 echo_project_root,
123- ) : ( Option < u64 > , String , Value , u8 , u8 , u8 ) = self . vim ( ) ?. eval (
123+ ) : ( Option < u64 > , String , Value , u8 , UseVirtualText , u8 ) = self . vim ( ) ?. eval (
124124 [
125125 "get(g:, 'LanguageClient_diagnosticsSignsMax', v:null)" ,
126126 "get(g:, 'LanguageClient_diagnosticsMaxSeverity', 'Hint')" ,
@@ -226,7 +226,7 @@ impl LanguageClient {
226226 state. wait_output_timeout = wait_output_timeout;
227227 state. hoverPreview = hoverPreview;
228228 state. completionPreferTextEdit = completionPreferTextEdit;
229- state. use_virtual_text = use_virtual_text == 1 ;
229+ state. use_virtual_text = use_virtual_text;
230230 state. echo_project_root = echo_project_root == 1 ;
231231 state. loggingFile = loggingFile;
232232 state. loggingLevel = loggingLevel;
@@ -850,6 +850,18 @@ impl LanguageClient {
850850 }
851851 }
852852 }
853+ "rust-analyzer.runSingle" | "rust-analyzer.run" => {
854+ if let Some ( ref args) = cmd. arguments {
855+ let args = args[ 0 ] . clone ( ) ;
856+ let bin: String =
857+ try_get ( "bin" , & args) ?. ok_or_else ( || err_msg ( "no bin found" ) ) ?;
858+ let arguments: Vec < String > = try_get ( "args" , & args) ?. unwrap_or_else ( || vec ! [ ] ) ;
859+ let cmd = format ! ( "term {} {}" , bin, arguments. join( " " ) ) ;
860+ let cmd = cmd. replace ( '"' , "" ) ;
861+ self . vim ( ) ?. command ( cmd) ?;
862+ }
863+ }
864+ // TODO: implement all other rust-analyzer actions
853865 _ => return Ok ( false ) ,
854866 }
855867
@@ -1000,6 +1012,9 @@ impl LanguageClient {
10001012 publish_diagnostics : Some ( PublishDiagnosticsCapability {
10011013 related_information : Some ( true ) ,
10021014 } ) ,
1015+ code_lens : Some ( GenericCapability {
1016+ dynamic_registration : Some ( true ) ,
1017+ } ) ,
10031018 ..TextDocumentClientCapabilities :: default ( )
10041019 } ) ,
10051020 workspace : Some ( WorkspaceClientCapabilities {
@@ -1759,6 +1774,74 @@ impl LanguageClient {
17591774 Ok ( ( ) )
17601775 }
17611776
1777+ pub fn languageClient_handleCodeLensAction ( & self , params : & Value ) -> Fallible < Value > {
1778+ let filename = self . vim ( ) ?. get_filename ( params) ?;
1779+ let line = self . vim ( ) ?. get_position ( params) ?. line ;
1780+
1781+ let mut code_lens: Vec < CodeLens > =
1782+ self . get ( |state| state. code_lens . get ( filename. as_str ( ) ) . cloned ( ) . unwrap ( ) ) ?;
1783+ code_lens. retain ( |cl| cl. range . start . line == line) ;
1784+ if code_lens. len ( ) != 1 {
1785+ return Ok ( Value :: Null ) ;
1786+ }
1787+
1788+ if let Some ( command) = code_lens. pop ( ) . unwrap ( ) . command {
1789+ if !self . try_handle_command_by_client ( & command) ? {
1790+ let params = json ! ( {
1791+ "command" : command. command,
1792+ "arguments" : command. arguments,
1793+ } ) ;
1794+ self . workspace_executeCommand ( & params) ?;
1795+ }
1796+ }
1797+
1798+ Ok ( Value :: Null )
1799+ }
1800+
1801+ pub fn textDocument_codeLens ( & self , params : & Value ) -> Fallible < Value > {
1802+ let use_virtual_text = self . get ( |state| state. use_virtual_text . clone ( ) ) ?;
1803+ if UseVirtualText :: No == use_virtual_text || UseVirtualText :: Diagnostics == use_virtual_text
1804+ {
1805+ return Ok ( Value :: Null ) ;
1806+ }
1807+
1808+ info ! ( "Begin {}" , lsp:: request:: CodeLensRequest :: METHOD ) ;
1809+ let filename = self . vim ( ) ?. get_filename ( params) ?;
1810+ let language_id = self . vim ( ) ?. get_languageId ( & filename, params) ?;
1811+ let client = self . get_client ( & Some ( language_id) ) ?;
1812+ let input = lsp:: CodeLensParams {
1813+ text_document : TextDocumentIdentifier {
1814+ uri : filename. to_url ( ) ?,
1815+ } ,
1816+ } ;
1817+
1818+ let results: Value = client. call ( lsp:: request:: CodeLensRequest :: METHOD , & input) ?;
1819+
1820+ let code_lens: Option < Vec < CodeLens > > = serde_json:: from_value ( results. clone ( ) ) ?;
1821+ let mut resolved_code_lens = vec ! [ ] ;
1822+ if let Some ( code_lens) = code_lens {
1823+ for item in code_lens {
1824+ let mut item = item;
1825+ if let Some ( _d) = & item. data {
1826+ if let Some ( cl) = client. call ( lsp:: request:: CodeLensResolve :: METHOD , & item) ? {
1827+ item = cl;
1828+ }
1829+ }
1830+ resolved_code_lens. push ( item) ;
1831+ }
1832+ }
1833+
1834+ self . update ( |state| {
1835+ state
1836+ . code_lens
1837+ . insert ( filename. to_owned ( ) , resolved_code_lens) ;
1838+ Ok ( Value :: Null )
1839+ } ) ?;
1840+
1841+ info ! ( "End {}" , lsp:: request:: CodeLensRequest :: METHOD ) ;
1842+ Ok ( results)
1843+ }
1844+
17621845 pub fn textDocument_didOpen ( & self , params : & Value ) -> Fallible < ( ) > {
17631846 info ! ( "Begin {}" , lsp:: notification:: DidOpenTextDocument :: METHOD ) ;
17641847 let filename = self . vim ( ) ?. get_filename ( params) ?;
@@ -1794,6 +1877,8 @@ impl LanguageClient {
17941877 . rpcclient
17951878 . notify ( "s:ExecuteAutocmd" , "LanguageClientTextDocumentDidOpenPost" ) ?;
17961879
1880+ self . textDocument_codeLens ( params) ?;
1881+
17971882 info ! ( "End {}" , lsp:: notification:: DidOpenTextDocument :: METHOD ) ;
17981883 Ok ( ( ) )
17991884 }
@@ -1854,6 +1939,8 @@ impl LanguageClient {
18541939 } ,
18551940 ) ?;
18561941
1942+ self . textDocument_codeLens ( params) ?;
1943+
18571944 info ! ( "End {}" , lsp:: notification:: DidChangeTextDocument :: METHOD ) ;
18581945 Ok ( ( ) )
18591946 }
@@ -2347,7 +2434,9 @@ impl LanguageClient {
23472434 if !self . get ( |state| state. serverCommands . contains_key ( & languageId) ) ? {
23482435 return Ok ( ( ) ) ;
23492436 }
2350- if !self . get ( |state| state. diagnostics . contains_key ( & filename) ) ? {
2437+ if !self . get ( |state| state. diagnostics . contains_key ( & filename) ) ?
2438+ && !self . get ( |state| state. code_lens . contains_key ( & filename) ) ?
2439+ {
23512440 return Ok ( ( ) ) ;
23522441 }
23532442
@@ -2500,40 +2589,67 @@ impl LanguageClient {
25002589 . notify ( "s:AddHighlights" , json ! ( [ source, highlights] ) ) ?;
25012590 }
25022591
2503- if self . get ( |state| state . use_virtual_text ) ? {
2504- let namespace_id = self . get_or_create_namespace ( ) ?;
2592+ let mut virtual_texts = vec ! [ ] ;
2593+ let use_virtual_text = self . get ( |state| state . use_virtual_text . clone ( ) ) ?;
25052594
2506- let mut virtual_texts = vec ! [ ] ;
2507- self . update ( |state| {
2508- if let Some ( diag_list) = state. diagnostics . get ( & filename) {
2509- for diag in diag_list {
2510- if viewport. overlaps ( diag. range ) {
2511- virtual_texts. push ( VirtualText {
2512- line : diag. range . start . line ,
2513- text : diag. message . replace ( "\n " , " " ) . clone ( ) ,
2514- hl_group : state
2515- . diagnosticsDisplay
2516- . get (
2517- & ( diag. severity . unwrap_or ( DiagnosticSeverity :: Hint ) as u64 ) ,
2518- )
2519- . ok_or_else ( || err_msg ( "Failed to get display" ) ) ?
2520- . virtualTexthl
2521- . clone ( ) ,
2522- } ) ;
2523- }
2595+ // diagnostics
2596+ if UseVirtualText :: All == use_virtual_text
2597+ || UseVirtualText :: Diagnostics == use_virtual_text
2598+ {
2599+ let diagnostics = self . get ( |state| state. diagnostics . clone ( ) ) ?;
2600+ let diagnosticsDisplay = self . get ( |state| state. diagnosticsDisplay . clone ( ) ) ?;
2601+ let diag_list = diagnostics. get ( & filename) ;
2602+ if let Some ( diag_list) = diag_list {
2603+ for diag in diag_list {
2604+ if viewport. overlaps ( diag. range ) {
2605+ virtual_texts. push ( VirtualText {
2606+ line : diag. range . start . line ,
2607+ text : diag. message . replace ( "\n " , " " ) . clone ( ) ,
2608+ hl_group : diagnosticsDisplay
2609+ . get ( & ( diag. severity . unwrap_or ( DiagnosticSeverity :: Hint ) as u64 ) )
2610+ . ok_or_else ( || err_msg ( "Failed to get display" ) ) ?
2611+ . virtualTexthl
2612+ . clone ( ) ,
2613+ } ) ;
25242614 }
25252615 }
2526- Ok ( ( ) )
2616+ }
2617+ }
2618+
2619+ // code lens
2620+ if UseVirtualText :: All == use_virtual_text || UseVirtualText :: CodeLens == use_virtual_text {
2621+ let filename = self . vim ( ) ?. get_filename ( params) ?;
2622+ let code_lenses = self . get ( |state| {
2623+ state
2624+ . code_lens
2625+ . get ( & filename)
2626+ . cloned ( )
2627+ . unwrap_or_else ( || vec ! [ ] )
25272628 } ) ?;
2528- self . vim ( ) ?. set_virtual_texts (
2529- bufnr,
2530- namespace_id,
2531- viewport. start ,
2532- viewport. end ,
2533- & virtual_texts,
2534- ) ?;
2629+
2630+ for cl in code_lenses {
2631+ if cl. command . is_none ( ) {
2632+ continue ;
2633+ }
2634+ let command = cl. command . unwrap ( ) ;
2635+
2636+ virtual_texts. push ( VirtualText {
2637+ line : cl. range . start . line ,
2638+ text : command. title ,
2639+ hl_group : "Comment" . into ( ) ,
2640+ } )
2641+ }
25352642 }
25362643
2644+ let namespace_id = self . get_or_create_namespace ( ) ?;
2645+ self . vim ( ) ?. set_virtual_texts (
2646+ bufnr,
2647+ namespace_id,
2648+ viewport. start ,
2649+ viewport. end ,
2650+ & virtual_texts,
2651+ ) ?;
2652+
25372653 info ! ( "End {}" , NOTIFICATION__HandleCursorMoved ) ;
25382654 Ok ( ( ) )
25392655 }
0 commit comments