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 /crates/ra_lsp_server/src/main_loop | |
parent | 13a2bdb0a89260e978ba8e55abd7a51a003e62a7 (diff) |
Implement lens for impls and support resolving lenses.
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 85 |
1 files changed, 83 insertions, 2 deletions
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, |