From ae282d8da63a82077361bc142b2b9a272a2eac64 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 2 Apr 2019 10:23:18 +0300 Subject: add ast::tokens --- crates/ra_syntax/src/ast.rs | 106 +++++-------------------------------- crates/ra_syntax/src/ast/tokens.rs | 93 ++++++++++++++++++++++++++++++++ crates/ra_syntax/src/ast/traits.rs | 2 +- 3 files changed, 106 insertions(+), 95 deletions(-) create mode 100644 crates/ra_syntax/src/ast/tokens.rs (limited to 'crates/ra_syntax') diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 9950ab12d..beef2c6e2 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -1,6 +1,7 @@ //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s mod generated; mod traits; +mod tokens; use std::marker::PhantomData; @@ -15,6 +16,7 @@ use crate::{ pub use self::{ generated::*, traits::*, + tokens::*, }; /// The main trait to go from untyped `SyntaxNode` to a typed ast. The @@ -49,6 +51,16 @@ impl<'a, N: AstNode + 'a> Iterator for AstChildren<'a, N> { } } +pub trait AstToken<'a> { + fn cast(token: SyntaxToken<'a>) -> Option + where + Self: Sized; + fn syntax(&self) -> SyntaxToken<'a>; + fn text(&self) -> &'a SmolStr { + self.syntax().text() + } +} + impl Attr { pub fn is_inner(&self) -> bool { let tt = match self.value() { @@ -96,100 +108,6 @@ impl Attr { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct Comment<'a>(SyntaxToken<'a>); - -impl<'a> Comment<'a> { - pub fn cast(token: SyntaxToken<'a>) -> Option { - if token.kind() == COMMENT { - Some(Comment(token)) - } else { - None - } - } - - pub fn syntax(&self) -> SyntaxToken<'a> { - self.0 - } - - pub fn text(&self) -> &'a SmolStr { - self.0.text() - } - - pub fn flavor(&self) -> CommentFlavor { - let text = self.text(); - if text.starts_with("///") { - CommentFlavor::Doc - } else if text.starts_with("//!") { - CommentFlavor::ModuleDoc - } else if text.starts_with("//") { - CommentFlavor::Line - } else { - CommentFlavor::Multiline - } - } - - pub fn is_doc_comment(&self) -> bool { - self.flavor().is_doc_comment() - } - - pub fn prefix(&self) -> &'static str { - self.flavor().prefix() - } -} - -#[derive(Debug, PartialEq, Eq)] -pub enum CommentFlavor { - Line, - Doc, - ModuleDoc, - Multiline, -} - -impl CommentFlavor { - pub fn prefix(&self) -> &'static str { - use self::CommentFlavor::*; - match *self { - Line => "//", - Doc => "///", - ModuleDoc => "//!", - Multiline => "/*", - } - } - - pub fn is_doc_comment(&self) -> bool { - match self { - CommentFlavor::Doc | CommentFlavor::ModuleDoc => true, - _ => false, - } - } -} - -pub struct Whitespace<'a>(SyntaxToken<'a>); - -impl<'a> Whitespace<'a> { - pub fn cast(token: SyntaxToken<'a>) -> Option { - if token.kind() == WHITESPACE { - Some(Whitespace(token)) - } else { - None - } - } - - pub fn syntax(&self) -> SyntaxToken<'a> { - self.0 - } - - pub fn text(&self) -> &'a SmolStr { - self.0.text() - } - - pub fn spans_multiple_lines(&self) -> bool { - let text = self.text(); - text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n')) - } -} - impl Name { pub fn text(&self) -> &SmolStr { let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap(); diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs new file mode 100644 index 000000000..c830cdccf --- /dev/null +++ b/crates/ra_syntax/src/ast/tokens.rs @@ -0,0 +1,93 @@ +use crate::{ + SyntaxToken, + SyntaxKind::{COMMENT, WHITESPACE}, + ast::AstToken, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Comment<'a>(SyntaxToken<'a>); + +impl<'a> AstToken<'a> for Comment<'a> { + fn cast(token: SyntaxToken<'a>) -> Option { + if token.kind() == COMMENT { + Some(Comment(token)) + } else { + None + } + } + fn syntax(&self) -> SyntaxToken<'a> { + self.0 + } +} + +impl<'a> Comment<'a> { + pub fn flavor(&self) -> CommentFlavor { + let text = self.text(); + if text.starts_with("///") { + CommentFlavor::Doc + } else if text.starts_with("//!") { + CommentFlavor::ModuleDoc + } else if text.starts_with("//") { + CommentFlavor::Line + } else { + CommentFlavor::Multiline + } + } + + pub fn is_doc_comment(&self) -> bool { + self.flavor().is_doc_comment() + } + + pub fn prefix(&self) -> &'static str { + self.flavor().prefix() + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum CommentFlavor { + Line, + Doc, + ModuleDoc, + Multiline, +} + +impl CommentFlavor { + pub fn prefix(&self) -> &'static str { + use self::CommentFlavor::*; + match *self { + Line => "//", + Doc => "///", + ModuleDoc => "//!", + Multiline => "/*", + } + } + + pub fn is_doc_comment(&self) -> bool { + match self { + CommentFlavor::Doc | CommentFlavor::ModuleDoc => true, + _ => false, + } + } +} + +pub struct Whitespace<'a>(SyntaxToken<'a>); + +impl<'a> AstToken<'a> for Whitespace<'a> { + fn cast(token: SyntaxToken<'a>) -> Option { + if token.kind() == WHITESPACE { + Some(Whitespace(token)) + } else { + None + } + } + fn syntax(&self) -> SyntaxToken<'a> { + self.0 + } +} + +impl<'a> Whitespace<'a> { + pub fn spans_multiple_lines(&self) -> bool { + let text = self.text(); + text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n')) + } +} diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index 85fe6d5e1..f9021d7bf 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use crate::{ syntax_node::{SyntaxNodeChildren, SyntaxElementChildren}, - ast::{self, child_opt, children, AstNode, AstChildren}, + ast::{self, child_opt, children, AstNode, AstToken, AstChildren}, }; pub trait TypeAscriptionOwner: AstNode { -- cgit v1.2.3