diff options
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]] |
60 | name = "backtrace-sys" | 60 | name = "backtrace-sys" |
61 | version = "0.1.33" | 61 | version = "0.1.34" |
62 | source = "registry+https://github.com/rust-lang/crates.io-index" | 62 | source = "registry+https://github.com/rust-lang/crates.io-index" |
63 | checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" | 63 | checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69" |
64 | dependencies = [ | 64 | dependencies = [ |
65 | "cc", | 65 | "cc", |
66 | "libc", | 66 | "libc", |
@@ -80,9 +80,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" | |||
80 | 80 | ||
81 | [[package]] | 81 | [[package]] |
82 | name = "bstr" | 82 | name = "bstr" |
83 | version = "0.2.11" | 83 | version = "0.2.12" |
84 | source = "registry+https://github.com/rust-lang/crates.io-index" | 84 | source = "registry+https://github.com/rust-lang/crates.io-index" |
85 | checksum = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" | 85 | checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" |
86 | dependencies = [ | 86 | dependencies = [ |
87 | "memchr", | 87 | "memchr", |
88 | ] | 88 | ] |
@@ -1230,9 +1230,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" | |||
1230 | 1230 | ||
1231 | [[package]] | 1231 | [[package]] |
1232 | name = "regex" | 1232 | name = "regex" |
1233 | version = "1.3.4" | 1233 | version = "1.3.5" |
1234 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1234 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1235 | checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" | 1235 | checksum = "8900ebc1363efa7ea1c399ccc32daed870b4002651e0bed86e72d501ebbe0048" |
1236 | dependencies = [ | 1236 | dependencies = [ |
1237 | "aho-corasick", | 1237 | "aho-corasick", |
1238 | "memchr", | 1238 | "memchr", |
@@ -1242,9 +1242,9 @@ dependencies = [ | |||
1242 | 1242 | ||
1243 | [[package]] | 1243 | [[package]] |
1244 | name = "regex-syntax" | 1244 | name = "regex-syntax" |
1245 | version = "0.6.16" | 1245 | version = "0.6.17" |
1246 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1247 | checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" | 1247 | checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" |
1248 | 1248 | ||
1249 | [[package]] | 1249 | [[package]] |
1250 | name = "relative-path" | 1250 | name = "relative-path" |
@@ -1342,9 +1342,9 @@ dependencies = [ | |||
1342 | 1342 | ||
1343 | [[package]] | 1343 | [[package]] |
1344 | name = "ryu" | 1344 | name = "ryu" |
1345 | version = "1.0.2" | 1345 | version = "1.0.3" |
1346 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1347 | checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" | 1347 | checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" |
1348 | 1348 | ||
1349 | [[package]] | 1349 | [[package]] |
1350 | name = "salsa" | 1350 | name = "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 | ||
80 | const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST); | 76 | const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST); |
81 | 77 | ||
82 | fn value_parameter(p: &mut Parser, flavor: Flavor) { | 78 | struct Variadic(bool); |
79 | |||
80 | fn 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 | |||
136 | fn 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 @@ | |||
1 | extern "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 @@ | |||
1 | SOURCE_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 | ||
60 | impl Default for ServerConfig { | 63 | impl 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 | |||
976 | fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> { | 996 | fn 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 | ||
65 | export 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 | |||
65 | class RunnableQuickPick implements vscode.QuickPickItem { | 85 | class 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 | } |
86 | export const runnables = request<RunnablesParams, Vec<Runnable>>("runnables"); | 87 | export const runnables = request<RunnablesParams, Vec<Runnable>>("runnables"); |
87 | 88 | ||
88 | |||
89 | |||
90 | export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint; | 89 | export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint; |
91 | 90 | ||
92 | export namespace InlayHint { | 91 | export namespace InlayHint { |