diff options
| author | David Wood <david@davidtw.co> | 2018-01-14 17:29:07 +0000 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2018-01-27 11:46:27 +0000 |
| commit | c71cec8834bf30032a8e49d2949f6d8d4080b639 (patch) | |
| tree | 49dc11292d287459c01aeddbd4c40240de9b2e16 /src/libsyntax | |
| parent | c6e6428d1a13f61f5ffbe43697a21f3cd82cd01d (diff) | |
| download | rust-c71cec8834bf30032a8e49d2949f6d8d4080b639.tar.gz rust-c71cec8834bf30032a8e49d2949f6d8d4080b639.zip | |
end_point handling multibyte characters correctly.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/codemap.rs | 37 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 8 |
2 files changed, 42 insertions, 3 deletions
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index a58a61c3636..e74066da0ac 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -25,6 +25,7 @@ pub use self::ExpnFormat::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use std::cell::{RefCell, Ref}; +use std::cmp; use std::hash::Hash; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -607,6 +608,42 @@ impl CodeMap { self.span_until_char(sp, '{') } + /// Returns a new span representing just the end-point of this span + pub fn end_point(&self, sp: Span) -> Span { + let hi = sp.hi().0.checked_sub(1).unwrap_or(sp.hi().0); + let hi = self.get_start_of_char_bytepos(BytePos(hi)); + let lo = cmp::max(hi.0, sp.lo().0); + sp.with_lo(BytePos(lo)) + } + + /// Returns a new span representing the next character after the end-point of this span + pub fn next_point(&self, sp: Span) -> Span { + let hi = sp.lo().0.checked_add(1).unwrap_or(sp.lo().0); + let hi = self.get_start_of_char_bytepos(BytePos(hi)); + let lo = cmp::max(sp.hi().0, hi.0); + Span::new(BytePos(lo), BytePos(lo), sp.ctxt()) + } + + fn get_start_of_char_bytepos(&self, bpos: BytePos) -> BytePos { + let idx = self.lookup_filemap_idx(bpos); + let files = self.files.borrow(); + let map = &(*files)[idx]; + + for mbc in map.multibyte_chars.borrow().iter() { + if mbc.pos < bpos { + if bpos.to_usize() >= mbc.pos.to_usize() + mbc.bytes { + // If we do, then return the start of the character. + return mbc.pos; + } + } else { + break; + } + } + + // If this isn't a multibyte character, return the original position. + return bpos; + } + pub fn get_filemap(&self, filename: &FileName) -> Option<Rc<FileMap>> { for fm in self.files.borrow().iter() { if *filename == fm.name { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d393cab4718..e8e87e2854b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -704,13 +704,15 @@ impl<'a> Parser<'a> { expect.clone() }; (format!("expected one of {}, found `{}`", expect, actual), - (self.prev_span.next_point(), format!("expected one of {} here", short_expect))) + (self.sess.codemap().next_point(self.prev_span), + format!("expected one of {} here", short_expect))) } else if expected.is_empty() { (format!("unexpected token: `{}`", actual), (self.prev_span, "unexpected token after this".to_string())) } else { (format!("expected {}, found `{}`", expect, actual), - (self.prev_span.next_point(), format!("expected {} here", expect))) + (self.sess.codemap().next_point(self.prev_span), + format!("expected {} here", expect))) }; let mut err = self.fatal(&msg_exp); let sp = if self.token == token::Token::Eof { @@ -3190,7 +3192,7 @@ impl<'a> Parser<'a> { // return. This won't catch blocks with an explicit `return`, but that would be caught by // the dead code lint. if self.eat_keyword(keywords::Else) || !cond.returns() { - let sp = lo.next_point(); + let sp = self.sess.codemap().next_point(lo); let mut err = self.diagnostic() .struct_span_err(sp, "missing condition for `if` statemement"); err.span_label(sp, "expected if condition here"); |
