aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server
diff options
context:
space:
mode:
authorJeremy Kolb <[email protected]>2019-12-30 14:12:06 +0000
committerkjeremy <[email protected]>2020-01-08 15:15:49 +0000
commit1b19a8aa5ecfc9d7115f291b97d413bd845c89b5 (patch)
treecf209285ee7020bb0ab75b9a71eab4c006b86532 /crates/ra_lsp_server
parent928ecd069a508845ef4dbfd1bc1b9bf975d76e5b (diff)
Implement proposed CallHierarchy feature
See: https://github.com/microsoft/vscode-languageserver-node/blob/master/protocol/src/protocol.callHierarchy.proposed.ts
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r--crates/ra_lsp_server/src/caps.rs6
-rw-r--r--crates/ra_lsp_server/src/conv.rs18
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs3
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs98
-rw-r--r--crates/ra_lsp_server/src/req.rs16
5 files changed, 129 insertions, 12 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index db502c200..c4711076c 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -1,8 +1,8 @@
1//! Advertizes the capabilities of the LSP Server. 1//! Advertizes the capabilities of the LSP Server.
2 2
3use lsp_types::{ 3use lsp_types::{
4 CodeActionProviderCapability, CodeLensOptions, CompletionOptions, 4 CallHierarchyServerCapability, CodeActionProviderCapability, CodeLensOptions,
5 DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, 5 CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability,
6 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, 6 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions,
7 SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions, 7 SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions,
8 TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, 8 TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions,
@@ -56,7 +56,7 @@ pub fn server_capabilities() -> ServerCapabilities {
56 color_provider: None, 56 color_provider: None,
57 execute_command_provider: None, 57 execute_command_provider: None,
58 workspace: None, 58 workspace: None,
59 call_hierarchy_provider: None, 59 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
60 experimental: Default::default(), 60 experimental: Default::default(),
61 } 61 }
62} 62}
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index e93d4ea33..c260b51c4 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -490,6 +490,24 @@ impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<Vec<NavigationTarget>>)
490 } 490 }
491} 491}
492 492
493pub fn to_call_hierarchy_item(
494 file_id: FileId,
495 range: TextRange,
496 world: &WorldSnapshot,
497 line_index: &LineIndex,
498 nav: NavigationTarget,
499) -> Result<lsp_types::CallHierarchyItem> {
500 Ok(lsp_types::CallHierarchyItem {
501 name: nav.name().to_string(),
502 kind: nav.kind().conv(),
503 tags: None,
504 detail: nav.description().map(|it| it.to_string()),
505 uri: file_id.try_conv_with(&world)?,
506 range: nav.range().conv_with(&line_index),
507 selection_range: range.conv_with(&line_index),
508 })
509}
510
493pub fn to_location( 511pub fn to_location(
494 file_id: FileId, 512 file_id: FileId,
495 range: TextRange, 513 range: TextRange,
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 4336583fe..047c86a3b 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -499,6 +499,9 @@ fn on_request(
499 .on::<req::Formatting>(handlers::handle_formatting)? 499 .on::<req::Formatting>(handlers::handle_formatting)?
500 .on::<req::DocumentHighlightRequest>(handlers::handle_document_highlight)? 500 .on::<req::DocumentHighlightRequest>(handlers::handle_document_highlight)?
501 .on::<req::InlayHints>(handlers::handle_inlay_hints)? 501 .on::<req::InlayHints>(handlers::handle_inlay_hints)?
502 .on::<req::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare)?
503 .on::<req::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming)?
504 .on::<req::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing)?
502 .finish(); 505 .finish();
503 Ok(()) 506 Ok(())
504} 507}
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index c8f52eb0e..a5b6f48af 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -5,13 +5,16 @@ use std::{fmt::Write as _, io::Write as _};
5 5
6use lsp_server::ErrorCode; 6use lsp_server::ErrorCode;
7use lsp_types::{ 7use lsp_types::{
8 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
9 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
8 CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic, 10 CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic,
9 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, 11 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams,
10 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, 12 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse,
11 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, 13 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit,
12}; 14};
13use ra_ide::{ 15use ra_ide::{
14 AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope, 16 AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
17 SearchScope,
15}; 18};
16use ra_prof::profile; 19use ra_prof::profile;
17use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; 20use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit};
@@ -21,7 +24,10 @@ use serde_json::to_value;
21 24
22use crate::{ 25use crate::{
23 cargo_target_spec::{runnable_args, CargoTargetSpec}, 26 cargo_target_spec::{runnable_args, CargoTargetSpec},
24 conv::{to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith, TryConvWithToVec}, 27 conv::{
28 to_call_hierarchy_item, to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith,
29 TryConvWithToVec,
30 },
25 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind}, 31 req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
26 world::WorldSnapshot, 32 world::WorldSnapshot,
27 LspError, Result, 33 LspError, Result,
@@ -936,3 +942,91 @@ pub fn handle_inlay_hints(
936 }) 942 })
937 .collect()) 943 .collect())
938} 944}
945
946pub fn handle_call_hierarchy_prepare(
947 world: WorldSnapshot,
948 params: CallHierarchyPrepareParams,
949) -> Result<Option<Vec<CallHierarchyItem>>> {
950 let _p = profile("handle_call_hierarchy_prepare");
951 let position = params.text_document_position_params.try_conv_with(&world)?;
952 let file_id = position.file_id;
953
954 let nav_info = match world.analysis().call_hierarchy(position)? {
955 None => return Ok(None),
956 Some(it) => it,
957 };
958
959 let line_index = world.analysis().file_line_index(file_id)?;
960 let RangeInfo { range, info: navs } = nav_info;
961 let res = navs
962 .into_iter()
963 .filter(|it| it.kind() == SyntaxKind::FN_DEF)
964 .filter_map(|it| to_call_hierarchy_item(file_id, range, &world, &line_index, it).ok())
965 .collect();
966
967 Ok(Some(res))
968}
969
970pub fn handle_call_hierarchy_incoming(
971 world: WorldSnapshot,
972 params: CallHierarchyIncomingCallsParams,
973) -> Result<Option<Vec<CallHierarchyIncomingCall>>> {
974 let _p = profile("handle_call_hierarchy_incoming");
975 let item = params.item;
976
977 let doc = TextDocumentIdentifier::new(item.uri);
978 let frange: FileRange = (&doc, item.range).try_conv_with(&world)?;
979 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
980
981 let call_items = match world.analysis().incoming_calls(fpos)? {
982 None => return Ok(None),
983 Some(it) => it,
984 };
985
986 let mut res = vec![];
987
988 for call_item in call_items.into_iter() {
989 let file_id = call_item.target.file_id();
990 let line_index = world.analysis().file_line_index(file_id)?;
991 let range = call_item.target.range();
992 let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?;
993 res.push(CallHierarchyIncomingCall {
994 from: item,
995 from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(),
996 });
997 }
998
999 Ok(Some(res))
1000}
1001
1002pub fn handle_call_hierarchy_outgoing(
1003 world: WorldSnapshot,
1004 params: CallHierarchyOutgoingCallsParams,
1005) -> Result<Option<Vec<CallHierarchyOutgoingCall>>> {
1006 let _p = profile("handle_call_hierarchy_outgoing");
1007 let item = params.item;
1008
1009 let doc = TextDocumentIdentifier::new(item.uri);
1010 let frange: FileRange = (&doc, item.range).try_conv_with(&world)?;
1011 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
1012
1013 let call_items = match world.analysis().outgoing_calls(fpos)? {
1014 None => return Ok(None),
1015 Some(it) => it,
1016 };
1017
1018 let mut res = vec![];
1019
1020 for call_item in call_items.into_iter() {
1021 let file_id = call_item.target.file_id();
1022 let line_index = world.analysis().file_line_index(file_id)?;
1023 let range = call_item.target.range();
1024 let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?;
1025 res.push(CallHierarchyOutgoingCall {
1026 to: item,
1027 from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(),
1028 });
1029 }
1030
1031 Ok(Some(res))
1032}
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 40edaf677..8098ff31d 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -6,13 +6,15 @@ use serde::{Deserialize, Serialize};
6 6
7pub use lsp_types::{ 7pub use lsp_types::{
8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens, 8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
9 CodeLensParams, CompletionParams, CompletionResponse, DidChangeConfigurationParams, 9 CodeLensParams, CompletionParams, CompletionResponse, DiagnosticTag,
10 DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, 10 DidChangeConfigurationParams, DidChangeWatchedFilesParams,
11 DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, 11 DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams,
12 FileSystemWatcher, Hover, InitializeResult, MessageType, ProgressParams, ProgressParamsValue, 12 DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType,
13 ProgressToken, PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, 13 PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken,
14 SelectionRange, SelectionRangeParams, ShowMessageParams, SignatureHelp, TextDocumentEdit, 14 PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, SelectionRange,
15 TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, 15 SelectionRangeParams, ServerCapabilities, ShowMessageParams, SignatureHelp, SymbolKind,
16 TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkDoneProgressParams, WorkspaceEdit,
17 WorkspaceSymbolParams,
16}; 18};
17 19
18pub enum AnalyzerStatus {} 20pub enum AnalyzerStatus {}