Skip to content

Commit 5e5eb6a

Browse files
committed
Align grammar for record patterns and literals
The grammar now looks like this [name_ref :] pat
1 parent 6b49e77 commit 5e5eb6a

File tree

18 files changed

+145
-90
lines changed

18 files changed

+145
-90
lines changed

crates/ra_assists/src/handlers/reorder_fields.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
use std::collections::HashMap;
22

3-
use itertools::Itertools;
4-
53
use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct};
4+
use itertools::Itertools;
65
use ra_ide_db::RootDatabase;
76
use ra_syntax::{
8-
algo, ast,
9-
ast::{Name, Path, RecordLit, RecordPat},
10-
AstNode, SyntaxKind, SyntaxNode,
7+
algo,
8+
ast::{self, Path, RecordLit, RecordPat},
9+
match_ast, AstNode, SyntaxKind,
10+
SyntaxKind::*,
11+
SyntaxNode,
1112
};
1213

1314
use crate::{
1415
assist_ctx::{Assist, AssistCtx},
1516
AssistId,
1617
};
17-
use ra_syntax::ast::{Expr, NameRef};
1818

1919
// Assist: reorder_fields
2020
//
@@ -59,7 +59,6 @@ fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> {
5959
}
6060

6161
fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
62-
use SyntaxKind::*;
6362
match node.kind() {
6463
RECORD_LIT => vec![RECORD_FIELD],
6564
RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT],
@@ -68,19 +67,14 @@ fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
6867
}
6968

7069
fn get_field_name(node: &SyntaxNode) -> String {
71-
use SyntaxKind::*;
72-
match node.kind() {
73-
RECORD_FIELD => {
74-
if let Some(name) = node.children().find_map(NameRef::cast) {
75-
return name.to_string();
76-
}
77-
node.children().find_map(Expr::cast).map(|expr| expr.to_string()).unwrap_or_default()
78-
}
79-
BIND_PAT | RECORD_FIELD_PAT => {
80-
node.children().find_map(Name::cast).map(|n| n.to_string()).unwrap_or_default()
70+
let res = match_ast! {
71+
match node {
72+
ast::RecordField(field) => { field.field_name().map(|it| it.to_string()) },
73+
ast::RecordFieldPat(field) => { field.field_name().map(|it| it.to_string()) },
74+
_ => None,
8175
}
82-
_ => String::new(),
83-
}
76+
};
77+
res.unwrap_or_default()
8478
}
8579

8680
fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> {

crates/ra_hir_def/src/body/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ impl ExprCollector<'_> {
637637
let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
638638
let ast_pat = f.pat()?;
639639
let pat = self.collect_pat(ast_pat);
640-
let name = f.name()?.as_name();
640+
let name = f.field_name()?.as_name();
641641
Some(RecordFieldPat { name, pat })
642642
});
643643
fields.extend(iter);

crates/ra_hir_expand/src/name.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ impl AsName for ast::Name {
8383
}
8484
}
8585

86+
impl AsName for ast::NameOrNameRef {
87+
fn as_name(&self) -> Name {
88+
match self {
89+
ast::NameOrNameRef::Name(it) => it.as_name(),
90+
ast::NameOrNameRef::NameRef(it) => it.as_name(),
91+
}
92+
}
93+
}
94+
8695
impl AsName for tt::Ident {
8796
fn as_name(&self) -> Name {
8897
Name::resolve(&self.text)

crates/ra_hir_ty/src/tests/patterns.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use super::{infer, infer_with_mismatches};
21
use insta::assert_snapshot;
32
use test_utils::covers;
43

4+
use super::{infer, infer_with_mismatches};
5+
56
#[test]
67
fn infer_pattern() {
78
assert_snapshot!(

crates/ra_ide/src/completion/complete_pattern.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
77
if !ctx.is_pat_binding_or_const {
88
return;
99
}
10+
if ctx.record_pat_syntax.is_some() {
11+
return;
12+
}
13+
1014
// FIXME: ideally, we should look at the type we are matching against and
1115
// suggest variants + auto-imports
1216
ctx.scope().process_all_names(&mut |name, res| {

crates/ra_ide/src/completion/complete_record.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use crate::completion::{CompletionContext, Completions};
33

44
pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
5-
let missing_fields = match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) {
5+
let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
66
(None, None) => return None,
77
(Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"),
88
(Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat),

crates/ra_ide/src/completion/complete_unqualified_path.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33
use crate::completion::{CompletionContext, Completions};
44

55
pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
6-
if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const && !ctx.record_lit_syntax.is_some()) {
6+
if !ctx.is_trivial_path {
7+
return;
8+
}
9+
10+
if ctx.is_pat_binding_or_const
11+
|| ctx.record_lit_syntax.is_some()
12+
|| ctx.record_pat_syntax.is_some()
13+
{
714
return;
815
}
916

crates/ra_ide/src/completion/completion_context.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub(crate) struct CompletionContext<'a> {
3030
pub(super) function_syntax: Option<ast::FnDef>,
3131
pub(super) use_item_syntax: Option<ast::UseItem>,
3232
pub(super) record_lit_syntax: Option<ast::RecordLit>,
33-
pub(super) record_lit_pat: Option<ast::RecordPat>,
33+
pub(super) record_pat_syntax: Option<ast::RecordPat>,
3434
pub(super) impl_def: Option<ast::ImplDef>,
3535
pub(super) is_param: bool,
3636
/// If a name-binding or reference to a const in a pattern.
@@ -93,7 +93,7 @@ impl<'a> CompletionContext<'a> {
9393
function_syntax: None,
9494
use_item_syntax: None,
9595
record_lit_syntax: None,
96-
record_lit_pat: None,
96+
record_pat_syntax: None,
9797
impl_def: None,
9898
is_param: false,
9999
is_pat_binding_or_const: false,
@@ -182,6 +182,11 @@ impl<'a> CompletionContext<'a> {
182182
self.is_param = true;
183183
return;
184184
}
185+
// FIXME: remove this (V) duplication and make the check more precise
186+
if name_ref.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
187+
self.record_pat_syntax =
188+
self.sema.find_node_at_offset_with_macros(&original_file, offset);
189+
}
185190
self.classify_name_ref(original_file, name_ref, offset);
186191
}
187192

@@ -211,8 +216,9 @@ impl<'a> CompletionContext<'a> {
211216
self.is_param = true;
212217
return;
213218
}
219+
// FIXME: remove this (^) duplication and make the check more precise
214220
if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
215-
self.record_lit_pat =
221+
self.record_pat_syntax =
216222
self.sema.find_node_at_offset_with_macros(&original_file, offset);
217223
}
218224
}

crates/ra_parser/src/grammar/patterns.rs

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,30 @@ fn record_field_pat_list(p: &mut Parser) {
192192
match p.current() {
193193
// A trailing `..` is *not* treated as a DOT_DOT_PAT.
194194
T![.] if p.at(T![..]) => p.bump(T![..]),
195-
196-
IDENT | INT_NUMBER if p.nth(1) == T![:] => record_field_pat(p),
197195
T!['{'] => error_block(p, "expected ident"),
198-
T![box] => {
199-
box_pat(p);
200-
}
201-
_ => {
202-
bind_pat(p, false);
196+
197+
c => {
198+
let m = p.start();
199+
match c {
200+
// test record_field_pat
201+
// fn foo() {
202+
// let S { 0: 1 } = ();
203+
// let S { x: 1 } = ();
204+
// }
205+
IDENT | INT_NUMBER if p.nth(1) == T![:] => {
206+
name_ref_or_index(p);
207+
p.bump(T![:]);
208+
pattern(p);
209+
}
210+
T![box] => {
211+
// FIXME: not all box patterns should be allowed
212+
box_pat(p);
213+
}
214+
_ => {
215+
bind_pat(p, false);
216+
}
217+
}
218+
m.complete(p, RECORD_FIELD_PAT);
203219
}
204220
}
205221
if !p.at(T!['}']) {
@@ -210,26 +226,6 @@ fn record_field_pat_list(p: &mut Parser) {
210226
m.complete(p, RECORD_FIELD_PAT_LIST);
211227
}
212228

213-
// test record_field_pat
214-
// fn foo() {
215-
// let S { 0: 1 } = ();
216-
// let S { x: 1 } = ();
217-
// }
218-
fn record_field_pat(p: &mut Parser) {
219-
assert!(p.at(IDENT) || p.at(INT_NUMBER));
220-
assert!(p.nth(1) == T![:]);
221-
222-
let m = p.start();
223-
224-
if !p.eat(INT_NUMBER) {
225-
name(p)
226-
}
227-
228-
p.bump_any();
229-
pattern(p);
230-
m.complete(p, RECORD_FIELD_PAT);
231-
}
232-
233229
// test placeholder_pat
234230
// fn main() { let _ = (); }
235231
fn placeholder_pat(p: &mut Parser) -> CompletedMarker {

crates/ra_syntax/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::{
1818
pub use self::{
1919
expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
2020
extensions::{
21-
AttrKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind,
22-
TypeBoundKind, VisibilityKind,
21+
AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
22+
StructKind, TypeBoundKind, VisibilityKind,
2323
},
2424
generated::{nodes::*, tokens::*},
2525
tokens::*,

0 commit comments

Comments
 (0)