mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
Smart eof for blocks
This commit is contained in:
parent
8671a892c5
commit
f797c81155
7 changed files with 70 additions and 14 deletions
|
@ -74,7 +74,7 @@ fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
|
||||||
fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
|
fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
|
||||||
many(p, |p| {
|
many(p, |p| {
|
||||||
f(p);
|
f(p);
|
||||||
p.expect(COMMA)
|
p.is_eof() || p.expect(COMMA)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,14 @@ impl<'p> Parser<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
|
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
|
||||||
self.current_is(kind) && { self.bump(); true }
|
if self.current_is(kind) {
|
||||||
|
self.bump();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
self.error()
|
||||||
|
.message(format!("expected {:?}", kind))
|
||||||
|
.emit();
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,7 +10,10 @@ pub(crate) enum Event {
|
||||||
Token {
|
Token {
|
||||||
kind: SyntaxKind,
|
kind: SyntaxKind,
|
||||||
n_raw_tokens: u8,
|
n_raw_tokens: u8,
|
||||||
}
|
},
|
||||||
|
Error {
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse<'t>(text: &'t str, raw_tokens: &'t [Token]) -> Vec<Event> {
|
pub(crate) fn parse<'t>(text: &'t str, raw_tokens: &'t [Token]) -> Vec<Event> {
|
||||||
|
|
|
@ -10,7 +10,9 @@ pub struct Parser<'t> {
|
||||||
|
|
||||||
pos: usize,
|
pos: usize,
|
||||||
events: Vec<Event>,
|
events: Vec<Event>,
|
||||||
|
|
||||||
curly_level: i32,
|
curly_level: i32,
|
||||||
|
curly_limit: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parser<'t> {
|
impl<'t> Parser<'t> {
|
||||||
|
@ -32,6 +34,7 @@ impl<'t> Parser<'t> {
|
||||||
pos: 0,
|
pos: 0,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
curly_level: 0,
|
curly_level: 0,
|
||||||
|
curly_limit: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +44,14 @@ impl<'t> Parser<'t> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_eof(&self) -> bool {
|
pub(crate) fn is_eof(&self) -> bool {
|
||||||
self.pos == self.non_ws_tokens.len()
|
if self.pos == self.non_ws_tokens.len() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if let Some(limit) = self.curly_limit {
|
||||||
|
let idx = self.non_ws_tokens[self.pos].0;
|
||||||
|
return limit == self.curly_level && self.raw_tokens[idx].kind == R_CURLY;
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start(&mut self, kind: SyntaxKind) {
|
pub(crate) fn start(&mut self, kind: SyntaxKind) {
|
||||||
|
@ -52,6 +62,10 @@ impl<'t> Parser<'t> {
|
||||||
self.event(Event::Finish);
|
self.event(Event::Finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn error<'p>(&'p mut self) -> ErrorBuilder<'p, 't> {
|
||||||
|
ErrorBuilder::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn current(&self) -> Option<SyntaxKind> {
|
pub(crate) fn current(&self) -> Option<SyntaxKind> {
|
||||||
if self.is_eof() {
|
if self.is_eof() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -73,15 +87,18 @@ impl<'t> Parser<'t> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool {
|
pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool {
|
||||||
let level = self.curly_level;
|
let old_level = self.curly_level;
|
||||||
|
let old_limit = self.curly_limit;
|
||||||
if !self.expect(L_CURLY) {
|
if !self.expect(L_CURLY) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
self.curly_limit = Some(self.curly_level);
|
||||||
f(self);
|
f(self);
|
||||||
assert!(self.curly_level > level);
|
assert!(self.curly_level > old_level);
|
||||||
|
self.curly_limit = old_limit;
|
||||||
if !self.expect(R_CURLY) {
|
if !self.expect(R_CURLY) {
|
||||||
self.start(ERROR);
|
self.start(ERROR);
|
||||||
while self.curly_level > level {
|
while self.curly_level > old_level {
|
||||||
if self.bump().is_none() {
|
if self.bump().is_none() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -94,4 +111,25 @@ impl<'t> Parser<'t> {
|
||||||
fn event(&mut self, event: Event) {
|
fn event(&mut self, event: Event) {
|
||||||
self.events.push(event)
|
self.events.push(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct ErrorBuilder<'p, 't: 'p> {
|
||||||
|
message: Option<String>,
|
||||||
|
parser: &'p mut Parser<'t>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t, 'p> ErrorBuilder<'p, 't> {
|
||||||
|
fn new(parser: &'p mut Parser<'t>) -> Self {
|
||||||
|
ErrorBuilder { message: None, parser }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message<M: Into<String>>(mut self, m: M) -> Self {
|
||||||
|
self.message = Some(m.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emit(self) {
|
||||||
|
let message = self.message.expect("Error message not set");
|
||||||
|
self.parser.event(Event::Error { message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ fn from_events_to_file(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Event::Error { message } => builder.error().message(message).emit(),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.finish()
|
builder.finish()
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl<'f> ErrorBuilder<'f> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) {
|
pub fn emit(self) {
|
||||||
let message = self.message.expect("Error message not set");
|
let message = self.message.expect("Error message not set");
|
||||||
let node = self.builder.current_id();
|
let node = self.builder.current_id();
|
||||||
self.builder.errors.push(SyntaxErrorData { node, message })
|
self.builder.errors.push(SyntaxErrorData { node, message })
|
||||||
|
|
|
@ -73,7 +73,7 @@ impl<'f> Node<'f> {
|
||||||
Children { next: self.as_node(self.data().first_child) }
|
Children { next: self.as_node(self.data().first_child) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn SyntaxErrors(&self) -> SyntaxErrors<'f> {
|
pub fn errors(&self) -> SyntaxErrors<'f> {
|
||||||
let pos = self.file.errors.iter().position(|e| e.node == self.idx);
|
let pos = self.file.errors.iter().position(|e| e.node == self.idx);
|
||||||
let next = pos
|
let next = pos
|
||||||
.map(|i| ErrorIdx(i as u32))
|
.map(|i| ErrorIdx(i as u32))
|
||||||
|
@ -112,12 +112,13 @@ impl<'f> SyntaxError<'f> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(&self) -> Option<SyntaxError<'f>> {
|
fn next(&self) -> Option<SyntaxError<'f>> {
|
||||||
if self.file.errors.len() == self.idx.0 as usize {
|
let next_idx = self.idx.0 + 1;
|
||||||
|
if !((next_idx as usize) < self.file.errors.len()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let result = SyntaxError {
|
let result = SyntaxError {
|
||||||
file: self.file,
|
file: self.file,
|
||||||
idx: ErrorIdx(self.idx.0 + 1)
|
idx: ErrorIdx(next_idx)
|
||||||
};
|
};
|
||||||
if result.data().node != self.data().node {
|
if result.data().node != self.data().node {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -61,8 +61,12 @@ fn dump_tree(file: &File) -> String {
|
||||||
|
|
||||||
fn go(node: Node, buff: &mut String, level: usize) {
|
fn go(node: Node, buff: &mut String, level: usize) {
|
||||||
buff.push_str(&String::from(" ").repeat(level));
|
buff.push_str(&String::from(" ").repeat(level));
|
||||||
write!(buff, "{:?}\n", node)
|
write!(buff, "{:?}", node).unwrap();
|
||||||
.unwrap();
|
for err in node.errors() {
|
||||||
|
write!(buff, " err: `{}`", err.message()).unwrap();
|
||||||
|
}
|
||||||
|
write!(buff, "\n").unwrap();
|
||||||
|
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
go(child, buff, level + 1)
|
go(child, buff, level + 1)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue