From bee5cdb359c283c4201b0357c320f9d610d79786 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 13 Mar 2020 12:09:14 +0100 Subject: Parse variadics correctly closes #3571 --- crates/ra_parser/src/grammar/params.rs | 44 +++++-- crates/ra_syntax/src/tests.rs | 1 + .../parser/inline/ok/0032_fn_pointer_type.txt | 3 +- .../parser/inline/ok/0123_param_list_vararg.txt | 3 +- .../test_data/parser/ok/0051_parameter_attrs.txt | 3 +- .../test_data/parser/ok/0063_variadic_fun.rs | 5 + .../test_data/parser/ok/0063_variadic_fun.txt | 133 +++++++++++++++++++++ 7 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rs create mode 100644 crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.txt (limited to 'crates') 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) { // fn f(#[attr1] pat: Type) {} attributes::outer_attributes(p); - // test param_list_vararg - // extern "C" { fn printf(format: *const i8, ...) -> i32; } - match flavor { - FnDef | FnPointer if p.eat(T![...]) => break, - _ => (), - } - if !p.at_ts(VALUE_PARAMETER_FIRST) { p.error("expected value parameter"); break; } - value_parameter(p, flavor); + let param = value_parameter(p, flavor); if !p.at(ket) { p.expect(T![,]); } + if let Variadic(true) = param { + break; + } } p.expect(ket); @@ -79,14 +75,25 @@ fn list_(p: &mut Parser, flavor: Flavor) { const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST); -fn value_parameter(p: &mut Parser, flavor: Flavor) { +struct Variadic(bool); + +fn value_parameter(p: &mut Parser, flavor: Flavor) -> Variadic { + let mut res = Variadic(false); let m = p.start(); match flavor { + // test param_list_vararg + // extern "C" { fn printf(format: *const i8, ...) -> i32; } + Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true), + // test fn_def_param // fn foo((x, y): (i32, i32)) {} Flavor::FnDef => { patterns::pattern(p); - types::ascription(p); + if variadic_param(p) { + res = Variadic(true) + } else { + types::ascription(p); + } } // test value_parameters_no_patterns // type F = Box; @@ -102,7 +109,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { Flavor::FnPointer => { if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { patterns::pattern_single(p); - types::ascription(p); + if variadic_param(p) { + res = Variadic(true) + } else { + types::ascription(p); + } } else { types::type_(p); } @@ -119,6 +130,17 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { } } m.complete(p, PARAM); + res +} + +fn variadic_param(p: &mut Parser) -> bool { + if p.at(T![:]) && p.nth_at(1, T![...]) { + p.bump(T![:]); + p.bump(T![...]); + true + } else { + false + } } // 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() { "##; let parse = SourceFile::parse(code); + // eprintln!("{:#?}", parse.syntax_node()); assert!(parse.ok().is_ok()); } 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) WHITESPACE@[97; 98) " " COMMA@[98; 99) "," WHITESPACE@[99; 100) " " - DOTDOTDOT@[100; 103) "..." + PARAM@[100; 103) + DOTDOTDOT@[100; 103) "..." WHITESPACE@[103; 104) " " R_PAREN@[104; 105) ")" 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) IDENT@[38; 40) "i8" COMMA@[40; 41) "," WHITESPACE@[41; 42) " " - DOTDOTDOT@[42; 45) "..." + PARAM@[42; 45) + DOTDOTDOT@[42; 45) "..." R_PAREN@[45; 46) ")" WHITESPACE@[46; 47) " " 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) IDENT@[108; 112) "attr" R_BRACK@[112; 113) "]" WHITESPACE@[113; 114) " " - DOTDOTDOT@[114; 117) "..." + PARAM@[114; 117) + DOTDOTDOT@[114; 117) "..." R_PAREN@[117; 118) ")" WHITESPACE@[118; 119) " " 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 @@ +extern "C" { + fn a(_: *mut u8, ...,); + fn b(_: *mut u8, _: ...); + fn c(_: *mut u8, #[cfg(never)] [w, t, f]: ...,); +} 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 @@ +SOURCE_FILE@[0; 126) + EXTERN_BLOCK@[0; 125) + ABI@[0; 10) + EXTERN_KW@[0; 6) "extern" + WHITESPACE@[6; 7) " " + STRING@[7; 10) "\"C\"" + WHITESPACE@[10; 11) " " + EXTERN_ITEM_LIST@[11; 125) + L_CURLY@[11; 12) "{" + WHITESPACE@[12; 17) "\n " + FN_DEF@[17; 40) + FN_KW@[17; 19) "fn" + WHITESPACE@[19; 20) " " + NAME@[20; 21) + IDENT@[20; 21) "a" + PARAM_LIST@[21; 39) + L_PAREN@[21; 22) "(" + PARAM@[22; 32) + PLACEHOLDER_PAT@[22; 23) + UNDERSCORE@[22; 23) "_" + COLON@[23; 24) ":" + WHITESPACE@[24; 25) " " + POINTER_TYPE@[25; 32) + STAR@[25; 26) "*" + MUT_KW@[26; 29) "mut" + WHITESPACE@[29; 30) " " + PATH_TYPE@[30; 32) + PATH@[30; 32) + PATH_SEGMENT@[30; 32) + NAME_REF@[30; 32) + IDENT@[30; 32) "u8" + COMMA@[32; 33) "," + WHITESPACE@[33; 34) " " + PARAM@[34; 37) + DOTDOTDOT@[34; 37) "..." + COMMA@[37; 38) "," + R_PAREN@[38; 39) ")" + SEMI@[39; 40) ";" + WHITESPACE@[40; 45) "\n " + FN_DEF@[45; 70) + FN_KW@[45; 47) "fn" + WHITESPACE@[47; 48) " " + NAME@[48; 49) + IDENT@[48; 49) "b" + PARAM_LIST@[49; 69) + L_PAREN@[49; 50) "(" + PARAM@[50; 60) + PLACEHOLDER_PAT@[50; 51) + UNDERSCORE@[50; 51) "_" + COLON@[51; 52) ":" + WHITESPACE@[52; 53) " " + POINTER_TYPE@[53; 60) + STAR@[53; 54) "*" + MUT_KW@[54; 57) "mut" + WHITESPACE@[57; 58) " " + PATH_TYPE@[58; 60) + PATH@[58; 60) + PATH_SEGMENT@[58; 60) + NAME_REF@[58; 60) + IDENT@[58; 60) "u8" + COMMA@[60; 61) "," + WHITESPACE@[61; 62) " " + PARAM@[62; 68) + PLACEHOLDER_PAT@[62; 63) + UNDERSCORE@[62; 63) "_" + COLON@[63; 64) ":" + WHITESPACE@[64; 65) " " + DOTDOTDOT@[65; 68) "..." + R_PAREN@[68; 69) ")" + SEMI@[69; 70) ";" + WHITESPACE@[70; 75) "\n " + FN_DEF@[75; 123) + FN_KW@[75; 77) "fn" + WHITESPACE@[77; 78) " " + NAME@[78; 79) + IDENT@[78; 79) "c" + PARAM_LIST@[79; 122) + L_PAREN@[79; 80) "(" + PARAM@[80; 90) + PLACEHOLDER_PAT@[80; 81) + UNDERSCORE@[80; 81) "_" + COLON@[81; 82) ":" + WHITESPACE@[82; 83) " " + POINTER_TYPE@[83; 90) + STAR@[83; 84) "*" + MUT_KW@[84; 87) "mut" + WHITESPACE@[87; 88) " " + PATH_TYPE@[88; 90) + PATH@[88; 90) + PATH_SEGMENT@[88; 90) + NAME_REF@[88; 90) + IDENT@[88; 90) "u8" + COMMA@[90; 91) "," + WHITESPACE@[91; 92) " " + ATTR@[92; 105) + POUND@[92; 93) "#" + L_BRACK@[93; 94) "[" + PATH@[94; 97) + PATH_SEGMENT@[94; 97) + NAME_REF@[94; 97) + IDENT@[94; 97) "cfg" + TOKEN_TREE@[97; 104) + L_PAREN@[97; 98) "(" + IDENT@[98; 103) "never" + R_PAREN@[103; 104) ")" + R_BRACK@[104; 105) "]" + WHITESPACE@[105; 106) " " + PARAM@[106; 120) + SLICE_PAT@[106; 115) + L_BRACK@[106; 107) "[" + BIND_PAT@[107; 108) + NAME@[107; 108) + IDENT@[107; 108) "w" + COMMA@[108; 109) "," + WHITESPACE@[109; 110) " " + BIND_PAT@[110; 111) + NAME@[110; 111) + IDENT@[110; 111) "t" + COMMA@[111; 112) "," + WHITESPACE@[112; 113) " " + BIND_PAT@[113; 114) + NAME@[113; 114) + IDENT@[113; 114) "f" + R_BRACK@[114; 115) "]" + COLON@[115; 116) ":" + WHITESPACE@[116; 117) " " + DOTDOTDOT@[117; 120) "..." + COMMA@[120; 121) "," + R_PAREN@[121; 122) ")" + SEMI@[122; 123) ";" + WHITESPACE@[123; 124) "\n" + R_CURLY@[124; 125) "}" + WHITESPACE@[125; 126) "\n" -- cgit v1.2.3