aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs66
-rw-r--r--crates/ra_ide/src/runnables.rs250
-rw-r--r--crates/rust-analyzer/src/caps.rs3
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs31
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs41
-rw-r--r--crates/rust-analyzer/src/to_proto.rs18
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs113
7 files changed, 354 insertions, 168 deletions
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index 5da28edd2..c7bb1e69f 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -92,15 +92,16 @@ impl NavigationTarget {
92 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 92 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
93 if let Some(src) = module.declaration_source(db) { 93 if let Some(src) = module.declaration_source(db) {
94 let frange = original_range(db, src.as_ref().map(|it| it.syntax())); 94 let frange = original_range(db, src.as_ref().map(|it| it.syntax()));
95 return NavigationTarget::from_syntax( 95 let mut res = NavigationTarget::from_syntax(
96 frange.file_id, 96 frange.file_id,
97 name, 97 name,
98 None, 98 None,
99 frange.range, 99 frange.range,
100 src.value.syntax().kind(), 100 src.value.syntax().kind(),
101 src.value.doc_comment_text(),
102 src.value.short_label(),
103 ); 101 );
102 res.docs = src.value.doc_comment_text();
103 res.description = src.value.short_label();
104 return res;
104 } 105 }
105 module.to_nav(db) 106 module.to_nav(db)
106 } 107 }
@@ -130,11 +131,9 @@ impl NavigationTarget {
130 } 131 }
131 132
132 /// Allows `NavigationTarget` to be created from a `NameOwner` 133 /// Allows `NavigationTarget` to be created from a `NameOwner`
133 fn from_named( 134 pub(crate) fn from_named(
134 db: &RootDatabase, 135 db: &RootDatabase,
135 node: InFile<&dyn ast::NameOwner>, 136 node: InFile<&dyn ast::NameOwner>,
136 docs: Option<String>,
137 description: Option<String>,
138 ) -> NavigationTarget { 137 ) -> NavigationTarget {
139 //FIXME: use `_` instead of empty string 138 //FIXME: use `_` instead of empty string
140 let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); 139 let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default();
@@ -148,8 +147,6 @@ impl NavigationTarget {
148 focus_range, 147 focus_range,
149 frange.range, 148 frange.range,
150 node.value.syntax().kind(), 149 node.value.syntax().kind(),
151 docs,
152 description,
153 ) 150 )
154 } 151 }
155 152
@@ -159,8 +156,6 @@ impl NavigationTarget {
159 focus_range: Option<TextRange>, 156 focus_range: Option<TextRange>,
160 full_range: TextRange, 157 full_range: TextRange,
161 kind: SyntaxKind, 158 kind: SyntaxKind,
162 docs: Option<String>,
163 description: Option<String>,
164 ) -> NavigationTarget { 159 ) -> NavigationTarget {
165 NavigationTarget { 160 NavigationTarget {
166 file_id, 161 file_id,
@@ -169,8 +164,8 @@ impl NavigationTarget {
169 full_range, 164 full_range,
170 focus_range, 165 focus_range,
171 container_name: None, 166 container_name: None,
172 description, 167 description: None,
173 docs, 168 docs: None,
174 } 169 }
175 } 170 }
176} 171}
@@ -238,12 +233,11 @@ where
238{ 233{
239 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 234 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
240 let src = self.source(db); 235 let src = self.source(db);
241 NavigationTarget::from_named( 236 let mut res =
242 db, 237 NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
243 src.as_ref().map(|it| it as &dyn ast::NameOwner), 238 res.docs = src.value.doc_comment_text();
244 src.value.doc_comment_text(), 239 res.description = src.value.short_label();
245 src.value.short_label(), 240 res
246 )
247 } 241 }
248} 242}
249 243
@@ -258,15 +252,7 @@ impl ToNav for hir::Module {
258 } 252 }
259 }; 253 };
260 let frange = original_range(db, src.with_value(syntax)); 254 let frange = original_range(db, src.with_value(syntax));
261 NavigationTarget::from_syntax( 255 NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, syntax.kind())
262 frange.file_id,
263 name,
264 focus,
265 frange.range,
266 syntax.kind(),
267 None,
268 None,
269 )
270 } 256 }
271} 257}
272 258
@@ -285,8 +271,6 @@ impl ToNav for hir::ImplDef {
285 None, 271 None,
286 frange.range, 272 frange.range,
287 src.value.syntax().kind(), 273 src.value.syntax().kind(),
288 None,
289 None,
290 ) 274 )
291 } 275 }
292} 276}
@@ -296,12 +280,12 @@ impl ToNav for hir::Field {
296 let src = self.source(db); 280 let src = self.source(db);
297 281
298 match &src.value { 282 match &src.value {
299 FieldSource::Named(it) => NavigationTarget::from_named( 283 FieldSource::Named(it) => {
300 db, 284 let mut res = NavigationTarget::from_named(db, src.with_value(it));
301 src.with_value(it), 285 res.docs = it.doc_comment_text();
302 it.doc_comment_text(), 286 res.description = it.short_label();
303 it.short_label(), 287 res
304 ), 288 }
305 FieldSource::Pos(it) => { 289 FieldSource::Pos(it) => {
306 let frange = original_range(db, src.with_value(it.syntax())); 290 let frange = original_range(db, src.with_value(it.syntax()));
307 NavigationTarget::from_syntax( 291 NavigationTarget::from_syntax(
@@ -310,8 +294,6 @@ impl ToNav for hir::Field {
310 None, 294 None,
311 frange.range, 295 frange.range,
312 it.syntax().kind(), 296 it.syntax().kind(),
313 None,
314 None,
315 ) 297 )
316 } 298 }
317 } 299 }
@@ -322,12 +304,10 @@ impl ToNav for hir::MacroDef {
322 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 304 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
323 let src = self.source(db); 305 let src = self.source(db);
324 log::debug!("nav target {:#?}", src.value.syntax()); 306 log::debug!("nav target {:#?}", src.value.syntax());
325 NavigationTarget::from_named( 307 let mut res =
326 db, 308 NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
327 src.as_ref().map(|it| it as &dyn ast::NameOwner), 309 res.docs = src.value.doc_comment_text();
328 src.value.doc_comment_text(), 310 res
329 None,
330 )
331 } 311 }
332} 312}
333 313
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs
index 286d45eee..f32ce0d22 100644
--- a/crates/ra_ide/src/runnables.rs
+++ b/crates/ra_ide/src/runnables.rs
@@ -1,19 +1,19 @@
1use std::fmt;
2
1use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics}; 3use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
2use itertools::Itertools; 4use itertools::Itertools;
5use ra_cfg::CfgExpr;
3use ra_ide_db::RootDatabase; 6use ra_ide_db::RootDatabase;
4use ra_syntax::{ 7use ra_syntax::{
5 ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner}, 8 ast::{self, AstNode, AttrsOwner, DocCommentsOwner, ModuleItemOwner, NameOwner},
6 match_ast, SyntaxNode, TextRange, 9 match_ast, SyntaxNode,
7}; 10};
8 11
9use crate::FileId; 12use crate::{display::ToNav, FileId, NavigationTarget};
10use ast::DocCommentsOwner;
11use ra_cfg::CfgExpr;
12use std::fmt::Display;
13 13
14#[derive(Debug)] 14#[derive(Debug)]
15pub struct Runnable { 15pub struct Runnable {
16 pub range: TextRange, 16 pub nav: NavigationTarget,
17 pub kind: RunnableKind, 17 pub kind: RunnableKind,
18 pub cfg_exprs: Vec<CfgExpr>, 18 pub cfg_exprs: Vec<CfgExpr>,
19} 19}
@@ -24,8 +24,8 @@ pub enum TestId {
24 Path(String), 24 Path(String),
25} 25}
26 26
27impl Display for TestId { 27impl fmt::Display for TestId {
28 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 28 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29 match self { 29 match self {
30 TestId::Name(name) => write!(f, "{}", name), 30 TestId::Name(name) => write!(f, "{}", name),
31 TestId::Path(path) => write!(f, "{}", path), 31 TestId::Path(path) => write!(f, "{}", path),
@@ -131,7 +131,8 @@ fn runnable_fn(
131 let cfg_exprs = 131 let cfg_exprs =
132 attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); 132 attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
133 133
134 Some(Runnable { range: fn_def.syntax().text_range(), kind, cfg_exprs }) 134 let nav = NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def));
135 Some(Runnable { nav, kind, cfg_exprs })
135} 136}
136 137
137#[derive(Debug)] 138#[derive(Debug)]
@@ -183,7 +184,6 @@ fn runnable_mod(
183 if !has_test_function { 184 if !has_test_function {
184 return None; 185 return None;
185 } 186 }
186 let range = module.syntax().text_range();
187 let module_def = sema.to_def(&module)?; 187 let module_def = sema.to_def(&module)?;
188 188
189 let path = module_def 189 let path = module_def
@@ -197,7 +197,8 @@ fn runnable_mod(
197 let cfg_exprs = 197 let cfg_exprs =
198 attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); 198 attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
199 199
200 Some(Runnable { range, kind: RunnableKind::TestMod { path }, cfg_exprs }) 200 let nav = module_def.to_nav(sema.db);
201 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs })
201} 202}
202 203
203#[cfg(test)] 204#[cfg(test)]
@@ -227,12 +228,38 @@ mod tests {
227 @r###" 228 @r###"
228 [ 229 [
229 Runnable { 230 Runnable {
230 range: 1..21, 231 nav: NavigationTarget {
232 file_id: FileId(
233 1,
234 ),
235 full_range: 1..21,
236 name: "main",
237 kind: FN_DEF,
238 focus_range: Some(
239 12..16,
240 ),
241 container_name: None,
242 description: None,
243 docs: None,
244 },
231 kind: Bin, 245 kind: Bin,
232 cfg_exprs: [], 246 cfg_exprs: [],
233 }, 247 },
234 Runnable { 248 Runnable {
235 range: 22..46, 249 nav: NavigationTarget {
250 file_id: FileId(
251 1,
252 ),
253 full_range: 22..46,
254 name: "test_foo",
255 kind: FN_DEF,
256 focus_range: Some(
257 33..41,
258 ),
259 container_name: None,
260 description: None,
261 docs: None,
262 },
236 kind: Test { 263 kind: Test {
237 test_id: Path( 264 test_id: Path(
238 "test_foo", 265 "test_foo",
@@ -244,7 +271,20 @@ mod tests {
244 cfg_exprs: [], 271 cfg_exprs: [],
245 }, 272 },
246 Runnable { 273 Runnable {
247 range: 47..81, 274 nav: NavigationTarget {
275 file_id: FileId(
276 1,
277 ),
278 full_range: 47..81,
279 name: "test_foo",
280 kind: FN_DEF,
281 focus_range: Some(
282 68..76,
283 ),
284 container_name: None,
285 description: None,
286 docs: None,
287 },
248 kind: Test { 288 kind: Test {
249 test_id: Path( 289 test_id: Path(
250 "test_foo", 290 "test_foo",
@@ -279,12 +319,38 @@ mod tests {
279 @r###" 319 @r###"
280 [ 320 [
281 Runnable { 321 Runnable {
282 range: 1..21, 322 nav: NavigationTarget {
323 file_id: FileId(
324 1,
325 ),
326 full_range: 1..21,
327 name: "main",
328 kind: FN_DEF,
329 focus_range: Some(
330 12..16,
331 ),
332 container_name: None,
333 description: None,
334 docs: None,
335 },
283 kind: Bin, 336 kind: Bin,
284 cfg_exprs: [], 337 cfg_exprs: [],
285 }, 338 },
286 Runnable { 339 Runnable {
287 range: 22..64, 340 nav: NavigationTarget {
341 file_id: FileId(
342 1,
343 ),
344 full_range: 22..64,
345 name: "foo",
346 kind: FN_DEF,
347 focus_range: Some(
348 56..59,
349 ),
350 container_name: None,
351 description: None,
352 docs: None,
353 },
288 kind: DocTest { 354 kind: DocTest {
289 test_id: Path( 355 test_id: Path(
290 "foo", 356 "foo",
@@ -319,12 +385,38 @@ mod tests {
319 @r###" 385 @r###"
320 [ 386 [
321 Runnable { 387 Runnable {
322 range: 1..21, 388 nav: NavigationTarget {
389 file_id: FileId(
390 1,
391 ),
392 full_range: 1..21,
393 name: "main",
394 kind: FN_DEF,
395 focus_range: Some(
396 12..16,
397 ),
398 container_name: None,
399 description: None,
400 docs: None,
401 },
323 kind: Bin, 402 kind: Bin,
324 cfg_exprs: [], 403 cfg_exprs: [],
325 }, 404 },
326 Runnable { 405 Runnable {
327 range: 51..105, 406 nav: NavigationTarget {
407 file_id: FileId(
408 1,
409 ),
410 full_range: 51..105,
411 name: "foo",
412 kind: FN_DEF,
413 focus_range: Some(
414 97..100,
415 ),
416 container_name: None,
417 description: None,
418 docs: None,
419 },
328 kind: DocTest { 420 kind: DocTest {
329 test_id: Path( 421 test_id: Path(
330 "Data::foo", 422 "Data::foo",
@@ -354,14 +446,40 @@ mod tests {
354 @r###" 446 @r###"
355 [ 447 [
356 Runnable { 448 Runnable {
357 range: 1..59, 449 nav: NavigationTarget {
450 file_id: FileId(
451 1,
452 ),
453 full_range: 1..59,
454 name: "test_mod",
455 kind: MODULE,
456 focus_range: Some(
457 13..21,
458 ),
459 container_name: None,
460 description: None,
461 docs: None,
462 },
358 kind: TestMod { 463 kind: TestMod {
359 path: "test_mod", 464 path: "test_mod",
360 }, 465 },
361 cfg_exprs: [], 466 cfg_exprs: [],
362 }, 467 },
363 Runnable { 468 Runnable {
364 range: 28..57, 469 nav: NavigationTarget {
470 file_id: FileId(
471 1,
472 ),
473 full_range: 28..57,
474 name: "test_foo1",
475 kind: FN_DEF,
476 focus_range: Some(
477 43..52,
478 ),
479 container_name: None,
480 description: None,
481 docs: None,
482 },
365 kind: Test { 483 kind: Test {
366 test_id: Path( 484 test_id: Path(
367 "test_mod::test_foo1", 485 "test_mod::test_foo1",
@@ -396,14 +514,40 @@ mod tests {
396 @r###" 514 @r###"
397 [ 515 [
398 Runnable { 516 Runnable {
399 range: 23..85, 517 nav: NavigationTarget {
518 file_id: FileId(
519 1,
520 ),
521 full_range: 23..85,
522 name: "test_mod",
523 kind: MODULE,
524 focus_range: Some(
525 27..35,
526 ),
527 container_name: None,
528 description: None,
529 docs: None,
530 },
400 kind: TestMod { 531 kind: TestMod {
401 path: "foo::test_mod", 532 path: "foo::test_mod",
402 }, 533 },
403 cfg_exprs: [], 534 cfg_exprs: [],
404 }, 535 },
405 Runnable { 536 Runnable {
406 range: 46..79, 537 nav: NavigationTarget {
538 file_id: FileId(
539 1,
540 ),
541 full_range: 46..79,
542 name: "test_foo1",
543 kind: FN_DEF,
544 focus_range: Some(
545 65..74,
546 ),
547 container_name: None,
548 description: None,
549 docs: None,
550 },
407 kind: Test { 551 kind: Test {
408 test_id: Path( 552 test_id: Path(
409 "foo::test_mod::test_foo1", 553 "foo::test_mod::test_foo1",
@@ -440,14 +584,40 @@ mod tests {
440 @r###" 584 @r###"
441 [ 585 [
442 Runnable { 586 Runnable {
443 range: 41..115, 587 nav: NavigationTarget {
588 file_id: FileId(
589 1,
590 ),
591 full_range: 41..115,
592 name: "test_mod",
593 kind: MODULE,
594 focus_range: Some(
595 45..53,
596 ),
597 container_name: None,
598 description: None,
599 docs: None,
600 },
444 kind: TestMod { 601 kind: TestMod {
445 path: "foo::bar::test_mod", 602 path: "foo::bar::test_mod",
446 }, 603 },
447 cfg_exprs: [], 604 cfg_exprs: [],
448 }, 605 },
449 Runnable { 606 Runnable {
450 range: 68..105, 607 nav: NavigationTarget {
608 file_id: FileId(
609 1,
610 ),
611 full_range: 68..105,
612 name: "test_foo1",
613 kind: FN_DEF,
614 focus_range: Some(
615 91..100,
616 ),
617 container_name: None,
618 description: None,
619 docs: None,
620 },
451 kind: Test { 621 kind: Test {
452 test_id: Path( 622 test_id: Path(
453 "foo::bar::test_mod::test_foo1", 623 "foo::bar::test_mod::test_foo1",
@@ -479,7 +649,20 @@ mod tests {
479 @r###" 649 @r###"
480 [ 650 [
481 Runnable { 651 Runnable {
482 range: 1..58, 652 nav: NavigationTarget {
653 file_id: FileId(
654 1,
655 ),
656 full_range: 1..58,
657 name: "test_foo1",
658 kind: FN_DEF,
659 focus_range: Some(
660 44..53,
661 ),
662 container_name: None,
663 description: None,
664 docs: None,
665 },
483 kind: Test { 666 kind: Test {
484 test_id: Path( 667 test_id: Path(
485 "test_foo1", 668 "test_foo1",
@@ -516,7 +699,20 @@ mod tests {
516 @r###" 699 @r###"
517 [ 700 [
518 Runnable { 701 Runnable {
519 range: 1..80, 702 nav: NavigationTarget {
703 file_id: FileId(
704 1,
705 ),
706 full_range: 1..80,
707 name: "test_foo1",
708 kind: FN_DEF,
709 focus_range: Some(
710 66..75,
711 ),
712 container_name: None,
713 description: None,
714 docs: None,
715 },
520 kind: Test { 716 kind: Test {
521 test_id: Path( 717 test_id: Path(
522 "test_foo1", 718 "test_foo1",
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 345693524..673795e78 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -87,6 +87,9 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
87 "ssr": true, 87 "ssr": true,
88 "onEnter": true, 88 "onEnter": true,
89 "parentModule": true, 89 "parentModule": true,
90 "runnables": {
91 "kinds": [ "cargo" ],
92 },
90 })), 93 })),
91 } 94 }
92} 95}
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 173c23b9e..ec24ce5e0 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -4,7 +4,6 @@ use std::{collections::HashMap, path::PathBuf};
4 4
5use lsp_types::request::Request; 5use lsp_types::request::Request;
6use lsp_types::{Position, Range, TextDocumentIdentifier}; 6use lsp_types::{Position, Range, TextDocumentIdentifier};
7use rustc_hash::FxHashMap;
8use serde::{Deserialize, Serialize}; 7use serde::{Deserialize, Serialize};
9 8
10pub enum AnalyzerStatus {} 9pub enum AnalyzerStatus {}
@@ -111,7 +110,7 @@ pub enum Runnables {}
111impl Request for Runnables { 110impl Request for Runnables {
112 type Params = RunnablesParams; 111 type Params = RunnablesParams;
113 type Result = Vec<Runnable>; 112 type Result = Vec<Runnable>;
114 const METHOD: &'static str = "rust-analyzer/runnables"; 113 const METHOD: &'static str = "experimental/runnables";
115} 114}
116 115
117#[derive(Serialize, Deserialize, Debug)] 116#[derive(Serialize, Deserialize, Debug)]
@@ -121,25 +120,31 @@ pub struct RunnablesParams {
121 pub position: Option<Position>, 120 pub position: Option<Position>,
122} 121}
123 122
124// Must strictly correspond to the executable name 123#[derive(Deserialize, Serialize, Debug)]
124#[serde(rename_all = "camelCase")]
125pub struct Runnable {
126 pub label: String,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub location: Option<lsp_types::LocationLink>,
129 pub kind: RunnableKind,
130 pub args: CargoRunnable,
131}
132
125#[derive(Serialize, Deserialize, Debug)] 133#[derive(Serialize, Deserialize, Debug)]
126#[serde(rename_all = "lowercase")] 134#[serde(rename_all = "lowercase")]
127pub enum RunnableKind { 135pub enum RunnableKind {
128 Cargo, 136 Cargo,
129 Rustc,
130 Rustup,
131} 137}
132 138
133#[derive(Deserialize, Serialize, Debug)] 139#[derive(Deserialize, Serialize, Debug)]
134#[serde(rename_all = "camelCase")] 140#[serde(rename_all = "camelCase")]
135pub struct Runnable { 141pub struct CargoRunnable {
136 pub range: Range, 142 #[serde(skip_serializing_if = "Option::is_none")]
137 pub label: String, 143 pub workspace_root: Option<PathBuf>,
138 pub kind: RunnableKind, 144 // command, --package and --lib stuff
139 pub args: Vec<String>, 145 pub cargo_args: Vec<String>,
140 pub extra_args: Vec<String>, 146 // stuff after --
141 pub env: FxHashMap<String, String>, 147 pub executable_args: Vec<String>,
142 pub cwd: Option<PathBuf>,
143} 148}
144 149
145pub enum InlayHints {} 150pub enum InlayHints {}
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 410c654ab..7fd691764 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -23,7 +23,6 @@ use ra_ide::{
23use ra_prof::profile; 23use ra_prof::profile;
24use ra_project_model::TargetKind; 24use ra_project_model::TargetKind;
25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; 25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize};
26use rustc_hash::FxHashMap;
27use serde::{Deserialize, Serialize}; 26use serde::{Deserialize, Serialize};
28use serde_json::to_value; 27use serde_json::to_value;
29use stdx::format_to; 28use stdx::format_to;
@@ -401,7 +400,7 @@ pub fn handle_runnables(
401 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?; 400 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
402 for runnable in world.analysis().runnables(file_id)? { 401 for runnable in world.analysis().runnables(file_id)? {
403 if let Some(offset) = offset { 402 if let Some(offset) = offset {
404 if !runnable.range.contains_inclusive(offset) { 403 if !runnable.nav.full_range().contains_inclusive(offset) {
405 continue; 404 continue;
406 } 405 }
407 } 406 }
@@ -422,25 +421,31 @@ pub fn handle_runnables(
422 Some(spec) => { 421 Some(spec) => {
423 for &cmd in ["check", "test"].iter() { 422 for &cmd in ["check", "test"].iter() {
424 res.push(lsp_ext::Runnable { 423 res.push(lsp_ext::Runnable {
425 range: Default::default(),
426 label: format!("cargo {} -p {}", cmd, spec.package), 424 label: format!("cargo {} -p {}", cmd, spec.package),
425 location: None,
427 kind: lsp_ext::RunnableKind::Cargo, 426 kind: lsp_ext::RunnableKind::Cargo,
428 args: vec![cmd.to_string(), "--package".to_string(), spec.package.clone()], 427 args: lsp_ext::CargoRunnable {
429 extra_args: Vec::new(), 428 workspace_root: workspace_root.map(|root| root.to_owned()),
430 env: FxHashMap::default(), 429 cargo_args: vec![
431 cwd: workspace_root.map(|root| root.to_owned()), 430 cmd.to_string(),
431 "--package".to_string(),
432 spec.package.clone(),
433 ],
434 executable_args: Vec::new(),
435 },
432 }) 436 })
433 } 437 }
434 } 438 }
435 None => { 439 None => {
436 res.push(lsp_ext::Runnable { 440 res.push(lsp_ext::Runnable {
437 range: Default::default(),
438 label: "cargo check --workspace".to_string(), 441 label: "cargo check --workspace".to_string(),
442 location: None,
439 kind: lsp_ext::RunnableKind::Cargo, 443 kind: lsp_ext::RunnableKind::Cargo,
440 args: vec!["check".to_string(), "--workspace".to_string()], 444 args: lsp_ext::CargoRunnable {
441 extra_args: Vec::new(), 445 workspace_root: workspace_root.map(|root| root.to_owned()),
442 env: FxHashMap::default(), 446 cargo_args: vec!["check".to_string(), "--workspace".to_string()],
443 cwd: workspace_root.map(|root| root.to_owned()), 447 executable_args: Vec::new(),
448 },
444 }); 449 });
445 } 450 }
446 } 451 }
@@ -782,10 +787,11 @@ pub fn handle_code_lens(
782 } 787 }
783 }; 788 };
784 789
785 let mut r = to_proto::runnable(&world, file_id, runnable)?; 790 let range = to_proto::range(&line_index, runnable.nav.range());
791 let r = to_proto::runnable(&world, file_id, runnable)?;
786 if world.config.lens.run { 792 if world.config.lens.run {
787 let lens = CodeLens { 793 let lens = CodeLens {
788 range: r.range, 794 range,
789 command: Some(Command { 795 command: Some(Command {
790 title: run_title.to_string(), 796 title: run_title.to_string(),
791 command: "rust-analyzer.runSingle".into(), 797 command: "rust-analyzer.runSingle".into(),
@@ -797,13 +803,8 @@ pub fn handle_code_lens(
797 } 803 }
798 804
799 if debugee && world.config.lens.debug { 805 if debugee && world.config.lens.debug {
800 if r.args[0] == "run" {
801 r.args[0] = "build".into();
802 } else {
803 r.args.push("--no-run".into());
804 }
805 let debug_lens = CodeLens { 806 let debug_lens = CodeLens {
806 range: r.range, 807 range,
807 command: Some(Command { 808 command: Some(Command {
808 title: "Debug".into(), 809 title: "Debug".into(),
809 command: "rust-analyzer.debugSingle".into(), 810 command: "rust-analyzer.debugSingle".into(),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 66144fe24..85304aa87 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -8,7 +8,6 @@ use ra_ide::{
8}; 8};
9use ra_syntax::{SyntaxKind, TextRange, TextSize}; 9use ra_syntax::{SyntaxKind, TextRange, TextSize};
10use ra_vfs::LineEndings; 10use ra_vfs::LineEndings;
11use rustc_hash::FxHashMap;
12 11
13use crate::{ 12use crate::{
14 cargo_target_spec::CargoTargetSpec, lsp_ext, semantic_tokens, world::WorldSnapshot, Result, 13 cargo_target_spec::CargoTargetSpec, lsp_ext, semantic_tokens, world::WorldSnapshot, Result,
@@ -638,9 +637,8 @@ pub(crate) fn runnable(
638) -> Result<lsp_ext::Runnable> { 637) -> Result<lsp_ext::Runnable> {
639 let spec = CargoTargetSpec::for_file(world, file_id)?; 638 let spec = CargoTargetSpec::for_file(world, file_id)?;
640 let target = spec.as_ref().map(|s| s.target.clone()); 639 let target = spec.as_ref().map(|s| s.target.clone());
641 let (args, extra_args) = 640 let (cargo_args, executable_args) =
642 CargoTargetSpec::runnable_args(spec, &runnable.kind, &runnable.cfg_exprs)?; 641 CargoTargetSpec::runnable_args(spec, &runnable.kind, &runnable.cfg_exprs)?;
643 let line_index = world.analysis().file_line_index(file_id)?;
644 let label = match &runnable.kind { 642 let label = match &runnable.kind {
645 RunnableKind::Test { test_id, .. } => format!("test {}", test_id), 643 RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
646 RunnableKind::TestMod { path } => format!("test-mod {}", path), 644 RunnableKind::TestMod { path } => format!("test-mod {}", path),
@@ -650,18 +648,16 @@ pub(crate) fn runnable(
650 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t)) 648 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
651 } 649 }
652 }; 650 };
651 let location = location_link(world, None, runnable.nav)?;
653 652
654 Ok(lsp_ext::Runnable { 653 Ok(lsp_ext::Runnable {
655 range: range(&line_index, runnable.range),
656 label, 654 label,
655 location: Some(location),
657 kind: lsp_ext::RunnableKind::Cargo, 656 kind: lsp_ext::RunnableKind::Cargo,
658 args, 657 args: lsp_ext::CargoRunnable {
659 extra_args, 658 workspace_root: world.workspace_root_for(file_id).map(|root| root.to_owned()),
660 env: { 659 cargo_args,
661 let mut m = FxHashMap::default(); 660 executable_args,
662 m.insert("RUST_BACKTRACE".to_string(), "short".to_string());
663 m
664 }, 661 },
665 cwd: world.workspace_root_for(file_id).map(|root| root.to_owned()),
666 }) 662 })
667} 663}
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs
index 8b473ff74..e18f973b8 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/main.rs
@@ -76,30 +76,33 @@ fn foo() {
76 server.request::<Runnables>( 76 server.request::<Runnables>(
77 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None }, 77 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None },
78 json!([ 78 json!([
79 { 79 {
80 "args": [ "test" ], 80 "args": {
81 "extraArgs": [ "foo", "--nocapture" ], 81 "cargoArgs": ["test"],
82 "kind": "cargo", 82 "executableArgs": ["foo", "--nocapture"],
83 "env": { "RUST_BACKTRACE": "short" }, 83 },
84 "cwd": null, 84 "kind": "cargo",
85 "label": "test foo", 85 "label": "test foo",
86 "range": { 86 "location": {
87 "end": { "character": 1, "line": 2 }, 87 "targetRange": {
88 "start": { "character": 0, "line": 0 } 88 "end": { "character": 1, "line": 2 },
89 } 89 "start": { "character": 0, "line": 0 }
90 }, 90 },
91 { 91 "targetSelectionRange": {
92 "args": ["check", "--workspace"], 92 "end": { "character": 6, "line": 1 },
93 "extraArgs": [], 93 "start": { "character": 3, "line": 1 }
94 "kind": "cargo", 94 },
95 "env": {}, 95 "targetUri": "file:///[..]/lib.rs"
96 "cwd": null, 96 }
97 "label": "cargo check --workspace", 97 },
98 "range": { 98 {
99 "end": { "character": 0, "line": 0 }, 99 "args": {
100 "start": { "character": 0, "line": 0 } 100 "cargoArgs": ["check", "--workspace"],
101 "executableArgs": [],
102 },
103 "kind": "cargo",
104 "label": "cargo check --workspace"
101 } 105 }
102 }
103 ]), 106 ]),
104 ); 107 );
105} 108}
@@ -138,42 +141,44 @@ fn main() {}
138 server.request::<Runnables>( 141 server.request::<Runnables>(
139 RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None }, 142 RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None },
140 json!([ 143 json!([
141 { 144 {
142 "args": [ "test", "--package", "foo", "--test", "spam" ], 145 "args": {
143 "extraArgs": [ "test_eggs", "--exact", "--nocapture" ], 146 "cargoArgs": ["test", "--package", "foo", "--test", "spam"],
144 "kind": "cargo", 147 "executableArgs": ["test_eggs", "--exact", "--nocapture"],
145 "env": { "RUST_BACKTRACE": "short" }, 148 "workspaceRoot": server.path().join("foo")
146 "label": "test test_eggs",
147 "range": {
148 "end": { "character": 17, "line": 1 },
149 "start": { "character": 0, "line": 0 }
150 },
151 "cwd": server.path().join("foo")
152 }, 149 },
153 { 150 "kind": "cargo",
154 "args": [ "check", "--package", "foo" ], 151 "label": "test test_eggs",
155 "extraArgs": [], 152 "location": {
156 "kind": "cargo", 153 "targetRange": {
157 "env": {}, 154 "end": { "character": 17, "line": 1 },
158 "label": "cargo check -p foo",
159 "range": {
160 "end": { "character": 0, "line": 0 },
161 "start": { "character": 0, "line": 0 } 155 "start": { "character": 0, "line": 0 }
162 }, 156 },
163 "cwd": server.path().join("foo") 157 "targetSelectionRange": {
164 }, 158 "end": { "character": 12, "line": 1 },
165 { 159 "start": { "character": 3, "line": 1 }
166 "args": [ "test", "--package", "foo" ],
167 "extraArgs": [],
168 "kind": "cargo",
169 "env": {},
170 "label": "cargo test -p foo",
171 "range": {
172 "end": { "character": 0, "line": 0 },
173 "start": { "character": 0, "line": 0 }
174 }, 160 },
175 "cwd": server.path().join("foo") 161 "targetUri": "file:///[..]/tests/spam.rs"
176 } 162 }
163 },
164 {
165 "args": {
166 "cargoArgs": ["check", "--package", "foo"],
167 "executableArgs": [],
168 "workspaceRoot": server.path().join("foo")
169 },
170 "kind": "cargo",
171 "label": "cargo check -p foo"
172 },
173 {
174 "args": {
175 "cargoArgs": ["test", "--package", "foo"],
176 "executableArgs": [],
177 "workspaceRoot": server.path().join("foo")
178 },
179 "kind": "cargo",
180 "label": "cargo test -p foo"
181 }
177 ]), 182 ]),
178 ); 183 );
179} 184}