mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Merge #738
738: Implement lens for impls and support resolving lenses. r=matklad a=kjeremy Closes #620 Co-authored-by: Jeremy Kolb <kjeremy@gmail.com> Co-authored-by: kjeremy <kjeremy@gmail.com>
This commit is contained in:
commit
88702a758f
4 changed files with 101 additions and 3 deletions
|
@ -33,7 +33,7 @@ pub fn server_capabilities() -> ServerCapabilities {
|
||||||
workspace_symbol_provider: Some(true),
|
workspace_symbol_provider: Some(true),
|
||||||
code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
|
code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
|
||||||
code_lens_provider: Some(CodeLensOptions {
|
code_lens_provider: Some(CodeLensOptions {
|
||||||
resolve_provider: None,
|
resolve_provider: Some(true),
|
||||||
}),
|
}),
|
||||||
document_formatting_provider: Some(true),
|
document_formatting_provider: Some(true),
|
||||||
document_range_formatting_provider: None,
|
document_range_formatting_provider: None,
|
||||||
|
|
|
@ -312,6 +312,7 @@ fn on_request(
|
||||||
.on::<req::Completion>(handlers::handle_completion)?
|
.on::<req::Completion>(handlers::handle_completion)?
|
||||||
.on::<req::CodeActionRequest>(handlers::handle_code_action)?
|
.on::<req::CodeActionRequest>(handlers::handle_code_action)?
|
||||||
.on::<req::CodeLensRequest>(handlers::handle_code_lens)?
|
.on::<req::CodeLensRequest>(handlers::handle_code_lens)?
|
||||||
|
.on::<req::CodeLensResolve>(handlers::handle_code_lens_resolve)?
|
||||||
.on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
|
.on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
|
||||||
.on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
|
.on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
|
||||||
.on::<req::HoverRequest>(handlers::handle_hover)?
|
.on::<req::HoverRequest>(handlers::handle_hover)?
|
||||||
|
|
|
@ -5,15 +5,17 @@ use lsp_types::{
|
||||||
FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
|
FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
|
||||||
MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range,
|
MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range,
|
||||||
RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit,
|
RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit,
|
||||||
WorkspaceEdit
|
WorkspaceEdit,
|
||||||
};
|
};
|
||||||
use ra_ide_api::{
|
use ra_ide_api::{
|
||||||
FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity, Cancelable,
|
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 rustc_hash::FxHashMap;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
use serde_json::to_value;
|
use serde_json::to_value;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use url_serde::Ser;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cargo_target_spec::{runnable_args, CargoTargetSpec},
|
cargo_target_spec::{runnable_args, CargoTargetSpec},
|
||||||
|
@ -596,6 +598,10 @@ pub fn handle_code_action(
|
||||||
for source_edit in assists.chain(fixes) {
|
for source_edit in assists.chain(fixes) {
|
||||||
let title = source_edit.label.clone();
|
let title = source_edit.label.clone();
|
||||||
let edit = source_edit.try_conv_with(&world)?;
|
let edit = source_edit.try_conv_with(&world)?;
|
||||||
|
|
||||||
|
// We cannot use the 'editor.action.showReferences' command directly
|
||||||
|
// because that command requires vscode types which we convert in the handler
|
||||||
|
// on the client side.
|
||||||
let cmd = Command {
|
let cmd = Command {
|
||||||
title,
|
title,
|
||||||
command: "rust-analyzer.applySourceChange".to_string(),
|
command: "rust-analyzer.applySourceChange".to_string(),
|
||||||
|
@ -616,6 +622,7 @@ pub fn handle_code_lens(
|
||||||
|
|
||||||
let mut lenses: Vec<CodeLens> = Default::default();
|
let mut lenses: Vec<CodeLens> = Default::default();
|
||||||
|
|
||||||
|
// Gather runnables
|
||||||
for runnable in world.analysis().runnables(file_id)? {
|
for runnable in world.analysis().runnables(file_id)? {
|
||||||
let title = match &runnable.kind {
|
let title = match &runnable.kind {
|
||||||
RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => {
|
RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => {
|
||||||
|
@ -652,9 +659,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));
|
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<CodeLens> {
|
||||||
|
let data = code_lens.data.unwrap();
|
||||||
|
let resolve = serde_json::from_value(data)?;
|
||||||
|
match resolve {
|
||||||
|
Some(CodeLensResolveData::Impls(lens_params)) => {
|
||||||
|
let locations: Vec<Location> =
|
||||||
|
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(
|
pub fn handle_document_highlight(
|
||||||
world: ServerWorld,
|
world: ServerWorld,
|
||||||
params: req::TextDocumentPositionParams,
|
params: req::TextDocumentPositionParams,
|
||||||
|
|
|
@ -70,6 +70,18 @@ export function activate(context: vscode.ExtensionContext) {
|
||||||
'rust-analyzer.applySourceChange',
|
'rust-analyzer.applySourceChange',
|
||||||
commands.applySourceChange.handle
|
commands.applySourceChange.handle
|
||||||
);
|
);
|
||||||
|
registerCommand(
|
||||||
|
'rust-analyzer.showReferences',
|
||||||
|
(uri: string, position: lc.Position, locations: lc.Location[]) => {
|
||||||
|
vscode.commands.executeCommand(
|
||||||
|
'editor.action.showReferences',
|
||||||
|
vscode.Uri.parse(uri),
|
||||||
|
Server.client.protocol2CodeConverter.asPosition(position),
|
||||||
|
locations.map(Server.client.protocol2CodeConverter.asLocation)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
overrideCommand('type', commands.onEnter.handle);
|
overrideCommand('type', commands.onEnter.handle);
|
||||||
|
|
||||||
// Notifications are events triggered by the language server
|
// Notifications are events triggered by the language server
|
||||||
|
|
Loading…
Reference in a new issue