diff options
-rw-r--r-- | crates/ra_parser/src/grammar/type_params.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 67 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 43 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 15 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt | 13 |
5 files changed, 132 insertions, 8 deletions
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index 42763fc87..07d9b0792 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs | |||
@@ -165,7 +165,7 @@ fn where_predicate(p: &mut Parser) { | |||
165 | LIFETIME => { | 165 | LIFETIME => { |
166 | p.bump(); | 166 | p.bump(); |
167 | if p.at(COLON) { | 167 | if p.at(COLON) { |
168 | lifetime_bounds(p); | 168 | bounds(p); |
169 | } else { | 169 | } else { |
170 | p.error("expected colon"); | 170 | p.error("expected colon"); |
171 | } | 171 | } |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 4fddc00ea..fd7e63f84 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -799,3 +799,70 @@ fn test_doc_comment_preserves_indents() { | |||
799 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); | 799 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); |
800 | assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap()); | 800 | assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap()); |
801 | } | 801 | } |
802 | |||
803 | #[test] | ||
804 | fn test_where_predicates() { | ||
805 | fn assert_bound(text: &str, bound: Option<&TypeBound>) { | ||
806 | assert_eq!(text, bound.unwrap().syntax().text().to_string()); | ||
807 | } | ||
808 | |||
809 | let file = SourceFile::parse( | ||
810 | r#" | ||
811 | fn foo() | ||
812 | where | ||
813 | T: Clone + Copy + Debug + 'static, | ||
814 | 'a: 'b + 'c, | ||
815 | Iterator::Item: 'a + Debug, | ||
816 | Iterator::Item: Debug + 'a, | ||
817 | <T as Iterator>::Item: Debug + 'a, | ||
818 | for<'a> F: Fn(&'a str) | ||
819 | {} | ||
820 | "#, | ||
821 | ); | ||
822 | let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap(); | ||
823 | |||
824 | let mut predicates = where_clause.predicates(); | ||
825 | |||
826 | let pred = predicates.next().unwrap(); | ||
827 | let mut bounds = pred.type_bound_list().unwrap().bounds(); | ||
828 | |||
829 | assert_eq!("T", pred.type_ref().unwrap().syntax().text().to_string()); | ||
830 | assert_bound("Clone", bounds.next()); | ||
831 | assert_bound("Copy", bounds.next()); | ||
832 | assert_bound("Debug", bounds.next()); | ||
833 | assert_bound("'static", bounds.next()); | ||
834 | |||
835 | let pred = predicates.next().unwrap(); | ||
836 | let mut bounds = pred.type_bound_list().unwrap().bounds(); | ||
837 | |||
838 | assert_eq!("'a", pred.lifetime().unwrap().syntax().text().to_string()); | ||
839 | |||
840 | assert_bound("'b", bounds.next()); | ||
841 | assert_bound("'c", bounds.next()); | ||
842 | |||
843 | let pred = predicates.next().unwrap(); | ||
844 | let mut bounds = pred.type_bound_list().unwrap().bounds(); | ||
845 | |||
846 | assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string()); | ||
847 | assert_bound("'a", bounds.next()); | ||
848 | |||
849 | let pred = predicates.next().unwrap(); | ||
850 | let mut bounds = pred.type_bound_list().unwrap().bounds(); | ||
851 | |||
852 | assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string()); | ||
853 | assert_bound("Debug", bounds.next()); | ||
854 | assert_bound("'a", bounds.next()); | ||
855 | |||
856 | let pred = predicates.next().unwrap(); | ||
857 | let mut bounds = pred.type_bound_list().unwrap().bounds(); | ||
858 | |||
859 | assert_eq!("<T as Iterator>::Item", pred.type_ref().unwrap().syntax().text().to_string()); | ||
860 | assert_bound("Debug", bounds.next()); | ||
861 | assert_bound("'a", bounds.next()); | ||
862 | |||
863 | let pred = predicates.next().unwrap(); | ||
864 | let mut bounds = pred.type_bound_list().unwrap().bounds(); | ||
865 | |||
866 | assert_eq!("for<'a> F", pred.type_ref().unwrap().syntax().text().to_string()); | ||
867 | assert_bound("Fn(&'a str)", bounds.next()); | ||
868 | } | ||
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 9ea423b40..c51b4caa4 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -4810,7 +4810,48 @@ impl ToOwned for WhereClause { | |||
4810 | } | 4810 | } |
4811 | 4811 | ||
4812 | 4812 | ||
4813 | impl WhereClause {} | 4813 | impl WhereClause { |
4814 | pub fn predicates(&self) -> impl Iterator<Item = &WherePred> { | ||
4815 | super::children(self) | ||
4816 | } | ||
4817 | } | ||
4818 | |||
4819 | // WherePred | ||
4820 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
4821 | #[repr(transparent)] | ||
4822 | pub struct WherePred { | ||
4823 | pub(crate) syntax: SyntaxNode, | ||
4824 | } | ||
4825 | unsafe impl TransparentNewType for WherePred { | ||
4826 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
4827 | } | ||
4828 | |||
4829 | impl AstNode for WherePred { | ||
4830 | fn cast(syntax: &SyntaxNode) -> Option<&Self> { | ||
4831 | match syntax.kind() { | ||
4832 | WHERE_PRED => Some(WherePred::from_repr(syntax.into_repr())), | ||
4833 | _ => None, | ||
4834 | } | ||
4835 | } | ||
4836 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
4837 | } | ||
4838 | |||
4839 | impl ToOwned for WherePred { | ||
4840 | type Owned = TreeArc<WherePred>; | ||
4841 | fn to_owned(&self) -> TreeArc<WherePred> { TreeArc::cast(self.syntax.to_owned()) } | ||
4842 | } | ||
4843 | |||
4844 | |||
4845 | impl ast::TypeBoundsOwner for WherePred {} | ||
4846 | impl WherePred { | ||
4847 | pub fn type_ref(&self) -> Option<&TypeRef> { | ||
4848 | super::child_opt(self) | ||
4849 | } | ||
4850 | |||
4851 | pub fn lifetime(&self) -> Option<&Lifetime> { | ||
4852 | super::child_opt(self) | ||
4853 | } | ||
4854 | } | ||
4814 | 4855 | ||
4815 | // WhileExpr | 4856 | // WhileExpr |
4816 | #[derive(Debug, PartialEq, Eq, Hash)] | 4857 | #[derive(Debug, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 18730a894..1123c2e95 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -595,7 +595,20 @@ Grammar( | |||
595 | ["bounds", "TypeBound"], | 595 | ["bounds", "TypeBound"], |
596 | ] | 596 | ] |
597 | ), | 597 | ), |
598 | "WhereClause": (), | 598 | "WherePred": ( |
599 | options: [ | ||
600 | "TypeRef", | ||
601 | "Lifetime", | ||
602 | ], | ||
603 | traits: [ | ||
604 | "TypeBoundsOwner", | ||
605 | ], | ||
606 | ), | ||
607 | "WhereClause": ( | ||
608 | collections: [ | ||
609 | ["predicates", "WherePred"], | ||
610 | ], | ||
611 | ), | ||
599 | "ExprStmt": ( | 612 | "ExprStmt": ( |
600 | options: [ ["expr", "Expr"] ] | 613 | options: [ ["expr", "Expr"] ] |
601 | ), | 614 | ), |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt index e04b61eb3..77a62ab4d 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt | |||
@@ -15,11 +15,14 @@ SOURCE_FILE@[0; 116) | |||
15 | LIFETIME@[18; 20) "'a" | 15 | LIFETIME@[18; 20) "'a" |
16 | COLON@[20; 21) | 16 | COLON@[20; 21) |
17 | WHITESPACE@[21; 22) | 17 | WHITESPACE@[21; 22) |
18 | LIFETIME@[22; 24) "'b" | 18 | TYPE_BOUND_LIST@[22; 29) |
19 | WHITESPACE@[24; 25) | 19 | TYPE_BOUND@[22; 24) |
20 | PLUS@[25; 26) | 20 | LIFETIME@[22; 24) "'b" |
21 | WHITESPACE@[26; 27) | 21 | WHITESPACE@[24; 25) |
22 | LIFETIME@[27; 29) "'c" | 22 | PLUS@[25; 26) |
23 | WHITESPACE@[26; 27) | ||
24 | TYPE_BOUND@[27; 29) | ||
25 | LIFETIME@[27; 29) "'c" | ||
23 | COMMA@[29; 30) | 26 | COMMA@[29; 30) |
24 | WHITESPACE@[30; 34) | 27 | WHITESPACE@[30; 34) |
25 | WHERE_PRED@[34; 59) | 28 | WHERE_PRED@[34; 59) |