mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
commit
419b9b7e5e
12 changed files with 49 additions and 70 deletions
|
@ -25,7 +25,7 @@ mod parser;
|
||||||
pub mod syntax_kinds;
|
pub mod syntax_kinds;
|
||||||
pub use text::{TextRange, TextUnit};
|
pub use text::{TextRange, TextUnit};
|
||||||
pub use tree::{File, Node, SyntaxKind, Token};
|
pub use tree::{File, Node, SyntaxKind, Token};
|
||||||
pub(crate) use tree::{FileBuilder, Sink};
|
pub(crate) use tree::{ErrorMsg, FileBuilder, Sink};
|
||||||
pub use lexer::{next_token, tokenize};
|
pub use lexer::{next_token, tokenize};
|
||||||
pub use parser::parse;
|
pub use parser::parse;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use {File, FileBuilder, Sink, SyntaxKind, TextUnit, Token};
|
use {ErrorMsg, File, FileBuilder, Sink, SyntaxKind, TextUnit, Token};
|
||||||
use syntax_kinds::TOMBSTONE;
|
use syntax_kinds::TOMBSTONE;
|
||||||
use super::is_insignificant;
|
use super::is_insignificant;
|
||||||
|
|
||||||
|
@ -140,7 +140,9 @@ pub(super) fn to_file(text: String, tokens: &[Token], events: Vec<Event>) -> Fil
|
||||||
}
|
}
|
||||||
builder.leaf(kind, len);
|
builder.leaf(kind, len);
|
||||||
}
|
}
|
||||||
&Event::Error { ref message } => builder.error().message(message.clone()).emit(),
|
&Event::Error { ref message } => builder.error(ErrorMsg {
|
||||||
|
message: message.clone(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.finish()
|
builder.finish()
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn meta_item(p: &mut Parser) {
|
||||||
EQ => {
|
EQ => {
|
||||||
p.bump();
|
p.bump();
|
||||||
if !expressions::literal(p) {
|
if !expressions::literal(p) {
|
||||||
p.error().message("expected literal").emit();
|
p.error("expected literal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
L_PAREN => meta_item_arg_list(p),
|
L_PAREN => meta_item_arg_list(p),
|
||||||
|
@ -45,7 +45,7 @@ fn meta_item(p: &mut Parser) {
|
||||||
}
|
}
|
||||||
meta_item.complete(p, META_ITEM);
|
meta_item.complete(p, META_ITEM);
|
||||||
} else {
|
} else {
|
||||||
p.error().message("expected attribute value").emit()
|
p.error("expected attribute value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,12 +60,12 @@ fn meta_item_arg_list(p: &mut Parser) {
|
||||||
let message = "expected attribute";
|
let message = "expected attribute";
|
||||||
|
|
||||||
if items::ITEM_FIRST.contains(c) {
|
if items::ITEM_FIRST.contains(c) {
|
||||||
p.error().message(message).emit();
|
p.error(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let err = p.start();
|
let err = p.start();
|
||||||
p.error().message(message).emit();
|
p.error(message);
|
||||||
p.bump();
|
p.bump();
|
||||||
err.complete(p, ERROR);
|
err.complete(p, ERROR);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -15,6 +15,6 @@ pub(super) fn literal(p: &mut Parser) -> bool {
|
||||||
|
|
||||||
pub(super) fn expr(p: &mut Parser) {
|
pub(super) fn expr(p: &mut Parser) {
|
||||||
if !literal(p) {
|
if !literal(p) {
|
||||||
p.error().message("expected expression").emit();
|
p.error("expected expression");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ fn item(p: &mut Parser) {
|
||||||
// extern struct Foo;
|
// extern struct Foo;
|
||||||
_ => {
|
_ => {
|
||||||
item.abandon(p);
|
item.abandon(p);
|
||||||
p.error().message("expected `fn` or `{`").emit();
|
p.error("expected `fn` or `{`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ fn item(p: &mut Parser) {
|
||||||
abi(p);
|
abi(p);
|
||||||
if !p.at(FN_KW) {
|
if !p.at(FN_KW) {
|
||||||
item.abandon(p);
|
item.abandon(p);
|
||||||
p.error().message("expected function").emit();
|
p.error("expected function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fn_item(p);
|
fn_item(p);
|
||||||
|
@ -144,7 +144,7 @@ fn item(p: &mut Parser) {
|
||||||
if t == L_CURLY {
|
if t == L_CURLY {
|
||||||
error_block(p, message);
|
error_block(p, message);
|
||||||
} else {
|
} else {
|
||||||
p.error().message(message).emit();
|
p.error(message);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ fn fn_item(p: &mut Parser) {
|
||||||
if p.at(L_PAREN) {
|
if p.at(L_PAREN) {
|
||||||
fn_value_parameters(p);
|
fn_value_parameters(p);
|
||||||
} else {
|
} else {
|
||||||
p.error().message("expected function arguments").emit();
|
p.error("expected function arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.at(L_CURLY) {
|
if p.at(L_CURLY) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub(super) fn struct_item(p: &mut Parser) {
|
||||||
L_CURLY => named_fields(p),
|
L_CURLY => named_fields(p),
|
||||||
_ => {
|
_ => {
|
||||||
//TODO: special case `(` error message
|
//TODO: special case `(` error message
|
||||||
p.error().message("expected `;` or `{`").emit();
|
p.error("expected `;` or `{`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ pub(super) fn struct_item(p: &mut Parser) {
|
||||||
p.expect(SEMI);
|
p.expect(SEMI);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
p.error().message("expected `;`, `{`, or `(`").emit();
|
p.error("expected `;`, `{`, or `(`");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn use_tree(p: &mut Parser) {
|
||||||
L_CURLY => nested_trees(p),
|
L_CURLY => nested_trees(p),
|
||||||
_ => {
|
_ => {
|
||||||
// is this unreachable?
|
// is this unreachable?
|
||||||
p.error().message("expected `{` or `*`").emit();
|
p.error("expected `{` or `*`");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ fn alias(p: &mut Parser) -> bool {
|
||||||
fn error_block(p: &mut Parser, message: &str) {
|
fn error_block(p: &mut Parser, message: &str) {
|
||||||
assert!(p.at(L_CURLY));
|
assert!(p.at(L_CURLY));
|
||||||
let err = p.start();
|
let err = p.start();
|
||||||
p.error().message(message).emit();
|
p.error(message);
|
||||||
p.bump();
|
p.bump();
|
||||||
let mut level: u32 = 1;
|
let mut level: u32 = 1;
|
||||||
while level > 0 && !p.at(EOF) {
|
while level > 0 && !p.at(EOF) {
|
||||||
|
@ -74,7 +74,7 @@ impl<'p> Parser<'p> {
|
||||||
|
|
||||||
fn err_and_bump(&mut self, message: &str) {
|
fn err_and_bump(&mut self, message: &str) {
|
||||||
let err = self.start();
|
let err = self.start();
|
||||||
self.error().message(message).emit();
|
self.error(message);
|
||||||
self.bump();
|
self.bump();
|
||||||
err.complete(self, ERROR);
|
err.complete(self, ERROR);
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ impl<'p> Parser<'p> {
|
||||||
self.bump();
|
self.bump();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
self.error().message(format!("expected {:?}", kind)).emit();
|
self.error(format!("expected {:?}", kind));
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,9 @@ fn path_segment(p: &mut Parser, first: bool) {
|
||||||
}
|
}
|
||||||
match p.current() {
|
match p.current() {
|
||||||
IDENT | SELF_KW | SUPER_KW => p.bump(),
|
IDENT | SELF_KW | SUPER_KW => p.bump(),
|
||||||
_ => p.error().message("expected identifier").emit(),
|
_ => {
|
||||||
|
p.error("expected identifier");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
segment.complete(p, PATH_SEGMENT);
|
segment.complete(p, PATH_SEGMENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,8 +129,8 @@ impl<'t> Parser<'t> {
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn error<'p>(&'p mut self) -> ErrorBuilder<'p, 't> {
|
pub(crate) fn error<'p, T: Into<String>>(&'p mut self, msg: T) -> ErrorBuilder<'p, 't> {
|
||||||
ErrorBuilder::new(self)
|
ErrorBuilder::new(self, msg.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn bump(&mut self) {
|
pub(crate) fn bump(&mut self) {
|
||||||
|
@ -175,25 +175,19 @@ impl<'t> Parser<'t> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct ErrorBuilder<'p, 't: 'p> {
|
pub(crate) struct ErrorBuilder<'p, 't: 'p> {
|
||||||
message: Option<String>,
|
message: String,
|
||||||
parser: &'p mut Parser<'t>,
|
parser: &'p mut Parser<'t>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t, 'p> ErrorBuilder<'p, 't> {
|
impl<'p, 't: 'p> Drop for ErrorBuilder<'p, 't> {
|
||||||
fn new(parser: &'p mut Parser<'t>) -> Self {
|
fn drop(&mut self) {
|
||||||
ErrorBuilder {
|
let message = ::std::mem::replace(&mut self.message, String::new());
|
||||||
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 });
|
self.parser.event(Event::Error { message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'t, 'p> ErrorBuilder<'p, 't> {
|
||||||
|
fn new(parser: &'p mut Parser<'t>, message: String) -> Self {
|
||||||
|
ErrorBuilder { message, parser }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub(crate) trait Sink {
|
||||||
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
|
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
|
||||||
fn start_internal(&mut self, kind: SyntaxKind);
|
fn start_internal(&mut self, kind: SyntaxKind);
|
||||||
fn finish_internal(&mut self);
|
fn finish_internal(&mut self);
|
||||||
fn error(&mut self) -> ErrorBuilder;
|
fn error(&mut self, err: ErrorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -22,7 +22,8 @@ pub(crate) struct FileBuilder {
|
||||||
text: String,
|
text: String,
|
||||||
nodes: Vec<NodeData>,
|
nodes: Vec<NodeData>,
|
||||||
errors: Vec<SyntaxErrorData>,
|
errors: Vec<SyntaxErrorData>,
|
||||||
in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child)
|
in_progress: Vec<(NodeIdx, Option<NodeIdx>)>,
|
||||||
|
// (parent, last_child)
|
||||||
pos: TextUnit,
|
pos: TextUnit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +66,13 @@ impl Sink for FileBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self) -> ErrorBuilder {
|
fn error(&mut self, err: ErrorMsg) {
|
||||||
ErrorBuilder::new(self)
|
let &(node, after_child) = self.in_progress.last().unwrap();
|
||||||
|
self.errors.push(SyntaxErrorData {
|
||||||
|
node,
|
||||||
|
message: err.message,
|
||||||
|
after_child,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,32 +155,7 @@ fn grow(left: &mut TextRange, right: TextRange) {
|
||||||
*left = TextRange::from_to(left.start(), right.end())
|
*left = TextRange::from_to(left.start(), right.end())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Default)]
|
||||||
pub struct ErrorBuilder<'f> {
|
pub(crate) struct ErrorMsg {
|
||||||
message: Option<String>,
|
pub(crate) message: String,
|
||||||
builder: &'f mut FileBuilder,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'f> ErrorBuilder<'f> {
|
|
||||||
fn new(builder: &'f mut FileBuilder) -> Self {
|
|
||||||
ErrorBuilder {
|
|
||||||
message: None,
|
|
||||||
builder,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
let &(node, after_child) = self.builder.in_progress.last().unwrap();
|
|
||||||
self.builder.errors.push(SyntaxErrorData {
|
|
||||||
node,
|
|
||||||
message,
|
|
||||||
after_child,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
mod file_builder;
|
mod file_builder;
|
||||||
pub(crate) use self::file_builder::{FileBuilder, Sink};
|
pub(crate) use self::file_builder::{ErrorMsg, FileBuilder, Sink};
|
||||||
|
|
||||||
pub use syntax_kinds::SyntaxKind;
|
pub use syntax_kinds::SyntaxKind;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue