mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
introduce tree builder
This commit is contained in:
parent
0c1cb98182
commit
f078f7adc8
3 changed files with 61 additions and 20 deletions
|
@ -36,7 +36,7 @@ pub use crate::{
|
|||
ast::AstNode,
|
||||
syntax_error::{SyntaxError, SyntaxErrorKind, Location},
|
||||
syntax_text::SyntaxText,
|
||||
syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc},
|
||||
syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder},
|
||||
ptr::{SyntaxNodePtr, AstPtr},
|
||||
parsing::{tokenize, Token},
|
||||
};
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use std::mem;
|
||||
|
||||
use ra_parser::{TreeSink, ParseError};
|
||||
use rowan::GreenNodeBuilder;
|
||||
|
||||
use crate::{
|
||||
SmolStr, SyntaxError, SyntaxErrorKind, TextUnit, TextRange,
|
||||
SmolStr, SyntaxError, TextUnit, TextRange, SyntaxTreeBuilder,
|
||||
SyntaxKind::{self, *},
|
||||
parsing::Token,
|
||||
syntax_node::{GreenNode, RaTypes},
|
||||
syntax_node::GreenNode,
|
||||
};
|
||||
|
||||
/// Bridges the parser with our specific syntax tree representation.
|
||||
|
@ -19,8 +18,7 @@ pub(crate) struct TextTreeSink<'a> {
|
|||
text_pos: TextUnit,
|
||||
token_pos: usize,
|
||||
state: State,
|
||||
errors: Vec<SyntaxError>,
|
||||
inner: GreenNodeBuilder<RaTypes>,
|
||||
inner: SyntaxTreeBuilder,
|
||||
}
|
||||
|
||||
enum State {
|
||||
|
@ -33,7 +31,7 @@ impl<'a> TreeSink for TextTreeSink<'a> {
|
|||
fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) {
|
||||
match mem::replace(&mut self.state, State::Normal) {
|
||||
State::PendingStart => unreachable!(),
|
||||
State::PendingFinish => self.inner.finish_internal(),
|
||||
State::PendingFinish => self.inner.finish_branch(),
|
||||
State::Normal => (),
|
||||
}
|
||||
self.eat_trivias();
|
||||
|
@ -48,12 +46,12 @@ impl<'a> TreeSink for TextTreeSink<'a> {
|
|||
fn start_branch(&mut self, kind: SyntaxKind) {
|
||||
match mem::replace(&mut self.state, State::Normal) {
|
||||
State::PendingStart => {
|
||||
self.inner.start_internal(kind);
|
||||
self.inner.start_branch(kind);
|
||||
// No need to attach trivias to previous node: there is no
|
||||
// previous node.
|
||||
return;
|
||||
}
|
||||
State::PendingFinish => self.inner.finish_internal(),
|
||||
State::PendingFinish => self.inner.finish_branch(),
|
||||
State::Normal => (),
|
||||
}
|
||||
|
||||
|
@ -73,21 +71,20 @@ impl<'a> TreeSink for TextTreeSink<'a> {
|
|||
n_attached_trivias(kind, leading_trivias)
|
||||
};
|
||||
self.eat_n_trivias(n_trivias - n_attached_trivias);
|
||||
self.inner.start_internal(kind);
|
||||
self.inner.start_branch(kind);
|
||||
self.eat_n_trivias(n_attached_trivias);
|
||||
}
|
||||
|
||||
fn finish_branch(&mut self) {
|
||||
match mem::replace(&mut self.state, State::PendingFinish) {
|
||||
State::PendingStart => unreachable!(),
|
||||
State::PendingFinish => self.inner.finish_internal(),
|
||||
State::PendingFinish => self.inner.finish_branch(),
|
||||
State::Normal => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn error(&mut self, error: ParseError) {
|
||||
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), self.text_pos);
|
||||
self.errors.push(error)
|
||||
self.inner.error(error, self.text_pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,8 +96,7 @@ impl<'a> TextTreeSink<'a> {
|
|||
text_pos: 0.into(),
|
||||
token_pos: 0,
|
||||
state: State::PendingStart,
|
||||
errors: Vec::new(),
|
||||
inner: GreenNodeBuilder::new(),
|
||||
inner: SyntaxTreeBuilder::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,12 +104,12 @@ impl<'a> TextTreeSink<'a> {
|
|||
match mem::replace(&mut self.state, State::Normal) {
|
||||
State::PendingFinish => {
|
||||
self.eat_trivias();
|
||||
self.inner.finish_internal()
|
||||
self.inner.finish_branch()
|
||||
}
|
||||
State::PendingStart | State::Normal => unreachable!(),
|
||||
}
|
||||
|
||||
(self.inner.finish(), self.errors)
|
||||
self.inner.finish_raw()
|
||||
}
|
||||
|
||||
fn eat_trivias(&mut self) {
|
||||
|
|
|
@ -11,11 +11,12 @@ use std::{
|
|||
borrow::Borrow,
|
||||
};
|
||||
|
||||
use rowan::{Types, TransparentNewType};
|
||||
use ra_parser::ParseError;
|
||||
use rowan::{Types, TransparentNewType, GreenNodeBuilder};
|
||||
|
||||
use crate::{
|
||||
SmolStr, SyntaxKind, TextRange, SyntaxText, SourceFile, AstNode,
|
||||
syntax_error::SyntaxError,
|
||||
SmolStr, SyntaxKind, TextUnit, TextRange, SyntaxText, SourceFile, AstNode,
|
||||
syntax_error::{SyntaxError, SyntaxErrorKind},
|
||||
};
|
||||
|
||||
pub use rowan::WalkEvent;
|
||||
|
@ -276,3 +277,47 @@ fn has_short_text(kind: SyntaxKind) -> bool {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyntaxTreeBuilder {
|
||||
errors: Vec<SyntaxError>,
|
||||
inner: GreenNodeBuilder<RaTypes>,
|
||||
}
|
||||
|
||||
impl Default for SyntaxTreeBuilder {
|
||||
fn default() -> SyntaxTreeBuilder {
|
||||
SyntaxTreeBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl SyntaxTreeBuilder {
|
||||
pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
|
||||
let green = self.inner.finish();
|
||||
(green, self.errors)
|
||||
}
|
||||
|
||||
pub fn finish(self) -> TreeArc<SyntaxNode> {
|
||||
let (green, errors) = self.finish_raw();
|
||||
let node = SyntaxNode::new(green, errors);
|
||||
if cfg!(debug_assertions) {
|
||||
crate::validation::validate_block_structure(&node);
|
||||
}
|
||||
node
|
||||
}
|
||||
|
||||
pub fn leaf(&mut self, kind: SyntaxKind, text: SmolStr) {
|
||||
self.inner.leaf(kind, text)
|
||||
}
|
||||
|
||||
pub fn start_branch(&mut self, kind: SyntaxKind) {
|
||||
self.inner.start_internal(kind)
|
||||
}
|
||||
|
||||
pub fn finish_branch(&mut self) {
|
||||
self.inner.finish_internal()
|
||||
}
|
||||
|
||||
pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
|
||||
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos);
|
||||
self.errors.push(error)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue