From 68196ccc10c60de52bb771d295879456f73ede95 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Fri, 3 Apr 2020 21:12:08 +0200 Subject: Add AstElement trait, generate tokens, support tokens in enums - Adds a new AstElement trait that is implemented by all generated node, token and enum structs - Overhauls the code generators to code-generate all tokens, and also enhances enums to support including tokens, node, and nested enums --- crates/ra_syntax/src/ast.rs | 114 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 5 deletions(-) (limited to 'crates/ra_syntax/src/ast.rs') diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 26fafb469..1ac0201b8 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -11,7 +11,10 @@ pub mod make; use std::marker::PhantomData; use crate::{ - syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken}, + syntax_node::{ + NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, + SyntaxToken, + }, SmolStr, SyntaxKind, }; @@ -30,16 +33,24 @@ pub use self::{ /// conversion itself has zero runtime cost: ast and syntax nodes have exactly /// the same representation: a pointer to the tree root and a pointer to the /// node itself. -pub trait AstNode: std::fmt::Display { +pub trait AstNode: AstElement { fn can_cast(kind: SyntaxKind) -> bool where Self: Sized; - fn cast(syntax: SyntaxNode) -> Option + fn cast_or_return(syntax: SyntaxNode) -> Result where Self: Sized; + fn cast(syntax: SyntaxNode) -> Option + where + Self: Sized, + { + ::cast_or_return(syntax).ok() + } + fn syntax(&self) -> &SyntaxNode; + fn into_syntax(self) -> SyntaxNode; } #[test] @@ -48,16 +59,51 @@ fn assert_ast_is_object_safe() { } /// Like `AstNode`, but wraps tokens rather than interior nodes. -pub trait AstToken { - fn cast(token: SyntaxToken) -> Option +pub trait AstToken: AstElement { + fn can_cast(token: SyntaxKind) -> bool where Self: Sized; + + fn cast_or_return(syntax: SyntaxToken) -> Result + where + Self: Sized; + + fn cast(syntax: SyntaxToken) -> Option + where + Self: Sized, + { + ::cast_or_return(syntax).ok() + } + fn syntax(&self) -> &SyntaxToken; + fn into_syntax(self) -> SyntaxToken; + fn text(&self) -> &SmolStr { self.syntax().text() } } +/// Like `AstNode`, but wraps either nodes or tokens rather than interior nodes. +pub trait AstElement: std::fmt::Display { + fn can_cast_element(kind: SyntaxKind) -> bool + where + Self: Sized; + + fn cast_or_return_element(syntax: SyntaxElement) -> Result + where + Self: Sized; + + fn cast_element(syntax: SyntaxElement) -> Option + where + Self: Sized, + { + ::cast_or_return_element(syntax).ok() + } + + fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken>; + fn into_syntax_element(self) -> SyntaxElement; +} + /// An iterator over `SyntaxNode` children of a particular AST type. #[derive(Debug, Clone)] pub struct AstChildren { @@ -86,6 +132,64 @@ fn children(parent: &P) -> AstChildren { AstChildren::new(parent.syntax()) } +/// An iterator over `SyntaxToken` children of a particular AST type. +#[derive(Debug, Clone)] +pub struct AstChildTokens { + inner: SyntaxElementChildren, + ph: PhantomData, +} + +impl AstChildTokens { + fn new(parent: &SyntaxNode) -> Self { + AstChildTokens { inner: parent.children_with_tokens(), ph: PhantomData } + } +} + +impl Iterator for AstChildTokens { + type Item = N; + fn next(&mut self) -> Option { + self.inner.by_ref().filter_map(|x| x.into_token()).find_map(N::cast) + } +} + +fn child_token_opt(parent: &P) -> Option { + child_tokens(parent).next() +} + +fn child_tokens(parent: &P) -> AstChildTokens { + AstChildTokens::new(parent.syntax()) +} + +/// An iterator over `SyntaxNode` children of a particular AST type. +#[derive(Debug, Clone)] +pub struct AstChildElements { + inner: SyntaxElementChildren, + ph: PhantomData, +} + +impl AstChildElements { + fn new(parent: &SyntaxNode) -> Self { + AstChildElements { inner: parent.children_with_tokens(), ph: PhantomData } + } +} + +impl Iterator for AstChildElements { + type Item = N; + fn next(&mut self) -> Option { + self.inner.by_ref().find_map(N::cast_element) + } +} + +#[allow(dead_code)] +fn child_element_opt(parent: &P) -> Option { + child_elements(parent).next() +} + +#[allow(dead_code)] +fn child_elements(parent: &P) -> AstChildElements { + AstChildElements::new(parent.syntax()) +} + #[test] fn test_doc_comment_none() { let file = SourceFile::parse( -- cgit v1.2.3 From 8f01e62bb962fbe282344125f6ace54326efcaa3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 10:47:05 +0200 Subject: Scale back the traits --- crates/ra_syntax/src/ast.rs | 108 ++------------------------------------------ 1 file changed, 5 insertions(+), 103 deletions(-) (limited to 'crates/ra_syntax/src/ast.rs') diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 1ac0201b8..ab0f44dd2 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -11,10 +11,7 @@ pub mod make; use std::marker::PhantomData; use crate::{ - syntax_node::{ - NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, - SyntaxToken, - }, + syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken}, SmolStr, SyntaxKind, }; @@ -33,24 +30,16 @@ pub use self::{ /// conversion itself has zero runtime cost: ast and syntax nodes have exactly /// the same representation: a pointer to the tree root and a pointer to the /// node itself. -pub trait AstNode: AstElement { +pub trait AstNode { fn can_cast(kind: SyntaxKind) -> bool where Self: Sized; - fn cast_or_return(syntax: SyntaxNode) -> Result - where - Self: Sized; - fn cast(syntax: SyntaxNode) -> Option where - Self: Sized, - { - ::cast_or_return(syntax).ok() - } + Self: Sized; fn syntax(&self) -> &SyntaxNode; - fn into_syntax(self) -> SyntaxNode; } #[test] @@ -59,51 +48,22 @@ fn assert_ast_is_object_safe() { } /// Like `AstNode`, but wraps tokens rather than interior nodes. -pub trait AstToken: AstElement { +pub trait AstToken { fn can_cast(token: SyntaxKind) -> bool where Self: Sized; - fn cast_or_return(syntax: SyntaxToken) -> Result - where - Self: Sized; - fn cast(syntax: SyntaxToken) -> Option where - Self: Sized, - { - ::cast_or_return(syntax).ok() - } + Self: Sized; fn syntax(&self) -> &SyntaxToken; - fn into_syntax(self) -> SyntaxToken; fn text(&self) -> &SmolStr { self.syntax().text() } } -/// Like `AstNode`, but wraps either nodes or tokens rather than interior nodes. -pub trait AstElement: std::fmt::Display { - fn can_cast_element(kind: SyntaxKind) -> bool - where - Self: Sized; - - fn cast_or_return_element(syntax: SyntaxElement) -> Result - where - Self: Sized; - - fn cast_element(syntax: SyntaxElement) -> Option - where - Self: Sized, - { - ::cast_or_return_element(syntax).ok() - } - - fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken>; - fn into_syntax_element(self) -> SyntaxElement; -} - /// An iterator over `SyntaxNode` children of a particular AST type. #[derive(Debug, Clone)] pub struct AstChildren { @@ -132,64 +92,6 @@ fn children(parent: &P) -> AstChildren { AstChildren::new(parent.syntax()) } -/// An iterator over `SyntaxToken` children of a particular AST type. -#[derive(Debug, Clone)] -pub struct AstChildTokens { - inner: SyntaxElementChildren, - ph: PhantomData, -} - -impl AstChildTokens { - fn new(parent: &SyntaxNode) -> Self { - AstChildTokens { inner: parent.children_with_tokens(), ph: PhantomData } - } -} - -impl Iterator for AstChildTokens { - type Item = N; - fn next(&mut self) -> Option { - self.inner.by_ref().filter_map(|x| x.into_token()).find_map(N::cast) - } -} - -fn child_token_opt(parent: &P) -> Option { - child_tokens(parent).next() -} - -fn child_tokens(parent: &P) -> AstChildTokens { - AstChildTokens::new(parent.syntax()) -} - -/// An iterator over `SyntaxNode` children of a particular AST type. -#[derive(Debug, Clone)] -pub struct AstChildElements { - inner: SyntaxElementChildren, - ph: PhantomData, -} - -impl AstChildElements { - fn new(parent: &SyntaxNode) -> Self { - AstChildElements { inner: parent.children_with_tokens(), ph: PhantomData } - } -} - -impl Iterator for AstChildElements { - type Item = N; - fn next(&mut self) -> Option { - self.inner.by_ref().find_map(N::cast_element) - } -} - -#[allow(dead_code)] -fn child_element_opt(parent: &P) -> Option { - child_elements(parent).next() -} - -#[allow(dead_code)] -fn child_elements(parent: &P) -> AstChildElements { - AstChildElements::new(parent.syntax()) -} - #[test] fn test_doc_comment_none() { let file = SourceFile::parse( -- cgit v1.2.3