aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorVille Penttinen <[email protected]>2019-03-24 17:45:11 +0000
committerVille Penttinen <[email protected]>2019-03-31 11:20:56 +0100
commit3f62ab8f510fdac1eeab515c515c437d6dd141e6 (patch)
tree91bb5a70b999474e4d8212245fe265e71c3afde4 /crates
parent4666138c910a655deb0e8129b0a1dc5974b49bdf (diff)
Add WherePred to allow predicate access in WhereClause
This also unifies parsing of WHERE_PRED bounds, now Lifetime bounds will also be parsed using TYPE_BOUND_LIST
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_parser/src/grammar/type_params.rs2
-rw-r--r--crates/ra_syntax/src/ast.rs67
-rw-r--r--crates/ra_syntax/src/ast/generated.rs43
-rw-r--r--crates/ra_syntax/src/grammar.ron15
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt13
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]
804fn 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#"
811fn foo()
812where
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
4813impl WhereClause {} 4813impl 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)]
4822pub struct WherePred {
4823 pub(crate) syntax: SyntaxNode,
4824}
4825unsafe impl TransparentNewType for WherePred {
4826 type Repr = rowan::SyntaxNode<RaTypes>;
4827}
4828
4829impl 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
4839impl ToOwned for WherePred {
4840 type Owned = TreeArc<WherePred>;
4841 fn to_owned(&self) -> TreeArc<WherePred> { TreeArc::cast(self.syntax.to_owned()) }
4842}
4843
4844
4845impl ast::TypeBoundsOwner for WherePred {}
4846impl 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)