aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/main_loop
diff options
context:
space:
mode:
authorJeremy Kolb <[email protected]>2019-02-01 13:44:23 +0000
committerkjeremy <[email protected]>2019-02-04 13:45:33 +0000
commit6ac4cca6c1fc188ae0fda62fb81a9855a51b7530 (patch)
treeff72e9d32f18489fcef72d4ae7d1882d53540748 /crates/ra_lsp_server/src/main_loop
parent13a2bdb0a89260e978ba8e55abd7a51a003e62a7 (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.rs85
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};
10use ra_ide_api::{ 10use 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};
13use ra_syntax::{AstNode, TextUnit}; 13use ra_syntax::{AstNode, SyntaxKind, TextUnit};
14use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
15use serde::{Serialize, Deserialize};
15use serde_json::to_value; 16use serde_json::to_value;
16use std::io::Write; 17use std::io::Write;
18use url_serde::Ser;
17 19
18use crate::{ 20use 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")]
686enum CodeLensResolveData {
687 Impls(req::TextDocumentPositionParams),
688}
689
690pub 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
658pub fn handle_document_highlight( 739pub fn handle_document_highlight(
659 world: ServerWorld, 740 world: ServerWorld,
660 params: req::TextDocumentPositionParams, 741 params: req::TextDocumentPositionParams,