diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-16 18:35:27 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-19 12:37:25 +0000 |
commit | ab5deb78117693d776723bc0144e7b34e6f782d1 (patch) | |
tree | 06a1de31ffc6d9d75315829cd7aebce43b44e009 /crates | |
parent | 9c2d83a4c809b0b11ca389bb454e197859e5116c (diff) |
Create struct patterns up to the hir level
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 39 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 69 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 5 |
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 { | |||
329 | pub struct PatId(RawId); | 329 | pub struct PatId(RawId); |
330 | impl_arena_id!(PatId); | 330 | impl_arena_id!(PatId); |
331 | 331 | ||
332 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
333 | pub 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)] |
334 | pub enum Pat { | 340 | pub 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)] | ||
694 | pub struct FieldPat { | ||
695 | pub ident: SmolStr, | ||
696 | pub pat: Option<TreeArc<Pat>>, | ||
697 | } | ||
698 | |||
699 | impl 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] |
668 | fn test_doc_comment_of_items() { | 737 | fn 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 | ||
3069 | impl StructPat {} | 3066 | impl 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", |