Skip to content

Commit 6ac4cca

Browse files
committed
Implement lens for impls and support resolving lenses.
1 parent 13a2bdb commit 6ac4cca

File tree

4 files changed

+97
-3
lines changed

4 files changed

+97
-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: 83 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},
@@ -616,6 +618,7 @@ pub fn handle_code_lens(
616618

617619
let mut lenses: Vec<CodeLens> = Default::default();
618620

621+
// Gather runnables
619622
for runnable in world.analysis().runnables(file_id)? {
620623
let title = match &runnable.kind {
621624
RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => {
@@ -652,9 +655,87 @@ pub fn handle_code_lens(
652655
}
653656
}
654657

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+
655681
return Ok(Some(lenses));
656682
}
657683

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+
658739
pub fn handle_document_highlight(
659740
world: ServerWorld,
660741
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)