From fda8ddc5fe8a764c0dc91fecb92af1bdf3078485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Mon, 5 Nov 2018 18:38:34 +0100 Subject: [PATCH] Introduce Location and make SyntaxError fields private --- crates/ra_editor/src/lib.rs | 12 ++++- crates/ra_syntax/src/lib.rs | 2 +- crates/ra_syntax/src/parser_impl/event.rs | 4 +- crates/ra_syntax/src/parser_impl/mod.rs | 6 +-- crates/ra_syntax/src/reparsing.rs | 14 ++---- crates/ra_syntax/src/utils.rs | 8 +-- crates/ra_syntax/src/validation.rs | 25 ++-------- crates/ra_syntax/src/yellow/builder.rs | 7 ++- crates/ra_syntax/src/yellow/mod.rs | 2 +- crates/ra_syntax/src/yellow/syntax_error.rs | 54 +++++++++++++++++++-- 10 files changed, 82 insertions(+), 52 deletions(-) diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index 25124dbe3de..f92181b867c 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -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 { } pub fn diagnostics(file: &File) -> Vec { + 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() } diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 8996eb92103..69a679d04aa 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -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, }, }; diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index ced09bcffe4..1445401bcf7 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs @@ -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), ), } } diff --git a/crates/ra_syntax/src/parser_impl/mod.rs b/crates/ra_syntax/src/parser_impl/mod.rs index ade25770b9a..cb6e370ac51 100644 --- a/crates/ra_syntax/src/parser_impl/mod.rs +++ b/crates/ra_syntax/src/parser_impl/mod.rs @@ -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; } diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index 9f5baf1ef55..3c4ea5c22b7 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs @@ -165,20 +165,14 @@ fn merge_errors( ) -> Vec { 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 } diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index f55568d94bc..288d7edd4e8 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs @@ -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 diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 06e6e75056d..009f5052f92 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs @@ -33,17 +33,11 @@ fn validate_char(node: ast::Char, errors: &mut Vec) { 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) { } 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())); } } diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs index dbe2df12592..9fcebfb93b9 100644 --- a/crates/ra_syntax/src/yellow/builder.rs +++ b/crates/ra_syntax/src/yellow/builder.rs @@ -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) } diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs index fd2b5bd3374..6da9486489d 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow/mod.rs @@ -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)] diff --git a/crates/ra_syntax/src/yellow/syntax_error.rs b/crates/ra_syntax/src/yellow/syntax_error.rs index e8c818dc69a..098366f857a 100644 --- a/crates/ra_syntax/src/yellow/syntax_error.rs +++ b/crates/ra_syntax/src/yellow/syntax_error.rs @@ -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 for TextUnit { + fn into(self) -> Location { + Location::Offset(self) + } +} + +impl Into 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>(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) } }