From 4e91c23c796988e3934afabf619185333f85c116 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 12 Feb 2019 18:41:57 +0300 Subject: rename yellow -> syntax_node why yellow in the first place? Its red + green. --- crates/ra_syntax/src/ast.rs | 2 +- crates/ra_syntax/src/ast/generated.rs | 2 +- crates/ra_syntax/src/ast/generated.rs.tera | 2 +- crates/ra_syntax/src/lib.rs | 8 +- crates/ra_syntax/src/parser_impl.rs | 2 +- crates/ra_syntax/src/parser_impl/event.rs | 2 +- crates/ra_syntax/src/reparsing.rs | 4 +- crates/ra_syntax/src/syntax_node.rs | 223 +++++++++++++++++++++ crates/ra_syntax/src/syntax_node/builder.rs | 41 ++++ crates/ra_syntax/src/syntax_node/syntax_error.rs | 142 +++++++++++++ crates/ra_syntax/src/syntax_node/syntax_text.rs | 144 +++++++++++++ crates/ra_syntax/src/validation.rs | 2 +- crates/ra_syntax/src/validation/block.rs | 2 +- crates/ra_syntax/src/validation/byte.rs | 2 +- crates/ra_syntax/src/validation/byte_string.rs | 2 +- crates/ra_syntax/src/validation/char.rs | 2 +- crates/ra_syntax/src/validation/string.rs | 2 +- crates/ra_syntax/src/yellow.rs | 223 --------------------- crates/ra_syntax/src/yellow/builder.rs | 41 ---- crates/ra_syntax/src/yellow/syntax_error.rs | 142 ------------- crates/ra_syntax/src/yellow/syntax_text.rs | 144 ------------- .../tests/data/parser/fuzz-failures/0000.rs | 4 +- 22 files changed, 569 insertions(+), 569 deletions(-) create mode 100644 crates/ra_syntax/src/syntax_node.rs create mode 100644 crates/ra_syntax/src/syntax_node/builder.rs create mode 100644 crates/ra_syntax/src/syntax_node/syntax_error.rs create mode 100644 crates/ra_syntax/src/syntax_node/syntax_text.rs delete mode 100644 crates/ra_syntax/src/yellow.rs delete mode 100644 crates/ra_syntax/src/yellow/builder.rs delete mode 100644 crates/ra_syntax/src/yellow/syntax_error.rs delete mode 100644 crates/ra_syntax/src/yellow/syntax_text.rs diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index cf5cfecc2..22105d6c9 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -6,7 +6,7 @@ use itertools::Itertools; pub use self::generated::*; use crate::{ - yellow::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes}, + syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes}, SmolStr, SyntaxKind::*, }; diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index d2b080743..5df3f2ccf 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -13,7 +13,7 @@ use rowan::TransparentNewType; use crate::{ SyntaxNode, SyntaxKind::*, - yellow::{RaTypes, TreeArc}, + syntax_node::{RaTypes, TreeArc}, ast::{self, AstNode}, }; diff --git a/crates/ra_syntax/src/ast/generated.rs.tera b/crates/ra_syntax/src/ast/generated.rs.tera index ea0fc35fd..ca7a28581 100644 --- a/crates/ra_syntax/src/ast/generated.rs.tera +++ b/crates/ra_syntax/src/ast/generated.rs.tera @@ -15,7 +15,7 @@ use rowan::TransparentNewType; use crate::{ SyntaxNode, SyntaxKind::*, - yellow::{RaTypes, TreeArc}, + syntax_node::{RaTypes, TreeArc}, ast::{self, AstNode}, }; {% for node, methods in ast %} diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 088b2f5d7..cbba1d4ae 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -30,7 +30,7 @@ mod syntax_kinds; /// Utilities for simple uses of the parser. pub mod utils; mod validation; -mod yellow; +mod syntax_node; mod ptr; pub use rowan::{SmolStr, TextRange, TextUnit}; @@ -38,12 +38,12 @@ pub use crate::{ ast::AstNode, lexer::{tokenize, Token}, syntax_kinds::SyntaxKind, - yellow::{Direction, SyntaxError, SyntaxNode, WalkEvent, Location, TreeArc}, + syntax_node::{Direction, SyntaxError, SyntaxNode, WalkEvent, Location, TreeArc}, ptr::{SyntaxNodePtr, AstPtr}, }; use ra_text_edit::AtomTextEdit; -use crate::yellow::GreenNode; +use crate::syntax_node::GreenNode; /// `SourceFile` represents a parse tree for a single Rust file. pub use crate::ast::SourceFile; @@ -61,7 +61,7 @@ impl SourceFile { pub fn parse(text: &str) -> TreeArc { let tokens = tokenize(&text); let (green, errors) = - parser_impl::parse_with(yellow::GreenBuilder::new(), text, &tokens, grammar::root); + parser_impl::parse_with(syntax_node::GreenBuilder::new(), text, &tokens, grammar::root); SourceFile::new(green, errors) } diff --git a/crates/ra_syntax/src/parser_impl.rs b/crates/ra_syntax/src/parser_impl.rs index f255dc23b..d99615d72 100644 --- a/crates/ra_syntax/src/parser_impl.rs +++ b/crates/ra_syntax/src/parser_impl.rs @@ -11,7 +11,7 @@ use crate::{ input::{InputPosition, ParserInput}, }, SmolStr, - yellow::syntax_error::{ + syntax_node::syntax_error::{ ParseError, SyntaxError, }, diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index 677876ab5..b45830c61 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs @@ -13,7 +13,7 @@ use crate::{ SmolStr, SyntaxKind::{self, *}, TextRange, TextUnit, - yellow::syntax_error::{ + syntax_node::syntax_error::{ ParseError, SyntaxError, SyntaxErrorKind, diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index c5c609ad5..dd751465c 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs @@ -3,7 +3,7 @@ use crate::grammar; use crate::lexer::{tokenize, Token}; use crate::parser_api::Parser; use crate::parser_impl; -use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNode}; +use crate::syntax_node::{self, GreenNode, SyntaxError, SyntaxNode}; use crate::{SyntaxKind::*, TextRange, TextUnit}; use ra_text_edit::AtomTextEdit; @@ -56,7 +56,7 @@ fn reparse_block<'node>( return None; } let (green, new_errors) = - parser_impl::parse_with(yellow::GreenBuilder::new(), &text, &tokens, reparser); + parser_impl::parse_with(syntax_node::GreenBuilder::new(), &text, &tokens, reparser); Some((node, green, new_errors)) } diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs new file mode 100644 index 000000000..ed48739f8 --- /dev/null +++ b/crates/ra_syntax/src/syntax_node.rs @@ -0,0 +1,223 @@ +mod builder; +pub mod syntax_error; +mod syntax_text; + +use std::{fmt, borrow::Borrow}; + +use self::syntax_text::SyntaxText; +use crate::{SmolStr, SyntaxKind, TextRange}; +use rowan::{Types, TransparentNewType}; + +pub(crate) use self::builder::GreenBuilder; +pub use self::syntax_error::{SyntaxError, SyntaxErrorKind, Location}; +pub use rowan::WalkEvent; + +#[derive(Debug, Clone, Copy)] +pub enum RaTypes {} +impl Types for RaTypes { + type Kind = SyntaxKind; + type RootData = Vec; +} + +pub type GreenNode = rowan::GreenNode; + +#[derive(PartialEq, Eq, Hash)] +pub struct TreeArc>>( + pub(crate) rowan::TreeArc, +); + +impl>> Borrow for TreeArc { + fn borrow(&self) -> &T { + &*self + } +} + +impl TreeArc +where + T: TransparentNewType>, +{ + pub(crate) fn cast(this: TreeArc) -> TreeArc + where + U: TransparentNewType>, + { + TreeArc(rowan::TreeArc::cast(this.0)) + } +} + +impl std::ops::Deref for TreeArc +where + T: TransparentNewType>, +{ + type Target = T; + fn deref(&self) -> &T { + self.0.deref() + } +} + +impl PartialEq for TreeArc +where + T: TransparentNewType>, + T: PartialEq, +{ + fn eq(&self, other: &T) -> bool { + let t: &T = self; + t == other + } +} + +impl Clone for TreeArc +where + T: TransparentNewType>, +{ + fn clone(&self) -> TreeArc { + TreeArc(self.0.clone()) + } +} + +impl fmt::Debug for TreeArc +where + T: TransparentNewType>, + T: fmt::Debug, +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, fmt) + } +} + +#[derive(PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct SyntaxNode(pub(crate) rowan::SyntaxNode); +unsafe impl TransparentNewType for SyntaxNode { + type Repr = rowan::SyntaxNode; +} + +impl SyntaxNode { + pub(crate) fn new(green: GreenNode, errors: Vec) -> TreeArc { + let ptr = TreeArc(rowan::SyntaxNode::new(green, errors)); + TreeArc::cast(ptr) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Direction { + Next, + Prev, +} + +impl SyntaxNode { + pub fn leaf_text(&self) -> Option<&SmolStr> { + self.0.leaf_text() + } + pub fn ancestors(&self) -> impl Iterator { + crate::algo::generate(Some(self), |&node| node.parent()) + } + pub fn descendants(&self) -> impl Iterator { + self.preorder().filter_map(|event| match event { + WalkEvent::Enter(node) => Some(node), + WalkEvent::Leave(_) => None, + }) + } + pub fn siblings(&self, direction: Direction) -> impl Iterator { + crate::algo::generate(Some(self), move |&node| match direction { + Direction::Next => node.next_sibling(), + Direction::Prev => node.prev_sibling(), + }) + } + pub fn preorder(&self) -> impl Iterator> { + self.0.preorder().map(|event| match event { + WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)), + WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode::from_repr(n)), + }) + } +} + +impl ToOwned for SyntaxNode { + type Owned = TreeArc; + fn to_owned(&self) -> TreeArc { + let ptr = TreeArc(self.0.to_owned()); + TreeArc::cast(ptr) + } +} + +impl SyntaxNode { + pub(crate) fn root_data(&self) -> &Vec { + self.0.root_data() + } + + pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { + self.0.replace_self(replacement) + } + + pub fn kind(&self) -> SyntaxKind { + self.0.kind() + } + + pub fn range(&self) -> TextRange { + self.0.range() + } + + pub fn text(&self) -> SyntaxText { + SyntaxText::new(self) + } + + pub fn is_leaf(&self) -> bool { + self.0.is_leaf() + } + + pub fn parent(&self) -> Option<&SyntaxNode> { + self.0.parent().map(SyntaxNode::from_repr) + } + + pub fn first_child(&self) -> Option<&SyntaxNode> { + self.0.first_child().map(SyntaxNode::from_repr) + } + + pub fn last_child(&self) -> Option<&SyntaxNode> { + self.0.last_child().map(SyntaxNode::from_repr) + } + + pub fn next_sibling(&self) -> Option<&SyntaxNode> { + self.0.next_sibling().map(SyntaxNode::from_repr) + } + + pub fn prev_sibling(&self) -> Option<&SyntaxNode> { + self.0.prev_sibling().map(SyntaxNode::from_repr) + } + + pub fn children(&self) -> SyntaxNodeChildren { + SyntaxNodeChildren(self.0.children()) + } + + pub fn memory_size_of_subtree(&self) -> usize { + self.0.memory_size_of_subtree() + } +} + +impl fmt::Debug for SyntaxNode { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; + if has_short_text(self.kind()) { + write!(fmt, " \"{}\"", self.text())?; + } + Ok(()) + } +} + +#[derive(Debug)] +pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a, RaTypes>); + +impl<'a> Iterator for SyntaxNodeChildren<'a> { + type Item = &'a SyntaxNode; + + fn next(&mut self) -> Option<&'a SyntaxNode> { + self.0.next().map(SyntaxNode::from_repr) + } +} + +fn has_short_text(kind: SyntaxKind) -> bool { + use crate::SyntaxKind::*; + match kind { + IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, + _ => false, + } +} diff --git a/crates/ra_syntax/src/syntax_node/builder.rs b/crates/ra_syntax/src/syntax_node/builder.rs new file mode 100644 index 000000000..8abd0f051 --- /dev/null +++ b/crates/ra_syntax/src/syntax_node/builder.rs @@ -0,0 +1,41 @@ +use crate::{ + parser_impl::Sink, + syntax_node::{GreenNode, RaTypes, SyntaxError}, + SmolStr, SyntaxKind, +}; +use rowan::GreenNodeBuilder; + +pub(crate) struct GreenBuilder { + errors: Vec, + inner: GreenNodeBuilder, +} + +impl GreenBuilder { + pub(crate) fn new() -> GreenBuilder { + GreenBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() } + } +} + +impl Sink for GreenBuilder { + type Tree = (GreenNode, Vec); + + fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) { + self.inner.leaf(kind, text); + } + + fn start_branch(&mut self, kind: SyntaxKind) { + self.inner.start_internal(kind) + } + + fn finish_branch(&mut self) { + self.inner.finish_internal(); + } + + fn error(&mut self, error: SyntaxError) { + self.errors.push(error) + } + + fn finish(self) -> (GreenNode, Vec) { + (self.inner.finish(), self.errors) + } +} diff --git a/crates/ra_syntax/src/syntax_node/syntax_error.rs b/crates/ra_syntax/src/syntax_node/syntax_error.rs new file mode 100644 index 000000000..412cf82cc --- /dev/null +++ b/crates/ra_syntax/src/syntax_node/syntax_error.rs @@ -0,0 +1,142 @@ +use std::fmt; + +use crate::{TextRange, TextUnit}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SyntaxError { + kind: SyntaxErrorKind, + location: Location, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Location { + Offset(TextUnit), + Range(TextRange), +} + +impl Into for TextUnit { + fn into(self) -> Location { + Location::Offset(self) + } +} + +impl Into for TextRange { + fn into(self) -> Location { + Location::Range(self) + } +} + +impl SyntaxError { + pub fn new>(kind: SyntaxErrorKind, loc: L) -> SyntaxError { + SyntaxError { kind, location: loc.into() } + } + + pub fn kind(&self) -> SyntaxErrorKind { + self.kind.clone() + } + + pub fn location(&self) -> Location { + self.location.clone() + } + + pub fn offset(&self) -> TextUnit { + match self.location { + Location::Offset(offset) => offset, + Location::Range(range) => range.start(), + } + } + + pub fn add_offset(mut self, plus_offset: TextUnit) -> SyntaxError { + self.location = match self.location { + Location::Range(range) => Location::Range(range + plus_offset), + Location::Offset(offset) => Location::Offset(offset + plus_offset), + }; + + self + } +} + +impl fmt::Display for SyntaxError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.kind.fmt(f) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum SyntaxErrorKind { + ParseError(ParseError), + UnescapedCodepoint, + EmptyChar, + UnclosedChar, + OverlongChar, + EmptyByte, + UnclosedByte, + OverlongByte, + ByteOutOfRange, + UnescapedByte, + EmptyByteEscape, + InvalidByteEscape, + TooShortByteCodeEscape, + MalformedByteCodeEscape, + UnicodeEscapeForbidden, + EmptyAsciiEscape, + InvalidAsciiEscape, + TooShortAsciiCodeEscape, + AsciiCodeEscapeOutOfRange, + MalformedAsciiCodeEscape, + UnclosedUnicodeEscape, + MalformedUnicodeEscape, + EmptyUnicodeEcape, + OverlongUnicodeEscape, + UnicodeEscapeOutOfRange, + UnclosedString, + InvalidSuffix, + InvalidBlockAttr, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ParseError(pub String); + +impl fmt::Display for SyntaxErrorKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::SyntaxErrorKind::*; + match self { + UnescapedCodepoint => write!(f, "This codepoint should always be escaped"), + EmptyAsciiEscape => write!(f, "Empty escape sequence"), + InvalidAsciiEscape => write!(f, "Invalid escape sequence"), + EmptyChar => write!(f, "Empty char literal"), + UnclosedChar => write!(f, "Unclosed char literal"), + OverlongChar => write!(f, "Char literal should be one character long"), + EmptyByte => write!(f, "Empty byte literal"), + UnclosedByte => write!(f, "Unclosed byte literal"), + OverlongByte => write!(f, "Byte literal should be one character long"), + ByteOutOfRange => write!(f, "Byte should be a valid ASCII character"), + UnescapedByte => write!(f, "This byte should always be escaped"), + EmptyByteEscape => write!(f, "Empty escape sequence"), + InvalidByteEscape => write!(f, "Invalid escape sequence"), + TooShortByteCodeEscape => write!(f, "Escape sequence should have two digits"), + MalformedByteCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), + UnicodeEscapeForbidden => { + write!(f, "Unicode escapes are not allowed in byte literals or byte strings") + } + TooShortAsciiCodeEscape => write!(f, "Escape sequence should have two digits"), + AsciiCodeEscapeOutOfRange => { + write!(f, "Escape sequence should be between \\x00 and \\x7F") + } + MalformedAsciiCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), + UnclosedUnicodeEscape => write!(f, "Missing `}}`"), + MalformedUnicodeEscape => write!(f, "Malformed unicode escape sequence"), + EmptyUnicodeEcape => write!(f, "Empty unicode escape sequence"), + OverlongUnicodeEscape => { + write!(f, "Unicode escape sequence should have at most 6 digits") + } + UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"), + UnclosedString => write!(f, "Unclosed string literal"), + InvalidSuffix => write!(f, "Invalid literal suffix"), + InvalidBlockAttr => { + write!(f, "A block in this position cannot accept inner attributes") + } + ParseError(msg) => write!(f, "{}", msg.0), + } + } +} diff --git a/crates/ra_syntax/src/syntax_node/syntax_text.rs b/crates/ra_syntax/src/syntax_node/syntax_text.rs new file mode 100644 index 000000000..84e5b231a --- /dev/null +++ b/crates/ra_syntax/src/syntax_node/syntax_text.rs @@ -0,0 +1,144 @@ +use std::{fmt, ops}; + +use crate::{SyntaxNode, TextRange, TextUnit}; + +#[derive(Clone)] +pub struct SyntaxText<'a> { + node: &'a SyntaxNode, + range: TextRange, +} + +impl<'a> SyntaxText<'a> { + pub(crate) fn new(node: &'a SyntaxNode) -> SyntaxText<'a> { + SyntaxText { node, range: node.range() } + } + + pub fn chunks(&self) -> impl Iterator { + let range = self.range; + self.node.descendants().filter_map(move |node| { + let text = node.leaf_text()?; + let range = range.intersection(&node.range())?; + let range = range - node.range().start(); + Some(&text[range]) + }) + } + + pub fn push_to(&self, buf: &mut String) { + self.chunks().for_each(|it| buf.push_str(it)); + } + + pub fn to_string(&self) -> String { + self.chunks().collect() + } + + pub fn contains(&self, c: char) -> bool { + self.chunks().any(|it| it.contains(c)) + } + + pub fn find(&self, c: char) -> Option { + let mut acc: TextUnit = 0.into(); + for chunk in self.chunks() { + if let Some(pos) = chunk.find(c) { + let pos: TextUnit = (pos as u32).into(); + return Some(acc + pos); + } + acc += TextUnit::of_str(chunk); + } + None + } + + pub fn len(&self) -> TextUnit { + self.range.len() + } + + pub fn slice(&self, range: impl SyntaxTextSlice) -> SyntaxText<'a> { + let range = range.restrict(self.range).unwrap_or_else(|| { + panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) + }); + SyntaxText { node: self.node, range } + } + + pub fn char_at(&self, offset: impl Into) -> Option { + let mut start: TextUnit = 0.into(); + let offset = offset.into(); + for chunk in self.chunks() { + let end = start + TextUnit::of_str(chunk); + if start <= offset && offset < end { + let off: usize = u32::from(offset - start) as usize; + return Some(chunk[off..].chars().next().unwrap()); + } + start = end; + } + None + } +} + +impl<'a> fmt::Debug for SyntaxText<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.to_string(), f) + } +} + +impl<'a> fmt::Display for SyntaxText<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.to_string(), f) + } +} + +pub trait SyntaxTextSlice: fmt::Debug { + fn restrict(&self, range: TextRange) -> Option; +} + +impl SyntaxTextSlice for TextRange { + fn restrict(&self, range: TextRange) -> Option { + self.intersection(&range) + } +} + +impl SyntaxTextSlice for ops::RangeTo { + fn restrict(&self, range: TextRange) -> Option { + if !range.contains_inclusive(self.end) { + return None; + } + Some(TextRange::from_to(range.start(), self.end)) + } +} + +impl SyntaxTextSlice for ops::RangeFrom { + fn restrict(&self, range: TextRange) -> Option { + if !range.contains_inclusive(self.start) { + return None; + } + Some(TextRange::from_to(self.start, range.end())) + } +} + +impl SyntaxTextSlice for ops::Range { + fn restrict(&self, range: TextRange) -> Option { + TextRange::from_to(self.start, self.end).restrict(range) + } +} + +impl From> for String { + fn from(text: SyntaxText) -> String { + text.to_string() + } +} + +impl PartialEq for SyntaxText<'_> { + fn eq(&self, mut rhs: &str) -> bool { + for chunk in self.chunks() { + if !rhs.starts_with(chunk) { + return false; + } + rhs = &rhs[chunk.len()..]; + } + rhs.is_empty() + } +} + +impl PartialEq<&'_ str> for SyntaxText<'_> { + fn eq(&self, rhs: &&str) -> bool { + self == *rhs + } +} diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index ac6cc3dd6..10672d6bf 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs @@ -5,7 +5,7 @@ mod string; mod block; use crate::{ - SourceFile, yellow::SyntaxError, AstNode, + SourceFile, syntax_node::SyntaxError, AstNode, ast, algo::visit::{visitor_ctx, VisitorCtx}, }; diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs index 4e77c15b6..de949d967 100644 --- a/crates/ra_syntax/src/validation/block.rs +++ b/crates/ra_syntax/src/validation/block.rs @@ -1,6 +1,6 @@ use crate::{SyntaxKind::*, ast::{self, AttrsOwner, AstNode}, - yellow::{ + syntax_node::{ SyntaxError, SyntaxErrorKind::*, }, diff --git a/crates/ra_syntax/src/validation/byte.rs b/crates/ra_syntax/src/validation/byte.rs index d51fabcf9..acdc12552 100644 --- a/crates/ra_syntax/src/validation/byte.rs +++ b/crates/ra_syntax/src/validation/byte.rs @@ -5,7 +5,7 @@ use crate::{ string_lexing::{self, StringComponentKind}, TextRange, validation::char, - yellow::{ + syntax_node::{ SyntaxError, SyntaxErrorKind::*, }, diff --git a/crates/ra_syntax/src/validation/byte_string.rs b/crates/ra_syntax/src/validation/byte_string.rs index 7abe8f330..69a98b640 100644 --- a/crates/ra_syntax/src/validation/byte_string.rs +++ b/crates/ra_syntax/src/validation/byte_string.rs @@ -1,7 +1,7 @@ use crate::{ ast::{self, AstNode, AstToken}, string_lexing::{self, StringComponentKind}, - yellow::{ + syntax_node::{ SyntaxError, SyntaxErrorKind::*, }, diff --git a/crates/ra_syntax/src/validation/char.rs b/crates/ra_syntax/src/validation/char.rs index 012594db3..26c15e36d 100644 --- a/crates/ra_syntax/src/validation/char.rs +++ b/crates/ra_syntax/src/validation/char.rs @@ -8,7 +8,7 @@ use crate::{ ast::{self, AstNode, AstToken}, string_lexing::{self, StringComponentKind}, TextRange, - yellow::{ + syntax_node::{ SyntaxError, SyntaxErrorKind::*, }, diff --git a/crates/ra_syntax/src/validation/string.rs b/crates/ra_syntax/src/validation/string.rs index 4fd7fffdf..2f7f9c7c4 100644 --- a/crates/ra_syntax/src/validation/string.rs +++ b/crates/ra_syntax/src/validation/string.rs @@ -1,7 +1,7 @@ use crate::{ ast::{self, AstNode, AstToken}, string_lexing, - yellow::{ + syntax_node::{ SyntaxError, SyntaxErrorKind::*, }, diff --git a/crates/ra_syntax/src/yellow.rs b/crates/ra_syntax/src/yellow.rs deleted file mode 100644 index ed48739f8..000000000 --- a/crates/ra_syntax/src/yellow.rs +++ /dev/null @@ -1,223 +0,0 @@ -mod builder; -pub mod syntax_error; -mod syntax_text; - -use std::{fmt, borrow::Borrow}; - -use self::syntax_text::SyntaxText; -use crate::{SmolStr, SyntaxKind, TextRange}; -use rowan::{Types, TransparentNewType}; - -pub(crate) use self::builder::GreenBuilder; -pub use self::syntax_error::{SyntaxError, SyntaxErrorKind, Location}; -pub use rowan::WalkEvent; - -#[derive(Debug, Clone, Copy)] -pub enum RaTypes {} -impl Types for RaTypes { - type Kind = SyntaxKind; - type RootData = Vec; -} - -pub type GreenNode = rowan::GreenNode; - -#[derive(PartialEq, Eq, Hash)] -pub struct TreeArc>>( - pub(crate) rowan::TreeArc, -); - -impl>> Borrow for TreeArc { - fn borrow(&self) -> &T { - &*self - } -} - -impl TreeArc -where - T: TransparentNewType>, -{ - pub(crate) fn cast(this: TreeArc) -> TreeArc - where - U: TransparentNewType>, - { - TreeArc(rowan::TreeArc::cast(this.0)) - } -} - -impl std::ops::Deref for TreeArc -where - T: TransparentNewType>, -{ - type Target = T; - fn deref(&self) -> &T { - self.0.deref() - } -} - -impl PartialEq for TreeArc -where - T: TransparentNewType>, - T: PartialEq, -{ - fn eq(&self, other: &T) -> bool { - let t: &T = self; - t == other - } -} - -impl Clone for TreeArc -where - T: TransparentNewType>, -{ - fn clone(&self) -> TreeArc { - TreeArc(self.0.clone()) - } -} - -impl fmt::Debug for TreeArc -where - T: TransparentNewType>, - T: fmt::Debug, -{ - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.0, fmt) - } -} - -#[derive(PartialEq, Eq, Hash)] -#[repr(transparent)] -pub struct SyntaxNode(pub(crate) rowan::SyntaxNode); -unsafe impl TransparentNewType for SyntaxNode { - type Repr = rowan::SyntaxNode; -} - -impl SyntaxNode { - pub(crate) fn new(green: GreenNode, errors: Vec) -> TreeArc { - let ptr = TreeArc(rowan::SyntaxNode::new(green, errors)); - TreeArc::cast(ptr) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Direction { - Next, - Prev, -} - -impl SyntaxNode { - pub fn leaf_text(&self) -> Option<&SmolStr> { - self.0.leaf_text() - } - pub fn ancestors(&self) -> impl Iterator { - crate::algo::generate(Some(self), |&node| node.parent()) - } - pub fn descendants(&self) -> impl Iterator { - self.preorder().filter_map(|event| match event { - WalkEvent::Enter(node) => Some(node), - WalkEvent::Leave(_) => None, - }) - } - pub fn siblings(&self, direction: Direction) -> impl Iterator { - crate::algo::generate(Some(self), move |&node| match direction { - Direction::Next => node.next_sibling(), - Direction::Prev => node.prev_sibling(), - }) - } - pub fn preorder(&self) -> impl Iterator> { - self.0.preorder().map(|event| match event { - WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)), - WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode::from_repr(n)), - }) - } -} - -impl ToOwned for SyntaxNode { - type Owned = TreeArc; - fn to_owned(&self) -> TreeArc { - let ptr = TreeArc(self.0.to_owned()); - TreeArc::cast(ptr) - } -} - -impl SyntaxNode { - pub(crate) fn root_data(&self) -> &Vec { - self.0.root_data() - } - - pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { - self.0.replace_self(replacement) - } - - pub fn kind(&self) -> SyntaxKind { - self.0.kind() - } - - pub fn range(&self) -> TextRange { - self.0.range() - } - - pub fn text(&self) -> SyntaxText { - SyntaxText::new(self) - } - - pub fn is_leaf(&self) -> bool { - self.0.is_leaf() - } - - pub fn parent(&self) -> Option<&SyntaxNode> { - self.0.parent().map(SyntaxNode::from_repr) - } - - pub fn first_child(&self) -> Option<&SyntaxNode> { - self.0.first_child().map(SyntaxNode::from_repr) - } - - pub fn last_child(&self) -> Option<&SyntaxNode> { - self.0.last_child().map(SyntaxNode::from_repr) - } - - pub fn next_sibling(&self) -> Option<&SyntaxNode> { - self.0.next_sibling().map(SyntaxNode::from_repr) - } - - pub fn prev_sibling(&self) -> Option<&SyntaxNode> { - self.0.prev_sibling().map(SyntaxNode::from_repr) - } - - pub fn children(&self) -> SyntaxNodeChildren { - SyntaxNodeChildren(self.0.children()) - } - - pub fn memory_size_of_subtree(&self) -> usize { - self.0.memory_size_of_subtree() - } -} - -impl fmt::Debug for SyntaxNode { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; - if has_short_text(self.kind()) { - write!(fmt, " \"{}\"", self.text())?; - } - Ok(()) - } -} - -#[derive(Debug)] -pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a, RaTypes>); - -impl<'a> Iterator for SyntaxNodeChildren<'a> { - type Item = &'a SyntaxNode; - - fn next(&mut self) -> Option<&'a SyntaxNode> { - self.0.next().map(SyntaxNode::from_repr) - } -} - -fn has_short_text(kind: SyntaxKind) -> bool { - use crate::SyntaxKind::*; - match kind { - IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, - _ => false, - } -} diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs deleted file mode 100644 index e8b9112d4..000000000 --- a/crates/ra_syntax/src/yellow/builder.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::{ - parser_impl::Sink, - yellow::{GreenNode, RaTypes, SyntaxError}, - SmolStr, SyntaxKind, -}; -use rowan::GreenNodeBuilder; - -pub(crate) struct GreenBuilder { - errors: Vec, - inner: GreenNodeBuilder, -} - -impl GreenBuilder { - pub(crate) fn new() -> GreenBuilder { - GreenBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() } - } -} - -impl Sink for GreenBuilder { - type Tree = (GreenNode, Vec); - - fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) { - self.inner.leaf(kind, text); - } - - fn start_branch(&mut self, kind: SyntaxKind) { - self.inner.start_internal(kind) - } - - fn finish_branch(&mut self) { - self.inner.finish_internal(); - } - - fn error(&mut self, error: SyntaxError) { - self.errors.push(error) - } - - fn finish(self) -> (GreenNode, Vec) { - (self.inner.finish(), self.errors) - } -} diff --git a/crates/ra_syntax/src/yellow/syntax_error.rs b/crates/ra_syntax/src/yellow/syntax_error.rs deleted file mode 100644 index 412cf82cc..000000000 --- a/crates/ra_syntax/src/yellow/syntax_error.rs +++ /dev/null @@ -1,142 +0,0 @@ -use std::fmt; - -use crate::{TextRange, TextUnit}; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct SyntaxError { - kind: SyntaxErrorKind, - location: Location, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Location { - Offset(TextUnit), - Range(TextRange), -} - -impl Into for TextUnit { - fn into(self) -> Location { - Location::Offset(self) - } -} - -impl Into for TextRange { - fn into(self) -> Location { - Location::Range(self) - } -} - -impl SyntaxError { - pub fn new>(kind: SyntaxErrorKind, loc: L) -> SyntaxError { - SyntaxError { kind, location: loc.into() } - } - - pub fn kind(&self) -> SyntaxErrorKind { - self.kind.clone() - } - - pub fn location(&self) -> Location { - self.location.clone() - } - - pub fn offset(&self) -> TextUnit { - match self.location { - Location::Offset(offset) => offset, - Location::Range(range) => range.start(), - } - } - - pub fn add_offset(mut self, plus_offset: TextUnit) -> SyntaxError { - self.location = match self.location { - Location::Range(range) => Location::Range(range + plus_offset), - Location::Offset(offset) => Location::Offset(offset + plus_offset), - }; - - self - } -} - -impl fmt::Display for SyntaxError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.kind.fmt(f) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum SyntaxErrorKind { - ParseError(ParseError), - UnescapedCodepoint, - EmptyChar, - UnclosedChar, - OverlongChar, - EmptyByte, - UnclosedByte, - OverlongByte, - ByteOutOfRange, - UnescapedByte, - EmptyByteEscape, - InvalidByteEscape, - TooShortByteCodeEscape, - MalformedByteCodeEscape, - UnicodeEscapeForbidden, - EmptyAsciiEscape, - InvalidAsciiEscape, - TooShortAsciiCodeEscape, - AsciiCodeEscapeOutOfRange, - MalformedAsciiCodeEscape, - UnclosedUnicodeEscape, - MalformedUnicodeEscape, - EmptyUnicodeEcape, - OverlongUnicodeEscape, - UnicodeEscapeOutOfRange, - UnclosedString, - InvalidSuffix, - InvalidBlockAttr, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ParseError(pub String); - -impl fmt::Display for SyntaxErrorKind { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::SyntaxErrorKind::*; - match self { - UnescapedCodepoint => write!(f, "This codepoint should always be escaped"), - EmptyAsciiEscape => write!(f, "Empty escape sequence"), - InvalidAsciiEscape => write!(f, "Invalid escape sequence"), - EmptyChar => write!(f, "Empty char literal"), - UnclosedChar => write!(f, "Unclosed char literal"), - OverlongChar => write!(f, "Char literal should be one character long"), - EmptyByte => write!(f, "Empty byte literal"), - UnclosedByte => write!(f, "Unclosed byte literal"), - OverlongByte => write!(f, "Byte literal should be one character long"), - ByteOutOfRange => write!(f, "Byte should be a valid ASCII character"), - UnescapedByte => write!(f, "This byte should always be escaped"), - EmptyByteEscape => write!(f, "Empty escape sequence"), - InvalidByteEscape => write!(f, "Invalid escape sequence"), - TooShortByteCodeEscape => write!(f, "Escape sequence should have two digits"), - MalformedByteCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), - UnicodeEscapeForbidden => { - write!(f, "Unicode escapes are not allowed in byte literals or byte strings") - } - TooShortAsciiCodeEscape => write!(f, "Escape sequence should have two digits"), - AsciiCodeEscapeOutOfRange => { - write!(f, "Escape sequence should be between \\x00 and \\x7F") - } - MalformedAsciiCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), - UnclosedUnicodeEscape => write!(f, "Missing `}}`"), - MalformedUnicodeEscape => write!(f, "Malformed unicode escape sequence"), - EmptyUnicodeEcape => write!(f, "Empty unicode escape sequence"), - OverlongUnicodeEscape => { - write!(f, "Unicode escape sequence should have at most 6 digits") - } - UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"), - UnclosedString => write!(f, "Unclosed string literal"), - InvalidSuffix => write!(f, "Invalid literal suffix"), - InvalidBlockAttr => { - write!(f, "A block in this position cannot accept inner attributes") - } - ParseError(msg) => write!(f, "{}", msg.0), - } - } -} diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs deleted file mode 100644 index 84e5b231a..000000000 --- a/crates/ra_syntax/src/yellow/syntax_text.rs +++ /dev/null @@ -1,144 +0,0 @@ -use std::{fmt, ops}; - -use crate::{SyntaxNode, TextRange, TextUnit}; - -#[derive(Clone)] -pub struct SyntaxText<'a> { - node: &'a SyntaxNode, - range: TextRange, -} - -impl<'a> SyntaxText<'a> { - pub(crate) fn new(node: &'a SyntaxNode) -> SyntaxText<'a> { - SyntaxText { node, range: node.range() } - } - - pub fn chunks(&self) -> impl Iterator { - let range = self.range; - self.node.descendants().filter_map(move |node| { - let text = node.leaf_text()?; - let range = range.intersection(&node.range())?; - let range = range - node.range().start(); - Some(&text[range]) - }) - } - - pub fn push_to(&self, buf: &mut String) { - self.chunks().for_each(|it| buf.push_str(it)); - } - - pub fn to_string(&self) -> String { - self.chunks().collect() - } - - pub fn contains(&self, c: char) -> bool { - self.chunks().any(|it| it.contains(c)) - } - - pub fn find(&self, c: char) -> Option { - let mut acc: TextUnit = 0.into(); - for chunk in self.chunks() { - if let Some(pos) = chunk.find(c) { - let pos: TextUnit = (pos as u32).into(); - return Some(acc + pos); - } - acc += TextUnit::of_str(chunk); - } - None - } - - pub fn len(&self) -> TextUnit { - self.range.len() - } - - pub fn slice(&self, range: impl SyntaxTextSlice) -> SyntaxText<'a> { - let range = range.restrict(self.range).unwrap_or_else(|| { - panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) - }); - SyntaxText { node: self.node, range } - } - - pub fn char_at(&self, offset: impl Into) -> Option { - let mut start: TextUnit = 0.into(); - let offset = offset.into(); - for chunk in self.chunks() { - let end = start + TextUnit::of_str(chunk); - if start <= offset && offset < end { - let off: usize = u32::from(offset - start) as usize; - return Some(chunk[off..].chars().next().unwrap()); - } - start = end; - } - None - } -} - -impl<'a> fmt::Debug for SyntaxText<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.to_string(), f) - } -} - -impl<'a> fmt::Display for SyntaxText<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.to_string(), f) - } -} - -pub trait SyntaxTextSlice: fmt::Debug { - fn restrict(&self, range: TextRange) -> Option; -} - -impl SyntaxTextSlice for TextRange { - fn restrict(&self, range: TextRange) -> Option { - self.intersection(&range) - } -} - -impl SyntaxTextSlice for ops::RangeTo { - fn restrict(&self, range: TextRange) -> Option { - if !range.contains_inclusive(self.end) { - return None; - } - Some(TextRange::from_to(range.start(), self.end)) - } -} - -impl SyntaxTextSlice for ops::RangeFrom { - fn restrict(&self, range: TextRange) -> Option { - if !range.contains_inclusive(self.start) { - return None; - } - Some(TextRange::from_to(self.start, range.end())) - } -} - -impl SyntaxTextSlice for ops::Range { - fn restrict(&self, range: TextRange) -> Option { - TextRange::from_to(self.start, self.end).restrict(range) - } -} - -impl From> for String { - fn from(text: SyntaxText) -> String { - text.to_string() - } -} - -impl PartialEq for SyntaxText<'_> { - fn eq(&self, mut rhs: &str) -> bool { - for chunk in self.chunks() { - if !rhs.starts_with(chunk) { - return false; - } - rhs = &rhs[chunk.len()..]; - } - rhs.is_empty() - } -} - -impl PartialEq<&'_ str> for SyntaxText<'_> { - fn eq(&self, rhs: &&str) -> bool { - self == *rhs - } -} diff --git a/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs b/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs index 59cd11495..e0437d163 100644 --- a/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs +++ b/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs @@ -5,7 +5,7 @@ } pub fn parse(text: &str) -> File { let tokens = tokenize(&text); - let (green, errors) = parser_impl::parse_with::( + let (green, errors) = parser_impl::parse_with::( text, &tokens, grammar::root, ); File::new(green, errors) @@ -24,7 +24,7 @@ if !is_balanced(&tokens) { return None; } - let (green, new_errors) = parser_impl::parse_with::( + let (green, new_errors) = parser_impl::parse_with::( &te2t, &tokens, reparser, ); let green_root = node.replace_with(green); -- cgit v1.2.3