mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Error placement
This commit is contained in:
parent
efcfaae34a
commit
18f9e50b2d
4 changed files with 37 additions and 9 deletions
|
@ -156,7 +156,7 @@ impl<'f> ErrorBuilder<'f> {
|
||||||
|
|
||||||
pub fn emit(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, after_child) = self.builder.in_progress.last().unwrap();
|
||||||
self.builder.errors.push(SyntaxErrorData { node, message })
|
self.builder.errors.push(SyntaxErrorData { node, message, after_child })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use text::{TextUnit, TextRange};
|
||||||
use syntax_kinds::syntax_info;
|
use syntax_kinds::syntax_info;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
mod file_builder;
|
mod file_builder;
|
||||||
pub use self::file_builder::{FileBuilder, Sink};
|
pub use self::file_builder::{FileBuilder, Sink};
|
||||||
|
@ -96,6 +97,15 @@ impl<'f> fmt::Debug for Node<'f> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'f> cmp::PartialEq<Node<'f>> for Node<'f> {
|
||||||
|
fn eq(&self, other: &Node<'f>) -> bool {
|
||||||
|
self.idx == other.idx && ::std::ptr::eq(self.file, other.file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'f> cmp::Eq for Node<'f> {
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct SyntaxError<'f> {
|
pub struct SyntaxError<'f> {
|
||||||
file: &'f File,
|
file: &'f File,
|
||||||
|
@ -107,6 +117,11 @@ impl<'f> SyntaxError<'f> {
|
||||||
self.data().message.as_str()
|
self.data().message.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn after_child(&self) -> Option<Node<'f>> {
|
||||||
|
let idx = self.data().after_child?;
|
||||||
|
Some(Node { file: self.file, idx })
|
||||||
|
}
|
||||||
|
|
||||||
fn data(&self) -> &'f SyntaxErrorData {
|
fn data(&self) -> &'f SyntaxErrorData {
|
||||||
&self.file.errors[self.idx]
|
&self.file.errors[self.idx]
|
||||||
}
|
}
|
||||||
|
@ -187,6 +202,7 @@ struct ErrorIdx(u32);
|
||||||
struct SyntaxErrorData {
|
struct SyntaxErrorData {
|
||||||
node: NodeIdx,
|
node: NodeIdx,
|
||||||
message: String,
|
message: String,
|
||||||
|
after_child: Option<NodeIdx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> {
|
impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
FILE@[0; 34)
|
FILE@[0; 34)
|
||||||
STRUCT_ITEM@[0; 34) err: `expected COMMA`
|
STRUCT_ITEM@[0; 34)
|
||||||
STRUCT_KW@[0; 6)
|
STRUCT_KW@[0; 6)
|
||||||
WHITESPACE@[6; 7)
|
WHITESPACE@[6; 7)
|
||||||
IDENT@[7; 8)
|
IDENT@[7; 8)
|
||||||
|
@ -12,9 +12,11 @@ FILE@[0; 34)
|
||||||
WHITESPACE@[17; 18)
|
WHITESPACE@[17; 18)
|
||||||
IDENT@[18; 21)
|
IDENT@[18; 21)
|
||||||
WHITESPACE@[21; 26)
|
WHITESPACE@[21; 26)
|
||||||
|
err: `expected COMMA`
|
||||||
STRUCT_FIELD@[26; 33)
|
STRUCT_FIELD@[26; 33)
|
||||||
IDENT@[26; 27)
|
IDENT@[26; 27)
|
||||||
COLON@[27; 28)
|
COLON@[27; 28)
|
||||||
WHITESPACE@[28; 29)
|
WHITESPACE@[28; 29)
|
||||||
IDENT@[29; 32)
|
IDENT@[29; 32)
|
||||||
WHITESPACE@[32;
|
WHITESPACE@[32; 33)
|
||||||
|
R_CURLY@[33; 34)
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::path::{PathBuf, Path};
|
||||||
use std::fs::read_dir;
|
use std::fs::read_dir;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use libsyntax2::{tokenize, parse, Token, Node, File, FileBuilder};
|
use libsyntax2::{tokenize, parse, Node, File};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parser_tests() {
|
fn parser_tests() {
|
||||||
|
@ -70,14 +70,24 @@ 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, "{:?}", node).unwrap();
|
write!(buff, "{:?}\n", node).unwrap();
|
||||||
for err in node.errors() {
|
let my_errors = node.errors().filter(|e| e.after_child().is_none());
|
||||||
write!(buff, " err: `{}`", err.message()).unwrap();
|
let parent_errors = node.parent().into_iter()
|
||||||
|
.flat_map(|n| n.errors())
|
||||||
|
.filter(|e| e.after_child() == Some(node));
|
||||||
|
|
||||||
|
for err in my_errors {
|
||||||
|
buff.push_str(&String::from(" ").repeat(level));
|
||||||
|
write!(buff, "err: `{}`\n", 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for err in parent_errors {
|
||||||
|
buff.push_str(&String::from(" ").repeat(level));
|
||||||
|
write!(buff, "err: `{}`\n", err.message()).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue