aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-16 18:35:27 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:25 +0000
commitab5deb78117693d776723bc0144e7b34e6f782d1 (patch)
tree06a1de31ffc6d9d75315829cd7aebce43b44e009
parent9c2d83a4c809b0b11ca389bb454e197859e5116c (diff)
Create struct patterns up to the hir level
-rw-r--r--crates/ra_hir/src/expr.rs39
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_syntax/src/ast.rs69
-rw-r--r--crates/ra_syntax/src/ast/generated.rs13
-rw-r--r--crates/ra_syntax/src/grammar.ron5
5 files changed, 116 insertions, 12 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 8f7e75309..c6d442ec4 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -329,13 +329,23 @@ impl Expr {
329pub struct PatId(RawId); 329pub struct PatId(RawId);
330impl_arena_id!(PatId); 330impl_arena_id!(PatId);
331 331
332#[derive(Debug, Clone, Eq, PartialEq)]
333pub struct FieldPat {
334 name: Name,
335 pat: Option<PatId>,
336}
337
332/// Close relative to rustc's hir::PatKind 338/// Close relative to rustc's hir::PatKind
333#[derive(Debug, Clone, Eq, PartialEq)] 339#[derive(Debug, Clone, Eq, PartialEq)]
334pub enum Pat { 340pub enum Pat {
335 Missing, // do we need this? 341 Missing, // do we need this?
336 Wild, 342 Wild,
337 Tuple(Vec<PatId>), 343 Tuple(Vec<PatId>),
338 Struct, // TODO 344 Struct {
345 path: Option<Path>,
346 args: Vec<FieldPat>,
347 // TODO: 'ellipsis' option
348 },
339 Range { 349 Range {
340 start: ExprId, 350 start: ExprId,
341 end: ExprId, 351 end: ExprId,
@@ -802,11 +812,30 @@ impl ExprCollector {
802 Pat::Tuple(args) 812 Pat::Tuple(args)
803 } 813 }
804 ast::PatKind::PlaceholderPat(_) => Pat::Wild, 814 ast::PatKind::PlaceholderPat(_) => Pat::Wild,
815 ast::PatKind::StructPat(p) => {
816 let path = p.path().and_then(Path::from_ast);
817
818 if let Some(field_list) = p.field_pat_list() {
819 let fields = field_list
820 .field_pats()
821 .into_iter()
822 .map(|f| FieldPat {
823 name: Name::new(f.ident),
824 pat: f.pat.as_ref().map(|p| self.collect_pat(p)),
825 })
826 .collect();
827
828 Pat::Struct {
829 path: path,
830 args: fields,
831 }
832 } else {
833 Pat::Missing
834 }
835 }
836
805 // TODO: implement 837 // TODO: implement
806 ast::PatKind::FieldPatList(_) 838 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
807 | ast::PatKind::SlicePat(_)
808 | ast::PatKind::StructPat(_)
809 | ast::PatKind::RangePat(_) => Pat::Missing,
810 }; 839 };
811 let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); 840 let syntax_ptr = LocalSyntaxPtr::new(pat.syntax());
812 self.alloc_pat(pattern, syntax_ptr) 841 self.alloc_pat(pattern, syntax_ptr)
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index cdecbd064..3e1a4f02e 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -877,6 +877,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
877 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty { 877 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
878 let body = Arc::clone(&self.body); // avoid borrow checker problem 878 let body = Arc::clone(&self.body); // avoid borrow checker problem
879 879
880 // FIXME: we can do some inference even if the expected ty isnt already
881 // of the right form
880 let ty = match (&body[pat], &expected.ty) { 882 let ty = match (&body[pat], &expected.ty) {
881 (Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args)) 883 (Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
882 if args.len() == tuple_args.len() => 884 if args.len() == tuple_args.len() =>
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 000cfb981..3df23b16f 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -664,6 +664,75 @@ impl LiteralExpr {
664 } 664 }
665} 665}
666 666
667// STRUCT_PAT@[20; 42)
668// PATH@[20; 26)
669// PATH_SEGMENT@[20; 26)
670// NAME_REF@[20; 26)
671// IDENT@[20; 26) "Strukt"
672// WHITESPACE@[26; 27)
673// FIELD_PAT_LIST@[27; 42)
674// L_CURLY@[27; 28)
675// WHITESPACE@[28; 29)
676// IDENT@[29; 30) "x"
677// COLON@[30; 31)
678// WHITESPACE@[31; 32)
679// BIND_PAT@[32; 33)
680// NAME@[32; 33)
681// IDENT@[32; 33) "x"
682// COMMA@[33; 34)
683// WHITESPACE@[34; 35)
684// BIND_PAT@[35; 36)
685// NAME@[35; 36)
686// IDENT@[35; 36) "y"
687// COMMA@[36; 37)
688// WHITESPACE@[37; 38)
689// DOTDOT@[38; 40)
690// WHITESPACE@[40; 41)
691// R_CURLY@[41; 42)
692
693#[derive(Clone, Debug, PartialEq, Eq, Hash)]
694pub struct FieldPat {
695 pub ident: SmolStr,
696 pub pat: Option<TreeArc<Pat>>,
697}
698
699impl FieldPatList {
700 // TODO: try returning an iterator?
701 // FIXME: shouldnt the parser do this? :o
702 pub fn field_pats(&self) -> Vec<FieldPat> {
703 let mut child_iter = self.syntax().children();
704 let mut pats = Vec::new();
705
706 while let Some(node) = child_iter.next() {
707 if node.kind() != IDENT {
708 continue;
709 }
710
711 let ident = node.leaf_text().unwrap().clone();
712 let mut pat = None;
713
714 // get pat
715 while let Some(node) = child_iter.next() {
716 if node.kind() == COMMA {
717 break;
718 }
719
720 if let Some(p) = Pat::cast(node) {
721 pat = Some(p.to_owned());
722 }
723 }
724
725 let field_pat = FieldPat {
726 ident: ident,
727 pat: pat,
728 };
729 pats.push(field_pat);
730 }
731
732 pats
733 }
734}
735
667#[test] 736#[test]
668fn test_doc_comment_of_items() { 737fn test_doc_comment_of_items() {
669 let file = SourceFile::parse( 738 let file = SourceFile::parse(
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 2fd146bf1..251d53bdf 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -2156,7 +2156,6 @@ pub enum PatKind<'a> {
2156 PlaceholderPat(&'a PlaceholderPat), 2156 PlaceholderPat(&'a PlaceholderPat),
2157 PathPat(&'a PathPat), 2157 PathPat(&'a PathPat),
2158 StructPat(&'a StructPat), 2158 StructPat(&'a StructPat),
2159 FieldPatList(&'a FieldPatList),
2160 TupleStructPat(&'a TupleStructPat), 2159 TupleStructPat(&'a TupleStructPat),
2161 TuplePat(&'a TuplePat), 2160 TuplePat(&'a TuplePat),
2162 SlicePat(&'a SlicePat), 2161 SlicePat(&'a SlicePat),
@@ -2171,7 +2170,6 @@ impl AstNode for Pat {
2171 | PLACEHOLDER_PAT 2170 | PLACEHOLDER_PAT
2172 | PATH_PAT 2171 | PATH_PAT
2173 | STRUCT_PAT 2172 | STRUCT_PAT
2174 | FIELD_PAT_LIST
2175 | TUPLE_STRUCT_PAT 2173 | TUPLE_STRUCT_PAT
2176 | TUPLE_PAT 2174 | TUPLE_PAT
2177 | SLICE_PAT 2175 | SLICE_PAT
@@ -2191,7 +2189,6 @@ impl Pat {
2191 PLACEHOLDER_PAT => PatKind::PlaceholderPat(PlaceholderPat::cast(&self.syntax).unwrap()), 2189 PLACEHOLDER_PAT => PatKind::PlaceholderPat(PlaceholderPat::cast(&self.syntax).unwrap()),
2192 PATH_PAT => PatKind::PathPat(PathPat::cast(&self.syntax).unwrap()), 2190 PATH_PAT => PatKind::PathPat(PathPat::cast(&self.syntax).unwrap()),
2193 STRUCT_PAT => PatKind::StructPat(StructPat::cast(&self.syntax).unwrap()), 2191 STRUCT_PAT => PatKind::StructPat(StructPat::cast(&self.syntax).unwrap()),
2194 FIELD_PAT_LIST => PatKind::FieldPatList(FieldPatList::cast(&self.syntax).unwrap()),
2195 TUPLE_STRUCT_PAT => PatKind::TupleStructPat(TupleStructPat::cast(&self.syntax).unwrap()), 2192 TUPLE_STRUCT_PAT => PatKind::TupleStructPat(TupleStructPat::cast(&self.syntax).unwrap()),
2196 TUPLE_PAT => PatKind::TuplePat(TuplePat::cast(&self.syntax).unwrap()), 2193 TUPLE_PAT => PatKind::TuplePat(TuplePat::cast(&self.syntax).unwrap()),
2197 SLICE_PAT => PatKind::SlicePat(SlicePat::cast(&self.syntax).unwrap()), 2194 SLICE_PAT => PatKind::SlicePat(SlicePat::cast(&self.syntax).unwrap()),
@@ -3066,7 +3063,15 @@ impl AstNode for StructPat {
3066} 3063}
3067 3064
3068 3065
3069impl StructPat {} 3066impl StructPat {
3067 pub fn field_pat_list(&self) -> Option<&FieldPatList> {
3068 super::child_opt(self)
3069 }
3070
3071 pub fn path(&self) -> Option<&Path> {
3072 super::child_opt(self)
3073 }
3074}
3070 3075
3071// TokenTree 3076// TokenTree
3072#[derive(Debug, PartialEq, Eq, Hash)] 3077#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index b524c8aaf..33080f664 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -490,8 +490,8 @@ Grammar(
490 "RefPat": ( options: [ "Pat" ]), 490 "RefPat": ( options: [ "Pat" ]),
491 "BindPat": ( traits: ["NameOwner"] ), 491 "BindPat": ( traits: ["NameOwner"] ),
492 "PlaceholderPat": (), 492 "PlaceholderPat": (),
493 "PathPat": ( options: ["Path"] ), 493 "PathPat": ( options: [ "Path" ] ),
494 "StructPat": (), 494 "StructPat": ( options: ["FieldPatList", "Path"] ),
495 "FieldPatList": (), 495 "FieldPatList": (),
496 "TupleStructPat": ( 496 "TupleStructPat": (
497 options: ["Path"], 497 options: ["Path"],
@@ -508,7 +508,6 @@ Grammar(
508 "PlaceholderPat", 508 "PlaceholderPat",
509 "PathPat", 509 "PathPat",
510 "StructPat", 510 "StructPat",
511 "FieldPatList",
512 "TupleStructPat", 511 "TupleStructPat",
513 "TuplePat", 512 "TuplePat",
514 "SlicePat", 513 "SlicePat",