]> git.lizzy.rs Git - rust.git/commitdiff
Add WherePred to allow predicate access in WhereClause
authorVille Penttinen <villem.penttinen@gmail.com>
Sun, 24 Mar 2019 17:45:11 +0000 (19:45 +0200)
committerVille Penttinen <villem.penttinen@gmail.com>
Sun, 31 Mar 2019 10:20:56 +0000 (13:20 +0300)
This also unifies parsing of WHERE_PRED bounds, now Lifetime bounds will also be
parsed using TYPE_BOUND_LIST

crates/ra_parser/src/grammar/type_params.rs
crates/ra_syntax/src/ast.rs
crates/ra_syntax/src/ast/generated.rs
crates/ra_syntax/src/grammar.ron
crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt

index 42763fc87c1693ba200e0b393c5730531b5e6cd4..07d9b079217efec146630a17552fcf9274569b44 100644 (file)
@@ -165,7 +165,7 @@ fn where_predicate(p: &mut Parser) {
         LIFETIME => {
             p.bump();
             if p.at(COLON) {
-                lifetime_bounds(p);
+                bounds(p);
             } else {
                 p.error("expected colon");
             }
index 4fddc00ea5f3682e904c81f17f317530a9c16eb9..fd7e63f849f2aeba7ae28ba4d7a1e660cb3043dd 100644 (file)
@@ -799,3 +799,70 @@ mod foo {}
     let module = file.syntax().descendants().find_map(Module::cast).unwrap();
     assert_eq!("doc1\n```\nfn foo() {\n    // ...\n}\n```", module.doc_comment_text().unwrap());
 }
+
+#[test]
+fn test_where_predicates() {
+    fn assert_bound(text: &str, bound: Option<&TypeBound>) {
+        assert_eq!(text, bound.unwrap().syntax().text().to_string());
+    }
+
+    let file = SourceFile::parse(
+        r#"
+fn foo()
+where
+   T: Clone + Copy + Debug + 'static,
+   'a: 'b + 'c,
+   Iterator::Item: 'a + Debug,
+   Iterator::Item: Debug + 'a,
+   <T as Iterator>::Item: Debug + 'a,
+   for<'a> F: Fn(&'a str)
+{}
+        "#,
+    );
+    let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap();
+
+    let mut predicates = where_clause.predicates();
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("T", pred.type_ref().unwrap().syntax().text().to_string());
+    assert_bound("Clone", bounds.next());
+    assert_bound("Copy", bounds.next());
+    assert_bound("Debug", bounds.next());
+    assert_bound("'static", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("'a", pred.lifetime().unwrap().syntax().text().to_string());
+
+    assert_bound("'b", bounds.next());
+    assert_bound("'c", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
+    assert_bound("'a", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
+    assert_bound("Debug", bounds.next());
+    assert_bound("'a", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("<T as Iterator>::Item", pred.type_ref().unwrap().syntax().text().to_string());
+    assert_bound("Debug", bounds.next());
+    assert_bound("'a", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("for<'a> F", pred.type_ref().unwrap().syntax().text().to_string());
+    assert_bound("Fn(&'a str)", bounds.next());
+}
index 9ea423b40e251da45385effce42b88ff680a0f44..c51b4caa4f19407deb919244c4f67470e00517c5 100644 (file)
@@ -4810,7 +4810,48 @@ fn to_owned(&self) -> TreeArc<WhereClause> { TreeArc::cast(self.syntax.to_owned(
 }
 
 
-impl WhereClause {}
+impl WhereClause {
+    pub fn predicates(&self) -> impl Iterator<Item = &WherePred> {
+        super::children(self)
+    }
+}
+
+// WherePred
+#[derive(Debug, PartialEq, Eq, Hash)]
+#[repr(transparent)]
+pub struct WherePred {
+    pub(crate) syntax: SyntaxNode,
+}
+unsafe impl TransparentNewType for WherePred {
+    type Repr = rowan::SyntaxNode<RaTypes>;
+}
+
+impl AstNode for WherePred {
+    fn cast(syntax: &SyntaxNode) -> Option<&Self> {
+        match syntax.kind() {
+            WHERE_PRED => Some(WherePred::from_repr(syntax.into_repr())),
+            _ => None,
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+
+impl ToOwned for WherePred {
+    type Owned = TreeArc<WherePred>;
+    fn to_owned(&self) -> TreeArc<WherePred> { TreeArc::cast(self.syntax.to_owned()) }
+}
+
+
+impl ast::TypeBoundsOwner for WherePred {}
+impl WherePred {
+    pub fn type_ref(&self) -> Option<&TypeRef> {
+        super::child_opt(self)
+    }
+
+    pub fn lifetime(&self) -> Option<&Lifetime> {
+        super::child_opt(self)
+    }
+}
 
 // WhileExpr
 #[derive(Debug, PartialEq, Eq, Hash)]
index 18730a8941eb28310869e43e918c983af5de7060..1123c2e9589df55e9a1c3d617090c678e1662dd0 100644 (file)
@@ -595,7 +595,20 @@ Grammar(
                 ["bounds", "TypeBound"],
             ]
         ),
-        "WhereClause": (),
+        "WherePred": (
+            options: [
+                "TypeRef",
+                "Lifetime",
+            ],
+            traits: [
+                "TypeBoundsOwner",
+            ],
+        ),
+        "WhereClause": (
+            collections: [
+                ["predicates", "WherePred"],
+            ],
+        ),
         "ExprStmt": (
             options: [ ["expr", "Expr"] ]
         ),
index e04b61eb386c831d52323397ae71cec77b354239..77a62ab4d86a2340c9eccda83c985b9a4eaa0e8e 100644 (file)
@@ -15,11 +15,14 @@ SOURCE_FILE@[0; 116)
         LIFETIME@[18; 20) "'a"
         COLON@[20; 21)
         WHITESPACE@[21; 22)
-        LIFETIME@[22; 24) "'b"
-        WHITESPACE@[24; 25)
-        PLUS@[25; 26)
-        WHITESPACE@[26; 27)
-        LIFETIME@[27; 29) "'c"
+        TYPE_BOUND_LIST@[22; 29)
+          TYPE_BOUND@[22; 24)
+            LIFETIME@[22; 24) "'b"
+          WHITESPACE@[24; 25)
+          PLUS@[25; 26)
+          WHITESPACE@[26; 27)
+          TYPE_BOUND@[27; 29)
+            LIFETIME@[27; 29) "'c"
       COMMA@[29; 30)
       WHITESPACE@[30; 34)
       WHERE_PRED@[34; 59)