aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock20
-rw-r--r--crates/ra_parser/src/grammar/params.rs44
-rw-r--r--crates/ra_syntax/src/tests.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.txt3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.txt3
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt3
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.txt133
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs42
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs28
-rw-r--r--crates/rust-analyzer/src/req.rs1
-rw-r--r--crates/rust-analyzer/src/world.rs1
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs15
-rw-r--r--editors/code/src/client.ts1
-rw-r--r--editors/code/src/commands/runnables.ts22
-rw-r--r--editors/code/src/main.ts1
-rw-r--r--editors/code/src/rust-analyzer-api.ts3
19 files changed, 271 insertions, 60 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f3707f116..41b6d4ab4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -58,9 +58,9 @@ dependencies = [
58 58
59[[package]] 59[[package]]
60name = "backtrace-sys" 60name = "backtrace-sys"
61version = "0.1.33" 61version = "0.1.34"
62source = "registry+https://github.com/rust-lang/crates.io-index" 62source = "registry+https://github.com/rust-lang/crates.io-index"
63checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" 63checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69"
64dependencies = [ 64dependencies = [
65 "cc", 65 "cc",
66 "libc", 66 "libc",
@@ -80,9 +80,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
80 80
81[[package]] 81[[package]]
82name = "bstr" 82name = "bstr"
83version = "0.2.11" 83version = "0.2.12"
84source = "registry+https://github.com/rust-lang/crates.io-index" 84source = "registry+https://github.com/rust-lang/crates.io-index"
85checksum = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" 85checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41"
86dependencies = [ 86dependencies = [
87 "memchr", 87 "memchr",
88] 88]
@@ -1230,9 +1230,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
1230 1230
1231[[package]] 1231[[package]]
1232name = "regex" 1232name = "regex"
1233version = "1.3.4" 1233version = "1.3.5"
1234source = "registry+https://github.com/rust-lang/crates.io-index" 1234source = "registry+https://github.com/rust-lang/crates.io-index"
1235checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" 1235checksum = "8900ebc1363efa7ea1c399ccc32daed870b4002651e0bed86e72d501ebbe0048"
1236dependencies = [ 1236dependencies = [
1237 "aho-corasick", 1237 "aho-corasick",
1238 "memchr", 1238 "memchr",
@@ -1242,9 +1242,9 @@ dependencies = [
1242 1242
1243[[package]] 1243[[package]]
1244name = "regex-syntax" 1244name = "regex-syntax"
1245version = "0.6.16" 1245version = "0.6.17"
1246source = "registry+https://github.com/rust-lang/crates.io-index" 1246source = "registry+https://github.com/rust-lang/crates.io-index"
1247checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" 1247checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
1248 1248
1249[[package]] 1249[[package]]
1250name = "relative-path" 1250name = "relative-path"
@@ -1342,9 +1342,9 @@ dependencies = [
1342 1342
1343[[package]] 1343[[package]]
1344name = "ryu" 1344name = "ryu"
1345version = "1.0.2" 1345version = "1.0.3"
1346source = "registry+https://github.com/rust-lang/crates.io-index" 1346source = "registry+https://github.com/rust-lang/crates.io-index"
1347checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" 1347checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
1348 1348
1349[[package]] 1349[[package]]
1350name = "salsa" 1350name = "salsa"
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index 3ca32185c..f0da173cc 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -56,21 +56,17 @@ fn list_(p: &mut Parser, flavor: Flavor) {
56 // fn f(#[attr1] pat: Type) {} 56 // fn f(#[attr1] pat: Type) {}
57 attributes::outer_attributes(p); 57 attributes::outer_attributes(p);
58 58
59 // test param_list_vararg
60 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
61 match flavor {
62 FnDef | FnPointer if p.eat(T![...]) => break,
63 _ => (),
64 }
65
66 if !p.at_ts(VALUE_PARAMETER_FIRST) { 59 if !p.at_ts(VALUE_PARAMETER_FIRST) {
67 p.error("expected value parameter"); 60 p.error("expected value parameter");
68 break; 61 break;
69 } 62 }
70 value_parameter(p, flavor); 63 let param = value_parameter(p, flavor);
71 if !p.at(ket) { 64 if !p.at(ket) {
72 p.expect(T![,]); 65 p.expect(T![,]);
73 } 66 }
67 if let Variadic(true) = param {
68 break;
69 }
74 } 70 }
75 71
76 p.expect(ket); 72 p.expect(ket);
@@ -79,14 +75,25 @@ fn list_(p: &mut Parser, flavor: Flavor) {
79 75
80const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST); 76const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
81 77
82fn value_parameter(p: &mut Parser, flavor: Flavor) { 78struct Variadic(bool);
79
80fn value_parameter(p: &mut Parser, flavor: Flavor) -> Variadic {
81 let mut res = Variadic(false);
83 let m = p.start(); 82 let m = p.start();
84 match flavor { 83 match flavor {
84 // test param_list_vararg
85 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
86 Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true),
87
85 // test fn_def_param 88 // test fn_def_param
86 // fn foo((x, y): (i32, i32)) {} 89 // fn foo((x, y): (i32, i32)) {}
87 Flavor::FnDef => { 90 Flavor::FnDef => {
88 patterns::pattern(p); 91 patterns::pattern(p);
89 types::ascription(p); 92 if variadic_param(p) {
93 res = Variadic(true)
94 } else {
95 types::ascription(p);
96 }
90 } 97 }
91 // test value_parameters_no_patterns 98 // test value_parameters_no_patterns
92 // type F = Box<Fn(i32, &i32, &i32, ())>; 99 // type F = Box<Fn(i32, &i32, &i32, ())>;
@@ -102,7 +109,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
102 Flavor::FnPointer => { 109 Flavor::FnPointer => {
103 if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { 110 if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
104 patterns::pattern_single(p); 111 patterns::pattern_single(p);
105 types::ascription(p); 112 if variadic_param(p) {
113 res = Variadic(true)
114 } else {
115 types::ascription(p);
116 }
106 } else { 117 } else {
107 types::type_(p); 118 types::type_(p);
108 } 119 }
@@ -119,6 +130,17 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
119 } 130 }
120 } 131 }
121 m.complete(p, PARAM); 132 m.complete(p, PARAM);
133 res
134}
135
136fn variadic_param(p: &mut Parser) -> bool {
137 if p.at(T![:]) && p.nth_at(1, T![...]) {
138 p.bump(T![:]);
139 p.bump(T![...]);
140 true
141 } else {
142 false
143 }
122} 144}
123 145
124// test self_param 146// test self_param
diff --git a/crates/ra_syntax/src/tests.rs b/crates/ra_syntax/src/tests.rs
index d331d541e..6a8cb6bb5 100644
--- a/crates/ra_syntax/src/tests.rs
+++ b/crates/ra_syntax/src/tests.rs
@@ -34,6 +34,7 @@ fn main() {
34 "##; 34 "##;
35 35
36 let parse = SourceFile::parse(code); 36 let parse = SourceFile::parse(code);
37 // eprintln!("{:#?}", parse.syntax_node());
37 assert!(parse.ok().is_ok()); 38 assert!(parse.ok().is_ok());
38} 39}
39 40
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.txt b/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.txt
index a0a8aea76..4c17f0db8 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.txt
@@ -81,7 +81,8 @@ SOURCE_FILE@[0; 113)
81 WHITESPACE@[97; 98) " " 81 WHITESPACE@[97; 98) " "
82 COMMA@[98; 99) "," 82 COMMA@[98; 99) ","
83 WHITESPACE@[99; 100) " " 83 WHITESPACE@[99; 100) " "
84 DOTDOTDOT@[100; 103) "..." 84 PARAM@[100; 103)
85 DOTDOTDOT@[100; 103) "..."
85 WHITESPACE@[103; 104) " " 86 WHITESPACE@[103; 104) " "
86 R_PAREN@[104; 105) ")" 87 R_PAREN@[104; 105) ")"
87 WHITESPACE@[105; 106) " " 88 WHITESPACE@[105; 106) " "
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.txt b/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.txt
index 836e8e55b..6c3b17868 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.txt
@@ -32,7 +32,8 @@ SOURCE_FILE@[0; 57)
32 IDENT@[38; 40) "i8" 32 IDENT@[38; 40) "i8"
33 COMMA@[40; 41) "," 33 COMMA@[40; 41) ","
34 WHITESPACE@[41; 42) " " 34 WHITESPACE@[41; 42) " "
35 DOTDOTDOT@[42; 45) "..." 35 PARAM@[42; 45)
36 DOTDOTDOT@[42; 45) "..."
36 R_PAREN@[45; 46) ")" 37 R_PAREN@[45; 46) ")"
37 WHITESPACE@[46; 47) " " 38 WHITESPACE@[46; 47) " "
38 RET_TYPE@[47; 53) 39 RET_TYPE@[47; 53)
diff --git a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt
index 719c99c17..254eafc36 100644
--- a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt
@@ -118,7 +118,8 @@ SOURCE_FILE@[0; 519)
118 IDENT@[108; 112) "attr" 118 IDENT@[108; 112) "attr"
119 R_BRACK@[112; 113) "]" 119 R_BRACK@[112; 113) "]"
120 WHITESPACE@[113; 114) " " 120 WHITESPACE@[113; 114) " "
121 DOTDOTDOT@[114; 117) "..." 121 PARAM@[114; 117)
122 DOTDOTDOT@[114; 117) "..."
122 R_PAREN@[117; 118) ")" 123 R_PAREN@[117; 118) ")"
123 WHITESPACE@[118; 119) " " 124 WHITESPACE@[118; 119) " "
124 RET_TYPE@[119; 125) 125 RET_TYPE@[119; 125)
diff --git a/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rs b/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rs
new file mode 100644
index 000000000..a16afbaf3
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rs
@@ -0,0 +1,5 @@
1extern "C" {
2 fn a(_: *mut u8, ...,);
3 fn b(_: *mut u8, _: ...);
4 fn c(_: *mut u8, #[cfg(never)] [w, t, f]: ...,);
5}
diff --git a/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.txt b/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.txt
new file mode 100644
index 000000000..186f03626
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.txt
@@ -0,0 +1,133 @@
1SOURCE_FILE@[0; 126)
2 EXTERN_BLOCK@[0; 125)
3 ABI@[0; 10)
4 EXTERN_KW@[0; 6) "extern"
5 WHITESPACE@[6; 7) " "
6 STRING@[7; 10) "\"C\""
7 WHITESPACE@[10; 11) " "
8 EXTERN_ITEM_LIST@[11; 125)
9 L_CURLY@[11; 12) "{"
10 WHITESPACE@[12; 17) "\n "
11 FN_DEF@[17; 40)
12 FN_KW@[17; 19) "fn"
13 WHITESPACE@[19; 20) " "
14 NAME@[20; 21)
15 IDENT@[20; 21) "a"
16 PARAM_LIST@[21; 39)
17 L_PAREN@[21; 22) "("
18 PARAM@[22; 32)
19 PLACEHOLDER_PAT@[22; 23)
20 UNDERSCORE@[22; 23) "_"
21 COLON@[23; 24) ":"
22 WHITESPACE@[24; 25) " "
23 POINTER_TYPE@[25; 32)
24 STAR@[25; 26) "*"
25 MUT_KW@[26; 29) "mut"
26 WHITESPACE@[29; 30) " "
27 PATH_TYPE@[30; 32)
28 PATH@[30; 32)
29 PATH_SEGMENT@[30; 32)
30 NAME_REF@[30; 32)
31 IDENT@[30; 32) "u8"
32 COMMA@[32; 33) ","
33 WHITESPACE@[33; 34) " "
34 PARAM@[34; 37)
35 DOTDOTDOT@[34; 37) "..."
36 COMMA@[37; 38) ","
37 R_PAREN@[38; 39) ")"
38 SEMI@[39; 40) ";"
39 WHITESPACE@[40; 45) "\n "
40 FN_DEF@[45; 70)
41 FN_KW@[45; 47) "fn"
42 WHITESPACE@[47; 48) " "
43 NAME@[48; 49)
44 IDENT@[48; 49) "b"
45 PARAM_LIST@[49; 69)
46 L_PAREN@[49; 50) "("
47 PARAM@[50; 60)
48 PLACEHOLDER_PAT@[50; 51)
49 UNDERSCORE@[50; 51) "_"
50 COLON@[51; 52) ":"
51 WHITESPACE@[52; 53) " "
52 POINTER_TYPE@[53; 60)
53 STAR@[53; 54) "*"
54 MUT_KW@[54; 57) "mut"
55 WHITESPACE@[57; 58) " "
56 PATH_TYPE@[58; 60)
57 PATH@[58; 60)
58 PATH_SEGMENT@[58; 60)
59 NAME_REF@[58; 60)
60 IDENT@[58; 60) "u8"
61 COMMA@[60; 61) ","
62 WHITESPACE@[61; 62) " "
63 PARAM@[62; 68)
64 PLACEHOLDER_PAT@[62; 63)
65 UNDERSCORE@[62; 63) "_"
66 COLON@[63; 64) ":"
67 WHITESPACE@[64; 65) " "
68 DOTDOTDOT@[65; 68) "..."
69 R_PAREN@[68; 69) ")"
70 SEMI@[69; 70) ";"
71 WHITESPACE@[70; 75) "\n "
72 FN_DEF@[75; 123)
73 FN_KW@[75; 77) "fn"
74 WHITESPACE@[77; 78) " "
75 NAME@[78; 79)
76 IDENT@[78; 79) "c"
77 PARAM_LIST@[79; 122)
78 L_PAREN@[79; 80) "("
79 PARAM@[80; 90)
80 PLACEHOLDER_PAT@[80; 81)
81 UNDERSCORE@[80; 81) "_"
82 COLON@[81; 82) ":"
83 WHITESPACE@[82; 83) " "
84 POINTER_TYPE@[83; 90)
85 STAR@[83; 84) "*"
86 MUT_KW@[84; 87) "mut"
87 WHITESPACE@[87; 88) " "
88 PATH_TYPE@[88; 90)
89 PATH@[88; 90)
90 PATH_SEGMENT@[88; 90)
91 NAME_REF@[88; 90)
92 IDENT@[88; 90) "u8"
93 COMMA@[90; 91) ","
94 WHITESPACE@[91; 92) " "
95 ATTR@[92; 105)
96 POUND@[92; 93) "#"
97 L_BRACK@[93; 94) "["
98 PATH@[94; 97)
99 PATH_SEGMENT@[94; 97)
100 NAME_REF@[94; 97)
101 IDENT@[94; 97) "cfg"
102 TOKEN_TREE@[97; 104)
103 L_PAREN@[97; 98) "("
104 IDENT@[98; 103) "never"
105 R_PAREN@[103; 104) ")"
106 R_BRACK@[104; 105) "]"
107 WHITESPACE@[105; 106) " "
108 PARAM@[106; 120)
109 SLICE_PAT@[106; 115)
110 L_BRACK@[106; 107) "["
111 BIND_PAT@[107; 108)
112 NAME@[107; 108)
113 IDENT@[107; 108) "w"
114 COMMA@[108; 109) ","
115 WHITESPACE@[109; 110) " "
116 BIND_PAT@[110; 111)
117 NAME@[110; 111)
118 IDENT@[110; 111) "t"
119 COMMA@[111; 112) ","
120 WHITESPACE@[112; 113) " "
121 BIND_PAT@[113; 114)
122 NAME@[113; 114)
123 IDENT@[113; 114) "f"
124 R_BRACK@[114; 115) "]"
125 COLON@[115; 116) ":"
126 WHITESPACE@[116; 117) " "
127 DOTDOTDOT@[117; 120) "..."
128 COMMA@[120; 121) ","
129 R_PAREN@[121; 122) ")"
130 SEMI@[122; 123) ";"
131 WHITESPACE@[123; 124) "\n"
132 R_CURLY@[124; 125) "}"
133 WHITESPACE@[125; 126) "\n"
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 53751aafb..321861b16 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -19,50 +19,48 @@ impl CargoTargetSpec {
19 pub(crate) fn runnable_args( 19 pub(crate) fn runnable_args(
20 spec: Option<CargoTargetSpec>, 20 spec: Option<CargoTargetSpec>,
21 kind: &RunnableKind, 21 kind: &RunnableKind,
22 ) -> Result<Vec<String>> { 22 ) -> Result<(Vec<String>, Vec<String>)> {
23 let mut res = Vec::new(); 23 let mut args = Vec::new();
24 let mut extra_args = Vec::new();
24 match kind { 25 match kind {
25 RunnableKind::Test { test_id } => { 26 RunnableKind::Test { test_id } => {
26 res.push("test".to_string()); 27 args.push("test".to_string());
27 if let Some(spec) = spec { 28 if let Some(spec) = spec {
28 spec.push_to(&mut res); 29 spec.push_to(&mut args);
29 } 30 }
30 res.push("--".to_string()); 31 extra_args.push(test_id.to_string());
31 res.push(test_id.to_string());
32 if let TestId::Path(_) = test_id { 32 if let TestId::Path(_) = test_id {
33 res.push("--exact".to_string()); 33 extra_args.push("--exact".to_string());
34 } 34 }
35 res.push("--nocapture".to_string()); 35 extra_args.push("--nocapture".to_string());
36 } 36 }
37 RunnableKind::TestMod { path } => { 37 RunnableKind::TestMod { path } => {
38 res.push("test".to_string()); 38 args.push("test".to_string());
39 if let Some(spec) = spec { 39 if let Some(spec) = spec {
40 spec.push_to(&mut res); 40 spec.push_to(&mut args);
41 } 41 }
42 res.push("--".to_string()); 42 extra_args.push(path.to_string());
43 res.push(path.to_string()); 43 extra_args.push("--nocapture".to_string());
44 res.push("--nocapture".to_string());
45 } 44 }
46 RunnableKind::Bench { test_id } => { 45 RunnableKind::Bench { test_id } => {
47 res.push("bench".to_string()); 46 args.push("bench".to_string());
48 if let Some(spec) = spec { 47 if let Some(spec) = spec {
49 spec.push_to(&mut res); 48 spec.push_to(&mut args);
50 } 49 }
51 res.push("--".to_string()); 50 extra_args.push(test_id.to_string());
52 res.push(test_id.to_string());
53 if let TestId::Path(_) = test_id { 51 if let TestId::Path(_) = test_id {
54 res.push("--exact".to_string()); 52 extra_args.push("--exact".to_string());
55 } 53 }
56 res.push("--nocapture".to_string()); 54 extra_args.push("--nocapture".to_string());
57 } 55 }
58 RunnableKind::Bin => { 56 RunnableKind::Bin => {
59 res.push("run".to_string()); 57 args.push("run".to_string());
60 if let Some(spec) = spec { 58 if let Some(spec) = spec {
61 spec.push_to(&mut res); 59 spec.push_to(&mut args);
62 } 60 }
63 } 61 }
64 } 62 }
65 Ok(res) 63 Ok((args, extra_args))
66 } 64 }
67 65
68 pub(crate) fn for_file( 66 pub(crate) fn for_file(
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 084e17b04..6b9a11a87 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -55,6 +55,9 @@ pub struct ServerConfig {
55 55
56 /// Cargo feature configurations. 56 /// Cargo feature configurations.
57 pub cargo_features: CargoFeatures, 57 pub cargo_features: CargoFeatures,
58
59 /// Enabled if the vscode_lldb extension is available.
60 pub vscode_lldb: bool,
58} 61}
59 62
60impl Default for ServerConfig { 63impl Default for ServerConfig {
@@ -76,6 +79,7 @@ impl Default for ServerConfig {
76 additional_out_dirs: FxHashMap::default(), 79 additional_out_dirs: FxHashMap::default(),
77 cargo_features: Default::default(), 80 cargo_features: Default::default(),
78 rustfmt_args: Vec::new(), 81 rustfmt_args: Vec::new(),
82 vscode_lldb: false,
79 } 83 }
80 } 84 }
81} 85}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 2b3b16d35..eb29e8322 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -189,6 +189,7 @@ pub fn main_loop(
189 all_targets: config.cargo_watch_all_targets, 189 all_targets: config.cargo_watch_all_targets,
190 }, 190 },
191 rustfmt_args: config.rustfmt_args, 191 rustfmt_args: config.rustfmt_args,
192 vscode_lldb: config.vscode_lldb,
192 } 193 }
193 }; 194 };
194 195
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 6482f3b77..df3622d61 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -381,6 +381,7 @@ pub fn handle_runnables(
381 label, 381 label,
382 bin: "cargo".to_string(), 382 bin: "cargo".to_string(),
383 args: check_args, 383 args: check_args,
384 extra_args: Vec::new(),
384 env: FxHashMap::default(), 385 env: FxHashMap::default(),
385 cwd: workspace_root.map(|root| root.to_string_lossy().to_string()), 386 cwd: workspace_root.map(|root| root.to_string_lossy().to_string()),
386 }); 387 });
@@ -794,18 +795,35 @@ pub fn handle_code_lens(
794 RunnableKind::Bin => "Run", 795 RunnableKind::Bin => "Run",
795 } 796 }
796 .to_string(); 797 .to_string();
797 let r = to_lsp_runnable(&world, file_id, runnable)?; 798 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
798 let lens = CodeLens { 799 let lens = CodeLens {
799 range: r.range, 800 range: r.range,
800 command: Some(Command { 801 command: Some(Command {
801 title, 802 title,
802 command: "rust-analyzer.runSingle".into(), 803 command: "rust-analyzer.runSingle".into(),
803 arguments: Some(vec![to_value(r).unwrap()]), 804 arguments: Some(vec![to_value(&r).unwrap()]),
804 }), 805 }),
805 data: None, 806 data: None,
806 }; 807 };
807
808 lenses.push(lens); 808 lenses.push(lens);
809
810 if world.options.vscode_lldb {
811 if r.args[0] == "run" {
812 r.args[0] = "build".into();
813 } else {
814 r.args.push("--no-run".into());
815 }
816 let debug_lens = CodeLens {
817 range: r.range,
818 command: Some(Command {
819 title: "Debug".into(),
820 command: "rust-analyzer.debugSingle".into(),
821 arguments: Some(vec![to_value(r).unwrap()]),
822 }),
823 data: None,
824 };
825 lenses.push(debug_lens);
826 }
809 } 827 }
810 828
811 // Handle impls 829 // Handle impls
@@ -952,7 +970,7 @@ fn to_lsp_runnable(
952 runnable: Runnable, 970 runnable: Runnable,
953) -> Result<req::Runnable> { 971) -> Result<req::Runnable> {
954 let spec = CargoTargetSpec::for_file(world, file_id)?; 972 let spec = CargoTargetSpec::for_file(world, file_id)?;
955 let args = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; 973 let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?;
956 let line_index = world.analysis().file_line_index(file_id)?; 974 let line_index = world.analysis().file_line_index(file_id)?;
957 let label = match &runnable.kind { 975 let label = match &runnable.kind {
958 RunnableKind::Test { test_id } => format!("test {}", test_id), 976 RunnableKind::Test { test_id } => format!("test {}", test_id),
@@ -965,6 +983,7 @@ fn to_lsp_runnable(
965 label, 983 label,
966 bin: "cargo".to_string(), 984 bin: "cargo".to_string(),
967 args, 985 args,
986 extra_args,
968 env: { 987 env: {
969 let mut m = FxHashMap::default(); 988 let mut m = FxHashMap::default();
970 m.insert("RUST_BACKTRACE".to_string(), "short".to_string()); 989 m.insert("RUST_BACKTRACE".to_string(), "short".to_string());
@@ -973,6 +992,7 @@ fn to_lsp_runnable(
973 cwd: world.workspace_root_for(file_id).map(|root| root.to_string_lossy().to_string()), 992 cwd: world.workspace_root_for(file_id).map(|root| root.to_string_lossy().to_string()),
974 }) 993 })
975} 994}
995
976fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> { 996fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> {
977 let line_index = world.analysis().file_line_index(file_id)?; 997 let line_index = world.analysis().file_line_index(file_id)?;
978 let res = world 998 let res = world
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs
index a3efe3b9f..156328df8 100644
--- a/crates/rust-analyzer/src/req.rs
+++ b/crates/rust-analyzer/src/req.rs
@@ -169,6 +169,7 @@ pub struct Runnable {
169 pub label: String, 169 pub label: String,
170 pub bin: String, 170 pub bin: String,
171 pub args: Vec<String>, 171 pub args: Vec<String>,
172 pub extra_args: Vec<String>,
172 pub env: FxHashMap<String, String>, 173 pub env: FxHashMap<String, String>,
173 pub cwd: Option<String>, 174 pub cwd: Option<String>,
174} 175}
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 058ce2af8..5743471bf 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -38,6 +38,7 @@ pub struct Options {
38 pub inlay_hints: InlayHintsOptions, 38 pub inlay_hints: InlayHintsOptions,
39 pub rustfmt_args: Vec<String>, 39 pub rustfmt_args: Vec<String>,
40 pub cargo_watch: CheckOptions, 40 pub cargo_watch: CheckOptions,
41 pub vscode_lldb: bool,
41} 42}
42 43
43/// `WorldState` is the primary mutable state of the language server 44/// `WorldState` is the primary mutable state of the language server
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs
index 970185dec..145429571 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/main.rs
@@ -75,7 +75,8 @@ fn foo() {
75 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None }, 75 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None },
76 json!([ 76 json!([
77 { 77 {
78 "args": [ "test", "--", "foo", "--nocapture" ], 78 "args": [ "test" ],
79 "extraArgs": [ "foo", "--nocapture" ],
79 "bin": "cargo", 80 "bin": "cargo",
80 "env": { "RUST_BACKTRACE": "short" }, 81 "env": { "RUST_BACKTRACE": "short" },
81 "cwd": null, 82 "cwd": null,
@@ -90,6 +91,7 @@ fn foo() {
90 "check", 91 "check",
91 "--all" 92 "--all"
92 ], 93 ],
94 "extraArgs": [],
93 "bin": "cargo", 95 "bin": "cargo",
94 "env": {}, 96 "env": {},
95 "cwd": null, 97 "cwd": null,
@@ -141,13 +143,11 @@ fn main() {}
141 143
142 server.wait_until_workspace_is_loaded(); 144 server.wait_until_workspace_is_loaded();
143 server.request::<Runnables>( 145 server.request::<Runnables>(
144 RunnablesParams { 146 RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None },
145 text_document: server.doc_id("foo/tests/spam.rs"),
146 position: None,
147 },
148 json!([ 147 json!([
149 { 148 {
150 "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--exact", "--nocapture" ], 149 "args": [ "test", "--package", "foo", "--test", "spam" ],
150 "extraArgs": [ "test_eggs", "--exact", "--nocapture" ],
151 "bin": "cargo", 151 "bin": "cargo",
152 "env": { "RUST_BACKTRACE": "short" }, 152 "env": { "RUST_BACKTRACE": "short" },
153 "label": "test test_eggs", 153 "label": "test test_eggs",
@@ -165,6 +165,7 @@ fn main() {}
165 "--test", 165 "--test",
166 "spam" 166 "spam"
167 ], 167 ],
168 "extraArgs": [],
168 "bin": "cargo", 169 "bin": "cargo",
169 "env": {}, 170 "env": {},
170 "cwd": server.path().join("foo"), 171 "cwd": server.path().join("foo"),
@@ -180,7 +181,7 @@ fn main() {}
180 } 181 }
181 } 182 }
182 } 183 }
183 ]) 184 ]),
184 ); 185 );
185} 186}
186 187
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index b2c830b30..d65454275 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -46,6 +46,7 @@ export async function createClient(config: Config, serverPath: string): Promise<
46 withSysroot: config.withSysroot, 46 withSysroot: config.withSysroot,
47 cargoFeatures: config.cargoFeatures, 47 cargoFeatures: config.cargoFeatures,
48 rustfmtArgs: config.rustfmtArgs, 48 rustfmtArgs: config.rustfmtArgs,
49 vscodeLldb: vscode.extensions.getExtension("vadimcn.vscode-lldb") != null,
49 }, 50 },
50 traceOutputChannel, 51 traceOutputChannel,
51 middleware: { 52 middleware: {
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts
index 06b513466..357155163 100644
--- a/editors/code/src/commands/runnables.ts
+++ b/editors/code/src/commands/runnables.ts
@@ -62,6 +62,26 @@ export function runSingle(ctx: Ctx): Cmd {
62 }; 62 };
63} 63}
64 64
65export function debugSingle(ctx: Ctx): Cmd {
66 return async (config: ra.Runnable) => {
67 const editor = ctx.activeRustEditor;
68 if (!editor) return;
69
70 const debugConfig = {
71 type: "lldb",
72 request: "launch",
73 name: config.label,
74 cargo: {
75 args: config.args,
76 },
77 args: config.extraArgs,
78 cwd: config.cwd
79 };
80
81 return vscode.debug.startDebugging(undefined, debugConfig);
82 };
83}
84
65class RunnableQuickPick implements vscode.QuickPickItem { 85class RunnableQuickPick implements vscode.QuickPickItem {
66 public label: string; 86 public label: string;
67 public description?: string | undefined; 87 public description?: string | undefined;
@@ -87,7 +107,7 @@ function createTask(spec: ra.Runnable): vscode.Task {
87 type: 'cargo', 107 type: 'cargo',
88 label: spec.label, 108 label: spec.label,
89 command: spec.bin, 109 command: spec.bin,
90 args: spec.args, 110 args: spec.extraArgs ? [...spec.args, '--', ...spec.extraArgs] : spec.args,
91 env: spec.env, 111 env: spec.env,
92 }; 112 };
93 113
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index ecf53cf77..e01c89cc7 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -83,6 +83,7 @@ export async function activate(context: vscode.ExtensionContext) {
83 83
84 // Internal commands which are invoked by the server. 84 // Internal commands which are invoked by the server.
85 ctx.registerCommand('runSingle', commands.runSingle); 85 ctx.registerCommand('runSingle', commands.runSingle);
86 ctx.registerCommand('debugSingle', commands.debugSingle);
86 ctx.registerCommand('showReferences', commands.showReferences); 87 ctx.registerCommand('showReferences', commands.showReferences);
87 ctx.registerCommand('applySourceChange', commands.applySourceChange); 88 ctx.registerCommand('applySourceChange', commands.applySourceChange);
88 ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); 89 ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange);
diff --git a/editors/code/src/rust-analyzer-api.ts b/editors/code/src/rust-analyzer-api.ts
index bd6e3ada0..e09a203c9 100644
--- a/editors/code/src/rust-analyzer-api.ts
+++ b/editors/code/src/rust-analyzer-api.ts
@@ -80,13 +80,12 @@ export interface Runnable {
80 label: string; 80 label: string;
81 bin: string; 81 bin: string;
82 args: Vec<string>; 82 args: Vec<string>;
83 extraArgs: Vec<string>;
83 env: FxHashMap<string, string>; 84 env: FxHashMap<string, string>;
84 cwd: Option<string>; 85 cwd: Option<string>;
85} 86}
86export const runnables = request<RunnablesParams, Vec<Runnable>>("runnables"); 87export const runnables = request<RunnablesParams, Vec<Runnable>>("runnables");
87 88
88
89
90export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint; 89export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint;
91 90
92export namespace InlayHint { 91export namespace InlayHint {