mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Implement lens for impls and support resolving lenses.
This commit is contained in:
parent
13a2bdb0a8
commit
6ac4cca6c1
4 changed files with 97 additions and 3 deletions
|
@ -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,
|
||||
|
|
|
@ -312,6 +312,7 @@ fn on_request(
|
|||
.on::<req::Completion>(handlers::handle_completion)?
|
||||
.on::<req::CodeActionRequest>(handlers::handle_code_action)?
|
||||
.on::<req::CodeLensRequest>(handlers::handle_code_lens)?
|
||||
.on::<req::CodeLensResolve>(handlers::handle_code_lens_resolve)?
|
||||
.on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
|
||||
.on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
|
||||
.on::<req::HoverRequest>(handlers::handle_hover)?
|
||||
|
|
|
@ -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<CodeLens> = 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<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(
|
||||
world: ServerWorld,
|
||||
params: req::TextDocumentPositionParams,
|
||||
|
|
|
@ -70,6 +70,18 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
'rust-analyzer.applySourceChange',
|
||||
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);
|
||||
|
||||
// Notifications are events triggered by the language server
|
||||
|
|
Loading…
Reference in a new issue