Introduce Location and make SyntaxError fields private

This commit is contained in:
Adolfo Ochagavía 2018-11-05 18:38:34 +01:00
parent 3b42ddae60
commit fda8ddc5fe
10 changed files with 82 additions and 52 deletions

View File

@ -31,6 +31,7 @@ use ra_syntax::{
algo::find_leaf_at_offset,
ast::{self, AstNode, NameOwner},
File,
Location,
SyntaxKind::{self, *},
SyntaxNodeRef, TextRange, TextUnit,
};
@ -100,11 +101,18 @@ pub fn highlight(file: &File) -> Vec<HighlightedRange> {
}
pub fn diagnostics(file: &File) -> Vec<Diagnostic> {
fn location_to_range(location: Location) -> TextRange {
match location {
Location::Offset(offset) => TextRange::offset_len(offset, 1.into()),
Location::Range(range) => range,
}
}
file.errors()
.into_iter()
.map(|err| Diagnostic {
range: err.range,
msg: format!("Syntax Error: {}", err.kind),
range: location_to_range(err.location()),
msg: format!("Syntax Error: {}", err),
})
.collect()
}

View File

@ -54,7 +54,7 @@ pub use crate::{
rowan::{SmolStr, TextRange, TextUnit},
syntax_kinds::SyntaxKind,
yellow::{
Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent,
Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent, Location,
},
};

View File

@ -15,6 +15,7 @@ use crate::{
TextRange, TextUnit,
yellow::syntax_error::{
ParseError,
SyntaxError,
SyntaxErrorKind,
},
};
@ -162,8 +163,7 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
self.leaf(kind, len, n_raw_tokens);
}
Event::Error { msg } => self.sink.error(
SyntaxErrorKind::ParseError(msg),
TextRange::offset_len(self.text_pos, 1.into()),
SyntaxError::new(SyntaxErrorKind::ParseError(msg), self.text_pos),
),
}
}

View File

@ -10,10 +10,10 @@ use crate::{
event::{Event, EventProcessor},
input::{InputPosition, ParserInput},
},
SmolStr, TextRange,
SmolStr,
yellow::syntax_error::{
ParseError,
SyntaxErrorKind,
SyntaxError,
},
};
@ -25,7 +25,7 @@ pub(crate) trait Sink {
fn leaf(&mut self, kind: SyntaxKind, text: SmolStr);
fn start_internal(&mut self, kind: SyntaxKind);
fn finish_internal(&mut self);
fn error(&mut self, kind: SyntaxErrorKind, offset: TextRange);
fn error(&mut self, error: SyntaxError);
fn finish(self) -> Self::Tree;
}

View File

@ -165,20 +165,14 @@ fn merge_errors(
) -> Vec<SyntaxError> {
let mut res = Vec::new();
for e in old_errors {
if e.range.start() <= old_node.range().start() {
if e.offset() <= old_node.range().start() {
res.push(e)
} else if e.range.start() >= old_node.range().end() {
res.push(SyntaxError {
kind: e.kind,
range: e.range + TextUnit::of_str(&edit.insert) - edit.delete.len(),
})
} else if e.offset() >= old_node.range().end() {
res.push(e.add_offset(TextUnit::of_str(&edit.insert) - edit.delete.len()));
}
}
for e in new_errors {
res.push(SyntaxError {
kind: e.kind,
range: e.range + old_node.range().start(),
})
res.push(e.add_offset(old_node.range().start()));
}
res
}

View File

@ -4,7 +4,7 @@ use std::fmt::Write;
/// Parse a file and create a string representation of the resulting parse tree.
pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
let mut errors: Vec<_> = syntax.root_data().to_vec();
errors.sort_by_key(|e| e.range.start());
errors.sort_by_key(|e| e.offset());
let mut err_pos = 0;
let mut level = 0;
let mut buf = String::new();
@ -23,9 +23,9 @@ pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
writeln!(buf, "{:?}", node).unwrap();
if node.first_child().is_none() {
let off = node.range().end();
while err_pos < errors.len() && errors[err_pos].range.start() <= off {
while err_pos < errors.len() && errors[err_pos].offset() <= off {
indent!();
writeln!(buf, "err: `{}`", errors[err_pos].kind).unwrap();
writeln!(buf, "err: `{}`", errors[err_pos]).unwrap();
err_pos += 1;
}
}
@ -37,7 +37,7 @@ pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
assert_eq!(level, 0);
for err in errors[err_pos..].iter() {
writeln!(buf, "err: `{}`", err.kind).unwrap();
writeln!(buf, "err: `{}`", err).unwrap();
}
buf

View File

@ -33,17 +33,11 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
AsciiEscape => {
if text.len() == 1 {
// Escape sequence consists only of leading `\`
errors.push(SyntaxError {
kind: EmptyAsciiEscape,
range: range,
});
errors.push(SyntaxError::new(EmptyAsciiEscape, range));
} else {
let escape_code = text.chars().skip(1).next().unwrap();
if !is_ascii_escape(escape_code) {
errors.push(SyntaxError {
kind: InvalidAsciiEscape,
range: range,
});
errors.push(SyntaxError::new(InvalidAsciiEscape, range));
}
}
}
@ -64,24 +58,15 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
}
if !components.has_closing_quote {
errors.push(SyntaxError {
kind: UnclosedChar,
range: node.syntax().range(),
});
errors.push(SyntaxError::new(UnclosedChar, node.syntax().range()));
}
if len == 0 {
errors.push(SyntaxError {
kind: EmptyChar,
range: node.syntax().range(),
});
errors.push(SyntaxError::new(EmptyChar, node.syntax().range()));
}
if len > 1 {
errors.push(SyntaxError {
kind: LongChar,
range: node.syntax().range(),
});
errors.push(SyntaxError::new(LongChar, node.syntax().range()));
}
}

View File

@ -1,7 +1,7 @@
use crate::{
parser_impl::Sink,
yellow::{GreenNode, RaTypes, SyntaxError, SyntaxErrorKind},
SmolStr, SyntaxKind, TextRange,
yellow::{GreenNode, RaTypes, SyntaxError},
SmolStr, SyntaxKind,
};
use rowan::GreenNodeBuilder;
@ -34,8 +34,7 @@ impl Sink for GreenBuilder {
self.inner.finish_internal();
}
fn error(&mut self, kind: SyntaxErrorKind, range: TextRange) {
let error = SyntaxError { kind, range };
fn error(&mut self, error: SyntaxError) {
self.errors.push(error)
}

View File

@ -11,7 +11,7 @@ use std::{
};
pub(crate) use self::builder::GreenBuilder;
pub use self::syntax_error::{SyntaxError, SyntaxErrorKind};
pub use self::syntax_error::{SyntaxError, SyntaxErrorKind, Location};
pub use rowan::{TreeRoot, WalkEvent};
#[derive(Debug, Clone, Copy)]

View File

@ -1,16 +1,60 @@
use std::fmt;
use crate::TextRange;
use crate::{TextRange, TextUnit};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxError {
pub kind: SyntaxErrorKind,
pub range: TextRange,
kind: SyntaxErrorKind,
location: Location,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Location {
Offset(TextUnit),
Range(TextRange),
}
impl Into<Location> for TextUnit {
fn into(self) -> Location {
Location::Offset(self)
}
}
impl Into<Location> for TextRange {
fn into(self) -> Location {
Location::Range(self)
}
}
impl SyntaxError {
pub fn new(kind: SyntaxErrorKind, range: TextRange) -> SyntaxError {
SyntaxError { kind, range }
pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError {
SyntaxError { kind, location: loc.into() }
}
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)
}
}