diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs index 94d904932ac5..e02dd7d43eec 100644 --- a/crates/ide-completion/src/context/tests.rs +++ b/crates/ide-completion/src/context/tests.rs @@ -810,3 +810,39 @@ fn foo() { expect![[r#"ty: bool, name: ?"#]], ); } + +#[test] +fn expected_type_some_incomplete_ast() { + check_expected_type_and_name( + r#" +fn foo(x: u32) { + foo(y.$0) +} +"#, + expect!["ty: u32, name: x"], + ); + check_expected_type_and_name( + r#" +fn foo(x: u32) { + foo(y.in$0) +} +"#, + expect!["ty: u32, name: x"], + ); + check_expected_type_and_name( + r#" +fn foo(x: u32) { + foo(y::$0) +} +"#, + expect!["ty: u32, name: x"], + ); + check_expected_type_and_name( + r#" +fn foo(x: u32) { + foo(crate::$0) +} +"#, + expect!["ty: u32, name: x"], + ); +} diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index 3f341c2ab846..abad1f07d683 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -597,6 +597,14 @@ fn field_expr( } (false, m) => Ok(m.complete(p, FIELD_EXPR)), }; + } else if !p.at(EOF) && p.current().is_keyword(p.current_edition()) { + // test_err field_expr_keyword_field + // fn foo() { + // x.ref; + // f(x.ref); + // f(2.ref); + // } + p.err_and_bump("expected field name or number"); } else { p.error("expected field name or number"); } diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs index ccf8b89be74a..5e3c94387248 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -827,6 +827,10 @@ mod err { #[test] fn empty_segment() { run_and_expect_errors("test_data/parser/inline/err/empty_segment.rs"); } #[test] + fn field_expr_keyword_field() { + run_and_expect_errors("test_data/parser/inline/err/field_expr_keyword_field.rs"); + } + #[test] fn fn_pointer_type_missing_fn() { run_and_expect_errors("test_data/parser/inline/err/fn_pointer_type_missing_fn.rs"); } diff --git a/crates/parser/test_data/parser/inline/err/field_expr_keyword_field.rast b/crates/parser/test_data/parser/inline/err/field_expr_keyword_field.rast new file mode 100644 index 000000000000..a55119d192e1 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/field_expr_keyword_field.rast @@ -0,0 +1,70 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + FIELD_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + DOT "." + ERROR + REF_KW "ref" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + CALL_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "f" + ARG_LIST + L_PAREN "(" + FIELD_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + DOT "." + ERROR + REF_KW "ref" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + CALL_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "f" + ARG_LIST + L_PAREN "(" + FIELD_EXPR + LITERAL + INT_NUMBER "2" + DOT "." + ERROR + REF_KW "ref" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" +error 17: expected field name or number +error 30: expected field name or number +error 44: expected field name or number diff --git a/crates/parser/test_data/parser/inline/err/field_expr_keyword_field.rs b/crates/parser/test_data/parser/inline/err/field_expr_keyword_field.rs new file mode 100644 index 000000000000..1064c03e2e54 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/field_expr_keyword_field.rs @@ -0,0 +1,5 @@ +fn foo() { + x.ref; + f(x.ref); + f(2.ref); +}