From 6ac4cca6c1fc188ae0fda62fb81a9855a51b7530 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Fri, 1 Feb 2019 08:44:23 -0500 Subject: Implement lens for impls and support resolving lenses. --- crates/ra_lsp_server/src/caps.rs | 2 +- crates/ra_lsp_server/src/main_loop.rs | 1 + crates/ra_lsp_server/src/main_loop/handlers.rs | 85 +++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 3 deletions(-) (limited to 'crates/ra_lsp_server') 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 { workspace_symbol_provider: Some(true), code_action_provider: Some(CodeActionProviderCapability::Simple(true)), code_lens_provider: Some(CodeLensOptions { - resolve_provider: None, + resolve_provider: Some(true), }), document_formatting_provider: Some(true), 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( .on::(handlers::handle_completion)? .on::(handlers::handle_code_action)? .on::(handlers::handle_code_lens)? + .on::(handlers::handle_code_lens_resolve)? .on::(handlers::handle_folding_range)? .on::(handlers::handle_signature_help)? .on::(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::{ FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, - WorkspaceEdit + WorkspaceEdit, }; use ra_ide_api::{ FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity, Cancelable, }; -use ra_syntax::{AstNode, TextUnit}; +use ra_syntax::{AstNode, SyntaxKind, TextUnit}; use rustc_hash::FxHashMap; +use serde::{Serialize, Deserialize}; use serde_json::to_value; use std::io::Write; +use url_serde::Ser; use crate::{ cargo_target_spec::{runnable_args, CargoTargetSpec}, @@ -616,6 +618,7 @@ pub fn handle_code_lens( let mut lenses: Vec = Default::default(); + // Gather runnables for runnable in world.analysis().runnables(file_id)? { let title = match &runnable.kind { RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => { @@ -652,9 +655,87 @@ pub fn handle_code_lens( } } + // Handle impls + lenses.extend( + world + .analysis() + .file_structure(file_id) + .into_iter() + .filter(|it| match it.kind { + SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true, + _ => false, + }) + .map(|it| { + let range = it.node_range.conv_with(&line_index); + let pos = range.start; + let lens_params = + req::TextDocumentPositionParams::new(params.text_document.clone(), pos); + CodeLens { + range, + command: None, + data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()), + } + }), + ); + return Ok(Some(lenses)); } +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +enum CodeLensResolveData { + Impls(req::TextDocumentPositionParams), +} + +pub fn handle_code_lens_resolve(world: ServerWorld, code_lens: CodeLens) -> Result { + let data = code_lens.data.unwrap(); + let resolve = serde_json::from_value(data)?; + match resolve { + Some(CodeLensResolveData::Impls(lens_params)) => { + let locations: Vec = + match handle_goto_implementation(world, lens_params.clone())? { + Some(req::GotoDefinitionResponse::Scalar(loc)) => vec![loc], + Some(req::GotoDefinitionResponse::Array(locs)) => locs, + Some(req::GotoDefinitionResponse::Link(links)) => links + .into_iter() + .map(|link| Location::new(link.target_uri, link.target_selection_range)) + .collect(), + _ => vec![], + }; + + let title = if locations.len() == 1 { + "1 implementation".into() + } else { + format!("{} implementations", locations.len()) + }; + + return Ok(CodeLens { + range: code_lens.range, + command: Some(Command { + title, + command: "rust-analyzer.showReferences".into(), + arguments: Some(vec![ + to_value(&Ser::new(&lens_params.text_document.uri)).unwrap(), + to_value(code_lens.range.start).unwrap(), + to_value(locations).unwrap(), + ]), + }), + data: None, + }); + } + _ => { + return Ok(CodeLens { + range: code_lens.range, + command: Some(Command { + title: "Error".into(), + ..Default::default() + }), + data: None, + }); + } + } +} + pub fn handle_document_highlight( world: ServerWorld, params: req::TextDocumentPositionParams, -- cgit v1.2.3