diff options
author | Jeremy Kolb <[email protected]> | 2019-02-01 13:44:23 +0000 |
---|---|---|
committer | kjeremy <[email protected]> | 2019-02-04 13:45:33 +0000 |
commit | 6ac4cca6c1fc188ae0fda62fb81a9855a51b7530 (patch) | |
tree | ff72e9d32f18489fcef72d4ae7d1882d53540748 | |
parent | 13a2bdb0a89260e978ba8e55abd7a51a003e62a7 (diff) |
Implement lens for impls and support resolving lenses.
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 85 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 12 |
4 files changed, 97 insertions, 3 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 254624487..39992788d 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -33,7 +33,7 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
33 | workspace_symbol_provider: Some(true), | 33 | workspace_symbol_provider: Some(true), |
34 | code_action_provider: Some(CodeActionProviderCapability::Simple(true)), | 34 | code_action_provider: Some(CodeActionProviderCapability::Simple(true)), |
35 | code_lens_provider: Some(CodeLensOptions { | 35 | code_lens_provider: Some(CodeLensOptions { |
36 | resolve_provider: None, | 36 | resolve_provider: Some(true), |
37 | }), | 37 | }), |
38 | document_formatting_provider: Some(true), | 38 | document_formatting_provider: Some(true), |
39 | document_range_formatting_provider: None, | 39 | document_range_formatting_provider: None, |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index df390c19e..26b6fe54a 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -312,6 +312,7 @@ fn on_request( | |||
312 | .on::<req::Completion>(handlers::handle_completion)? | 312 | .on::<req::Completion>(handlers::handle_completion)? |
313 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? | 313 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? |
314 | .on::<req::CodeLensRequest>(handlers::handle_code_lens)? | 314 | .on::<req::CodeLensRequest>(handlers::handle_code_lens)? |
315 | .on::<req::CodeLensResolve>(handlers::handle_code_lens_resolve)? | ||
315 | .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? | 316 | .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? |
316 | .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? | 317 | .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? |
317 | .on::<req::HoverRequest>(handlers::handle_hover)? | 318 | .on::<req::HoverRequest>(handlers::handle_hover)? |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 0bec57e84..946992e15 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -5,15 +5,17 @@ use lsp_types::{ | |||
5 | FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, | 5 | FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, |
6 | MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, | 6 | MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, |
7 | RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, | 7 | RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, |
8 | WorkspaceEdit | 8 | WorkspaceEdit, |
9 | }; | 9 | }; |
10 | use ra_ide_api::{ | 10 | use ra_ide_api::{ |
11 | FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity, Cancelable, | 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 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
15 | use serde::{Serialize, Deserialize}; | ||
15 | use serde_json::to_value; | 16 | use serde_json::to_value; |
16 | use std::io::Write; | 17 | use std::io::Write; |
18 | use url_serde::Ser; | ||
17 | 19 | ||
18 | use crate::{ | 20 | use crate::{ |
19 | cargo_target_spec::{runnable_args, CargoTargetSpec}, | 21 | cargo_target_spec::{runnable_args, CargoTargetSpec}, |
@@ -616,6 +618,7 @@ pub fn handle_code_lens( | |||
616 | 618 | ||
617 | let mut lenses: Vec<CodeLens> = Default::default(); | 619 | let mut lenses: Vec<CodeLens> = Default::default(); |
618 | 620 | ||
621 | // Gather runnables | ||
619 | for runnable in world.analysis().runnables(file_id)? { | 622 | for runnable in world.analysis().runnables(file_id)? { |
620 | let title = match &runnable.kind { | 623 | let title = match &runnable.kind { |
621 | RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => { | 624 | RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => { |
@@ -652,9 +655,87 @@ pub fn handle_code_lens( | |||
652 | } | 655 | } |
653 | } | 656 | } |
654 | 657 | ||
658 | // Handle impls | ||
659 | lenses.extend( | ||
660 | world | ||
661 | .analysis() | ||
662 | .file_structure(file_id) | ||
663 | .into_iter() | ||
664 | .filter(|it| match it.kind { | ||
665 | SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true, | ||
666 | _ => false, | ||
667 | }) | ||
668 | .map(|it| { | ||
669 | let range = it.node_range.conv_with(&line_index); | ||
670 | let pos = range.start; | ||
671 | let lens_params = | ||
672 | req::TextDocumentPositionParams::new(params.text_document.clone(), pos); | ||
673 | CodeLens { | ||
674 | range, | ||
675 | command: None, | ||
676 | data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()), | ||
677 | } | ||
678 | }), | ||
679 | ); | ||
680 | |||
655 | return Ok(Some(lenses)); | 681 | return Ok(Some(lenses)); |
656 | } | 682 | } |
657 | 683 | ||
684 | #[derive(Debug, Serialize, Deserialize)] | ||
685 | #[serde(rename_all = "camelCase")] | ||
686 | enum CodeLensResolveData { | ||
687 | Impls(req::TextDocumentPositionParams), | ||
688 | } | ||
689 | |||
690 | pub fn handle_code_lens_resolve(world: ServerWorld, code_lens: CodeLens) -> Result<CodeLens> { | ||
691 | let data = code_lens.data.unwrap(); | ||
692 | let resolve = serde_json::from_value(data)?; | ||
693 | match resolve { | ||
694 | Some(CodeLensResolveData::Impls(lens_params)) => { | ||
695 | let locations: Vec<Location> = | ||
696 | match handle_goto_implementation(world, lens_params.clone())? { | ||
697 | Some(req::GotoDefinitionResponse::Scalar(loc)) => vec![loc], | ||
698 | Some(req::GotoDefinitionResponse::Array(locs)) => locs, | ||
699 | Some(req::GotoDefinitionResponse::Link(links)) => links | ||
700 | .into_iter() | ||
701 | .map(|link| Location::new(link.target_uri, link.target_selection_range)) | ||
702 | .collect(), | ||
703 | _ => vec![], | ||
704 | }; | ||
705 | |||
706 | let title = if locations.len() == 1 { | ||
707 | "1 implementation".into() | ||
708 | } else { | ||
709 | format!("{} implementations", locations.len()) | ||
710 | }; | ||
711 | |||
712 | return Ok(CodeLens { | ||
713 | range: code_lens.range, | ||
714 | command: Some(Command { | ||
715 | title, | ||
716 | command: "rust-analyzer.showReferences".into(), | ||
717 | arguments: Some(vec![ | ||
718 | to_value(&Ser::new(&lens_params.text_document.uri)).unwrap(), | ||
719 | to_value(code_lens.range.start).unwrap(), | ||
720 | to_value(locations).unwrap(), | ||
721 | ]), | ||
722 | }), | ||
723 | data: None, | ||
724 | }); | ||
725 | } | ||
726 | _ => { | ||
727 | return Ok(CodeLens { | ||
728 | range: code_lens.range, | ||
729 | command: Some(Command { | ||
730 | title: "Error".into(), | ||
731 | ..Default::default() | ||
732 | }), | ||
733 | data: None, | ||
734 | }); | ||
735 | } | ||
736 | } | ||
737 | } | ||
738 | |||
658 | pub fn handle_document_highlight( | 739 | pub fn handle_document_highlight( |
659 | world: ServerWorld, | 740 | world: ServerWorld, |
660 | params: req::TextDocumentPositionParams, | 741 | params: req::TextDocumentPositionParams, |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 0b2a6095b..a0be70202 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -70,6 +70,18 @@ export function activate(context: vscode.ExtensionContext) { | |||
70 | 'rust-analyzer.applySourceChange', | 70 | 'rust-analyzer.applySourceChange', |
71 | commands.applySourceChange.handle | 71 | commands.applySourceChange.handle |
72 | ); | 72 | ); |
73 | registerCommand( | ||
74 | 'rust-analyzer.showReferences', | ||
75 | (uri: string, position: lc.Position, locations: lc.Location[]) => { | ||
76 | vscode.commands.executeCommand( | ||
77 | 'editor.action.showReferences', | ||
78 | vscode.Uri.parse(uri), | ||
79 | Server.client.protocol2CodeConverter.asPosition(position), | ||
80 | locations.map(Server.client.protocol2CodeConverter.asLocation) | ||
81 | ); | ||
82 | } | ||
83 | ); | ||
84 | |||
73 | overrideCommand('type', commands.onEnter.handle); | 85 | overrideCommand('type', commands.onEnter.handle); |
74 | 86 | ||
75 | // Notifications are events triggered by the language server | 87 | // Notifications are events triggered by the language server |