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
This commit is contained in:
Ville Penttinen 2019-03-24 19:45:11 +02:00
parent 4666138c91
commit 3f62ab8f51
5 changed files with 132 additions and 8 deletions

View 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");
}

View File

@ -799,3 +799,70 @@ fn test_doc_comment_preserves_indents() {
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());
}

View File

@ -4810,7 +4810,48 @@ impl ToOwned for WhereClause {
}
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)]

View File

@ -595,7 +595,20 @@ Grammar(
["bounds", "TypeBound"],
]
),
"WhereClause": (),
"WherePred": (
options: [
"TypeRef",
"Lifetime",
],
traits: [
"TypeBoundsOwner",
],
),
"WhereClause": (
collections: [
["predicates", "WherePred"],
],
),
"ExprStmt": (
options: [ ["expr", "Expr"] ]
),

View 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)