mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 04:23:25 +00:00
Merge #4773
4773: Run|Debug hover actions. r=matklad a=vsrs ![hover_actions_run](https://user-images.githubusercontent.com/62505555/83335644-dfc1f780-a2b6-11ea-820b-ccaa82290e7d.gif) This hover actions work exactly like corresponding lenses. Co-authored-by: vsrs <vit@conrlab.com>
This commit is contained in:
commit
6e4fca5882
6 changed files with 312 additions and 68 deletions
|
@ -14,34 +14,43 @@ use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffs
|
|||
|
||||
use crate::{
|
||||
display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav},
|
||||
FilePosition, NavigationTarget, RangeInfo,
|
||||
runnables::runnable,
|
||||
FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
|
||||
};
|
||||
use test_utils::mark;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct HoverConfig {
|
||||
pub implementations: bool,
|
||||
pub run: bool,
|
||||
pub debug: bool,
|
||||
}
|
||||
|
||||
impl Default for HoverConfig {
|
||||
fn default() -> Self {
|
||||
Self { implementations: true }
|
||||
Self { implementations: true, run: true, debug: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl HoverConfig {
|
||||
pub const NO_ACTIONS: Self = Self { implementations: false };
|
||||
pub const NO_ACTIONS: Self = Self { implementations: false, run: false, debug: false };
|
||||
|
||||
pub fn any(&self) -> bool {
|
||||
self.implementations
|
||||
self.implementations || self.runnable()
|
||||
}
|
||||
|
||||
pub fn none(&self) -> bool {
|
||||
!self.any()
|
||||
}
|
||||
|
||||
pub fn runnable(&self) -> bool {
|
||||
self.run || self.debug
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum HoverAction {
|
||||
Runnable(Runnable),
|
||||
Implementaion(FilePosition),
|
||||
}
|
||||
|
||||
|
@ -125,6 +134,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
|
|||
res.push_action(action);
|
||||
}
|
||||
|
||||
if let Some(action) = runnable_action(&sema, name_kind, position.file_id) {
|
||||
res.push_action(action);
|
||||
}
|
||||
|
||||
return Some(RangeInfo::new(range, res));
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +188,36 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
|
|||
}
|
||||
}
|
||||
|
||||
fn runnable_action(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
def: Definition,
|
||||
file_id: FileId,
|
||||
) -> Option<HoverAction> {
|
||||
match def {
|
||||
Definition::ModuleDef(it) => match it {
|
||||
ModuleDef::Module(it) => match it.definition_source(sema.db).value {
|
||||
ModuleSource::Module(it) => runnable(&sema, it.syntax().clone(), file_id)
|
||||
.map(|it| HoverAction::Runnable(it)),
|
||||
_ => None,
|
||||
},
|
||||
ModuleDef::Function(it) => {
|
||||
let src = it.source(sema.db);
|
||||
if src.file_id != file_id.into() {
|
||||
mark::hit!(hover_macro_generated_struct_fn_doc_comment);
|
||||
mark::hit!(hover_macro_generated_struct_fn_doc_attr);
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
runnable(&sema, src.value.syntax().clone(), file_id)
|
||||
.map(|it| HoverAction::Runnable(it))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn hover_text(
|
||||
docs: Option<String>,
|
||||
desc: Option<String>,
|
||||
|
@ -292,6 +335,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use insta::assert_debug_snapshot;
|
||||
|
||||
use ra_db::FileLoader;
|
||||
use ra_syntax::TextRange;
|
||||
|
@ -309,6 +353,7 @@ mod tests {
|
|||
fn assert_impl_action(action: &HoverAction, position: u32) {
|
||||
let offset = match action {
|
||||
HoverAction::Implementaion(pos) => pos.offset,
|
||||
it => panic!("Unexpected hover action: {:#?}", it),
|
||||
};
|
||||
assert_eq!(offset, position.into());
|
||||
}
|
||||
|
@ -1076,6 +1121,8 @@ fn func(foo: i32) { if true { <|>foo; }; }
|
|||
|
||||
#[test]
|
||||
fn test_hover_macro_generated_struct_fn_doc_comment() {
|
||||
mark::check!(hover_macro_generated_struct_fn_doc_comment);
|
||||
|
||||
check_hover_result(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
|
@ -1102,6 +1149,8 @@ fn func(foo: i32) { if true { <|>foo; }; }
|
|||
|
||||
#[test]
|
||||
fn test_hover_macro_generated_struct_fn_doc_attr() {
|
||||
mark::check!(hover_macro_generated_struct_fn_doc_attr);
|
||||
|
||||
check_hover_result(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
|
@ -1176,4 +1225,89 @@ fn func(foo: i32) { if true { <|>foo; }; }
|
|||
);
|
||||
assert_impl_action(&actions[0], 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hover_test_has_action() {
|
||||
let (_, actions) = check_hover_result(
|
||||
"
|
||||
//- /lib.rs
|
||||
#[test]
|
||||
fn foo_<|>test() {}
|
||||
",
|
||||
&["fn foo_test()"],
|
||||
);
|
||||
assert_debug_snapshot!(actions,
|
||||
@r###"
|
||||
[
|
||||
Runnable(
|
||||
Runnable {
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 0..24,
|
||||
name: "foo_test",
|
||||
kind: FN_DEF,
|
||||
focus_range: Some(
|
||||
11..19,
|
||||
),
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: Test {
|
||||
test_id: Path(
|
||||
"foo_test",
|
||||
),
|
||||
attr: TestAttr {
|
||||
ignore: false,
|
||||
},
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
),
|
||||
]
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hover_test_mod_has_action() {
|
||||
let (_, actions) = check_hover_result(
|
||||
"
|
||||
//- /lib.rs
|
||||
mod tests<|> {
|
||||
#[test]
|
||||
fn foo_test() {}
|
||||
}
|
||||
",
|
||||
&["mod tests"],
|
||||
);
|
||||
assert_debug_snapshot!(actions,
|
||||
@r###"
|
||||
[
|
||||
Runnable(
|
||||
Runnable {
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 0..46,
|
||||
name: "tests",
|
||||
kind: MODULE,
|
||||
focus_range: Some(
|
||||
4..9,
|
||||
),
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: TestMod {
|
||||
path: "tests",
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
),
|
||||
]
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@ use ra_syntax::{
|
|||
|
||||
use crate::{display::ToNav, FileId, NavigationTarget};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Runnable {
|
||||
pub nav: NavigationTarget,
|
||||
pub kind: RunnableKind,
|
||||
pub cfg_exprs: Vec<CfgExpr>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TestId {
|
||||
Name(String),
|
||||
Path(String),
|
||||
|
@ -33,7 +33,7 @@ impl fmt::Display for TestId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RunnableKind {
|
||||
Test { test_id: TestId, attr: TestAttr },
|
||||
TestMod { path: String },
|
||||
|
@ -42,6 +42,42 @@ pub enum RunnableKind {
|
|||
Bin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct RunnableAction {
|
||||
pub run_title: &'static str,
|
||||
pub debugee: bool,
|
||||
}
|
||||
|
||||
const TEST: RunnableAction = RunnableAction { run_title: "▶\u{fe0e} Run Test", debugee: true };
|
||||
const DOCTEST: RunnableAction =
|
||||
RunnableAction { run_title: "▶\u{fe0e} Run Doctest", debugee: false };
|
||||
const BENCH: RunnableAction = RunnableAction { run_title: "▶\u{fe0e} Run Bench", debugee: true };
|
||||
const BIN: RunnableAction = RunnableAction { run_title: "▶\u{fe0e} Run", debugee: true };
|
||||
|
||||
impl Runnable {
|
||||
// test package::module::testname
|
||||
pub fn label(&self, target: Option<String>) -> String {
|
||||
match &self.kind {
|
||||
RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
|
||||
RunnableKind::TestMod { path } => format!("test-mod {}", path),
|
||||
RunnableKind::Bench { test_id } => format!("bench {}", test_id),
|
||||
RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id),
|
||||
RunnableKind::Bin => {
|
||||
target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn action(&self) -> &'static RunnableAction {
|
||||
match &self.kind {
|
||||
RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => &TEST,
|
||||
RunnableKind::DocTest { .. } => &DOCTEST,
|
||||
RunnableKind::Bench { .. } => &BENCH,
|
||||
RunnableKind::Bin => &BIN,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Feature: Run
|
||||
//
|
||||
// Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
|
||||
|
@ -59,7 +95,11 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
|||
source_file.syntax().descendants().filter_map(|i| runnable(&sema, i, file_id)).collect()
|
||||
}
|
||||
|
||||
fn runnable(sema: &Semantics<RootDatabase>, item: SyntaxNode, file_id: FileId) -> Option<Runnable> {
|
||||
pub(crate) fn runnable(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
item: SyntaxNode,
|
||||
file_id: FileId,
|
||||
) -> Option<Runnable> {
|
||||
match_ast! {
|
||||
match item {
|
||||
ast::FnDef(it) => runnable_fn(sema, it, file_id),
|
||||
|
@ -135,7 +175,7 @@ fn runnable_fn(
|
|||
Some(Runnable { nav, kind, cfg_exprs })
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TestAttr {
|
||||
pub ignore: bool,
|
||||
}
|
||||
|
@ -207,6 +247,15 @@ mod tests {
|
|||
|
||||
use crate::mock_analysis::analysis_and_position;
|
||||
|
||||
use super::{Runnable, RunnableAction, BENCH, BIN, DOCTEST, TEST};
|
||||
|
||||
fn assert_actions(runnables: &[Runnable], actions: &[&RunnableAction]) {
|
||||
assert_eq!(
|
||||
actions,
|
||||
runnables.into_iter().map(|it| it.action()).collect::<Vec<_>>().as_slice()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_runnables() {
|
||||
let (analysis, pos) = analysis_and_position(
|
||||
|
@ -221,6 +270,9 @@ mod tests {
|
|||
#[test]
|
||||
#[ignore]
|
||||
fn test_foo() {}
|
||||
|
||||
#[bench]
|
||||
fn bench() {}
|
||||
"#,
|
||||
);
|
||||
let runnables = analysis.runnables(pos.file_id).unwrap();
|
||||
|
@ -295,9 +347,32 @@ mod tests {
|
|||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
Runnable {
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 82..104,
|
||||
name: "bench",
|
||||
kind: FN_DEF,
|
||||
focus_range: Some(
|
||||
94..99,
|
||||
),
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: Bench {
|
||||
test_id: Path(
|
||||
"bench",
|
||||
),
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&BIN, &TEST, &TEST, &BENCH]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -361,6 +436,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&BIN, &DOCTEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -427,6 +503,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&BIN, &DOCTEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -493,6 +570,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&TEST, &TEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -561,6 +639,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&TEST, &TEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -631,6 +710,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&TEST, &TEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -681,6 +761,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&TEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -739,6 +820,7 @@ mod tests {
|
|||
]
|
||||
"###
|
||||
);
|
||||
assert_actions(&runnables, &[&TEST]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -285,6 +285,8 @@ impl Config {
|
|||
set(value, "/hoverActions/enable", &mut use_hover_actions);
|
||||
if use_hover_actions {
|
||||
set(value, "/hoverActions/implementations", &mut self.hover.implementations);
|
||||
set(value, "/hoverActions/run", &mut self.hover.run);
|
||||
set(value, "/hoverActions/debug", &mut self.hover.debug);
|
||||
} else {
|
||||
self.hover = HoverConfig::NO_ACTIONS;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ use lsp_types::{
|
|||
TextDocumentIdentifier, Url, WorkspaceEdit,
|
||||
};
|
||||
use ra_ide::{
|
||||
FileId, FilePosition, FileRange, HoverAction, Query, RangeInfo, RunnableKind, SearchScope,
|
||||
TextEdit,
|
||||
FileId, FilePosition, FileRange, HoverAction, Query, RangeInfo, Runnable, RunnableKind,
|
||||
SearchScope, TextEdit,
|
||||
};
|
||||
use ra_prof::profile;
|
||||
use ra_project_model::TargetKind;
|
||||
|
@ -404,15 +404,10 @@ pub fn handle_runnables(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
// Do not suggest binary run on other target than binary
|
||||
if let RunnableKind::Bin = runnable.kind {
|
||||
if let Some(spec) = &cargo_spec {
|
||||
match spec.target_kind {
|
||||
TargetKind::Bin => {}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
if should_skip_target(&runnable, cargo_spec.as_ref()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res.push(to_proto::runnable(&snap, file_id, runnable)?);
|
||||
}
|
||||
|
||||
|
@ -555,7 +550,7 @@ pub fn handle_hover(
|
|||
}),
|
||||
range: Some(range),
|
||||
},
|
||||
actions: prepare_hover_actions(&snap, info.info.actions()),
|
||||
actions: prepare_hover_actions(&snap, position.file_id, info.info.actions()),
|
||||
};
|
||||
|
||||
Ok(Some(hover))
|
||||
|
@ -817,55 +812,25 @@ pub fn handle_code_lens(
|
|||
if snap.config.lens.runnable() {
|
||||
// Gather runnables
|
||||
for runnable in snap.analysis().runnables(file_id)? {
|
||||
let (run_title, debugee) = match &runnable.kind {
|
||||
RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => {
|
||||
("▶\u{fe0e} Run Test", true)
|
||||
}
|
||||
RunnableKind::DocTest { .. } => {
|
||||
// cargo does not support -no-run for doctests
|
||||
("▶\u{fe0e} Run Doctest", false)
|
||||
}
|
||||
RunnableKind::Bench { .. } => {
|
||||
// Nothing wrong with bench debugging
|
||||
("Run Bench", true)
|
||||
}
|
||||
RunnableKind::Bin => {
|
||||
// Do not suggest binary run on other target than binary
|
||||
match &cargo_spec {
|
||||
Some(spec) => match spec.target_kind {
|
||||
TargetKind::Bin => ("Run", true),
|
||||
_ => continue,
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
};
|
||||
if should_skip_target(&runnable, cargo_spec.as_ref()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let action = runnable.action();
|
||||
let range = to_proto::range(&line_index, runnable.nav.range());
|
||||
let r = to_proto::runnable(&snap, file_id, runnable)?;
|
||||
if snap.config.lens.run {
|
||||
let lens = CodeLens {
|
||||
range,
|
||||
command: Some(Command {
|
||||
title: run_title.to_string(),
|
||||
command: "rust-analyzer.runSingle".into(),
|
||||
arguments: Some(vec![to_value(&r).unwrap()]),
|
||||
}),
|
||||
command: Some(run_single_command(&r, action.run_title)),
|
||||
data: None,
|
||||
};
|
||||
lenses.push(lens);
|
||||
}
|
||||
|
||||
if debugee && snap.config.lens.debug {
|
||||
let debug_lens = CodeLens {
|
||||
range,
|
||||
command: Some(Command {
|
||||
title: "Debug".into(),
|
||||
command: "rust-analyzer.debugSingle".into(),
|
||||
arguments: Some(vec![to_value(r).unwrap()]),
|
||||
}),
|
||||
data: None,
|
||||
};
|
||||
if action.debugee && snap.config.lens.debug {
|
||||
let debug_lens =
|
||||
CodeLens { range, command: Some(debug_single_command(&r)), data: None };
|
||||
lenses.push(debug_lens);
|
||||
}
|
||||
}
|
||||
|
@ -1169,6 +1134,22 @@ fn show_references_command(
|
|||
}
|
||||
}
|
||||
|
||||
fn run_single_command(runnable: &lsp_ext::Runnable, title: &str) -> Command {
|
||||
Command {
|
||||
title: title.to_string(),
|
||||
command: "rust-analyzer.runSingle".into(),
|
||||
arguments: Some(vec![to_value(runnable).unwrap()]),
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_single_command(runnable: &lsp_ext::Runnable) -> Command {
|
||||
Command {
|
||||
title: "Debug".into(),
|
||||
command: "rust-analyzer.debugSingle".into(),
|
||||
arguments: Some(vec![to_value(runnable).unwrap()]),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink {
|
||||
lsp_ext::CommandLink { tooltip: Some(tooltip), command }
|
||||
}
|
||||
|
@ -1199,8 +1180,37 @@ fn show_impl_command_link(
|
|||
None
|
||||
}
|
||||
|
||||
fn to_runnable_action(
|
||||
snap: &GlobalStateSnapshot,
|
||||
file_id: FileId,
|
||||
runnable: Runnable,
|
||||
) -> Option<lsp_ext::CommandLinkGroup> {
|
||||
let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?;
|
||||
if should_skip_target(&runnable, cargo_spec.as_ref()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let action: &'static _ = runnable.action();
|
||||
to_proto::runnable(snap, file_id, runnable).ok().map(|r| {
|
||||
let mut group = lsp_ext::CommandLinkGroup::default();
|
||||
|
||||
if snap.config.hover.run {
|
||||
let run_command = run_single_command(&r, action.run_title);
|
||||
group.commands.push(to_command_link(run_command, r.label.clone()));
|
||||
}
|
||||
|
||||
if snap.config.hover.debug {
|
||||
let dbg_command = debug_single_command(&r);
|
||||
group.commands.push(to_command_link(dbg_command, r.label));
|
||||
}
|
||||
|
||||
group
|
||||
})
|
||||
}
|
||||
|
||||
fn prepare_hover_actions(
|
||||
snap: &GlobalStateSnapshot,
|
||||
file_id: FileId,
|
||||
actions: &[HoverAction],
|
||||
) -> Vec<lsp_ext::CommandLinkGroup> {
|
||||
if snap.config.hover.none() || !snap.config.client_caps.hover_actions {
|
||||
|
@ -1211,6 +1221,20 @@ fn prepare_hover_actions(
|
|||
.iter()
|
||||
.filter_map(|it| match it {
|
||||
HoverAction::Implementaion(position) => show_impl_command_link(snap, position),
|
||||
HoverAction::Runnable(r) => to_runnable_action(snap, file_id, r.clone()),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&CargoTargetSpec>) -> bool {
|
||||
match runnable.kind {
|
||||
RunnableKind::Bin => {
|
||||
// Do not suggest binary run on other target than binary
|
||||
match &cargo_spec {
|
||||
Some(spec) => spec.target_kind != TargetKind::Bin,
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use ra_ide::{
|
|||
Assist, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind,
|
||||
FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, Indel,
|
||||
InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess,
|
||||
ResolvedAssist, Runnable, RunnableKind, Severity, SourceChange, SourceFileEdit, TextEdit,
|
||||
ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit,
|
||||
};
|
||||
use ra_syntax::{SyntaxKind, TextRange, TextSize};
|
||||
use ra_vfs::LineEndings;
|
||||
|
@ -662,15 +662,7 @@ pub(crate) fn runnable(
|
|||
let target = spec.as_ref().map(|s| s.target.clone());
|
||||
let (cargo_args, executable_args) =
|
||||
CargoTargetSpec::runnable_args(spec, &runnable.kind, &runnable.cfg_exprs)?;
|
||||
let label = match &runnable.kind {
|
||||
RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
|
||||
RunnableKind::TestMod { path } => format!("test-mod {}", path),
|
||||
RunnableKind::Bench { test_id } => format!("bench {}", test_id),
|
||||
RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id),
|
||||
RunnableKind::Bin => {
|
||||
target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
|
||||
}
|
||||
};
|
||||
let label = runnable.label(target);
|
||||
let location = location_link(snap, None, runnable.nav)?;
|
||||
|
||||
Ok(lsp_ext::Runnable {
|
||||
|
|
|
@ -486,6 +486,16 @@
|
|||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"rust-analyzer.hoverActions.run": {
|
||||
"markdownDescription": "Whether to show `Run` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"rust-analyzer.hoverActions.debug": {
|
||||
"markdownDescription": "Whether to show `Debug` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"rust-analyzer.linkedProjects": {
|
||||
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects. \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format",
|
||||
"type": "array",
|
||||
|
|
Loading…
Reference in a new issue