Skip to content

Commit 88702a7

Browse files
bors[bot]kjeremy
andcommitted
Merge #738
738: Implement lens for impls and support resolving lenses. r=matklad a=kjeremy Closes #620 Co-authored-by: Jeremy Kolb <[email protected]> Co-authored-by: kjeremy <[email protected]>
2 parents 13a2bdb + 0f7a714 commit 88702a7

File tree

4 files changed

+101
-3
lines changed

4 files changed

+101
-3
lines changed

crates/ra_lsp_server/src/caps.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn server_capabilities() -> ServerCapabilities {
3333
workspace_symbol_provider: Some(true),
3434
code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
3535
code_lens_provider: Some(CodeLensOptions {
36-
resolve_provider: None,
36+
resolve_provider: Some(true),
3737
}),
3838
document_formatting_provider: Some(true),
3939
document_range_formatting_provider: None,

crates/ra_lsp_server/src/main_loop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ fn on_request(
312312
.on::<req::Completion>(handlers::handle_completion)?
313313
.on::<req::CodeActionRequest>(handlers::handle_code_action)?
314314
.on::<req::CodeLensRequest>(handlers::handle_code_lens)?
315+
.on::<req::CodeLensResolve>(handlers::handle_code_lens_resolve)?
315316
.on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
316317
.on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
317318
.on::<req::HoverRequest>(handlers::handle_hover)?

crates/ra_lsp_server/src/main_loop/handlers.rs

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@ use lsp_types::{
55
FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
66
MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range,
77
RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit,
8-
WorkspaceEdit
8+
WorkspaceEdit,
99
};
1010
use ra_ide_api::{
1111
FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity, Cancelable,
1212
};
13-
use ra_syntax::{AstNode, TextUnit};
13+
use ra_syntax::{AstNode, SyntaxKind, TextUnit};
1414
use rustc_hash::FxHashMap;
15+
use serde::{Serialize, Deserialize};
1516
use serde_json::to_value;
1617
use std::io::Write;
18+
use url_serde::Ser;
1719

1820
use crate::{
1921
cargo_target_spec::{runnable_args, CargoTargetSpec},
@@ -596,6 +598,10 @@ pub fn handle_code_action(
596598
for source_edit in assists.chain(fixes) {
597599
let title = source_edit.label.clone();
598600
let edit = source_edit.try_conv_with(&world)?;
601+
602+
// We cannot use the 'editor.action.showReferences' command directly
603+
// because that command requires vscode types which we convert in the handler
604+
// on the client side.
599605
let cmd = Command {
600606
title,
601607
command: "rust-analyzer.applySourceChange".to_string(),
@@ -616,6 +622,7 @@ pub fn handle_code_lens(
616622

617623
let mut lenses: Vec<CodeLens> = Default::default();
618624

625+
// Gather runnables
619626
for runnable in world.analysis().runnables(file_id)? {
620627
let title = match &runnable.kind {
621628
RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => {
@@ -652,9 +659,87 @@ pub fn handle_code_lens(
652659
}
653660
}
654661

662+
// Handle impls
663+
lenses.extend(
664+
world
665+
.analysis()
666+
.file_structure(file_id)
667+
.into_iter()
668+
.filter(|it| match it.kind {
669+
SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true,
670+
_ => false,
671+
})
672+
.map(|it| {
673+
let range = it.node_range.conv_with(&line_index);
674+
let pos = range.start;
675+
let lens_params =
676+
req::TextDocumentPositionParams::new(params.text_document.clone(), pos);
677+
CodeLens {
678+
range,
679+
command: None,
680+
data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()),
681+
}
682+
}),
683+
);
684+
655685
return Ok(Some(lenses));
656686
}
657687

688+
#[derive(Debug, Serialize, Deserialize)]
689+
#[serde(rename_all = "camelCase")]
690+
enum CodeLensResolveData {
691+
Impls(req::TextDocumentPositionParams),
692+
}
693+
694+
pub fn handle_code_lens_resolve(world: ServerWorld, code_lens: CodeLens) -> Result<CodeLens> {
695+
let data = code_lens.data.unwrap();
696+
let resolve = serde_json::from_value(data)?;
697+
match resolve {
698+
Some(CodeLensResolveData::Impls(lens_params)) => {
699+
let locations: Vec<Location> =
700+
match handle_goto_implementation(world, lens_params.clone())? {
701+
Some(req::GotoDefinitionResponse::Scalar(loc)) => vec![loc],
702+
Some(req::GotoDefinitionResponse::Array(locs)) => locs,
703+
Some(req::GotoDefinitionResponse::Link(links)) => links
704+
.into_iter()
705+
.map(|link| Location::new(link.target_uri, link.target_selection_range))
706+
.collect(),
707+
_ => vec![],
708+
};
709+
710+
let title = if locations.len() == 1 {
711+
"1 implementation".into()
712+
} else {
713+
format!("{} implementations", locations.len())
714+
};
715+
716+
return Ok(CodeLens {
717+
range: code_lens.range,
718+
command: Some(Command {
719+
title,
720+
command: "rust-analyzer.showReferences".into(),
721+
arguments: Some(vec![
722+
to_value(&Ser::new(&lens_params.text_document.uri)).unwrap(),
723+
to_value(code_lens.range.start).unwrap(),
724+
to_value(locations).unwrap(),
725+
]),
726+
}),
727+
data: None,
728+
});
729+
}
730+
_ => {
731+
return Ok(CodeLens {
732+
range: code_lens.range,
733+
command: Some(Command {
734+
title: "Error".into(),
735+
..Default::default()
736+
}),
737+
data: None,
738+
});
739+
}
740+
}
741+
}
742+
658743
pub fn handle_document_highlight(
659744
world: ServerWorld,
660745
params: req::TextDocumentPositionParams,

editors/code/src/extension.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ export function activate(context: vscode.ExtensionContext) {
7070
'rust-analyzer.applySourceChange',
7171
commands.applySourceChange.handle
7272
);
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+
7385
overrideCommand('type', commands.onEnter.handle);
7486

7587
// Notifications are events triggered by the language server

0 commit comments

Comments
 (0)