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/tokens.rs | 93 ++++++++++++++++++++++++++++++++++++++ crates/ra_syntax/src/ast/traits.rs | 2 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 crates/ra_syntax/src/ast/tokens.rs (limited to 'crates/ra_syntax/src/ast') 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