Make FileMap::{lines, multibyte_chars, non_narrow_chars} non-mutable.
This commit is contained in:
parent
c20824323c
commit
257d279fe4
6 changed files with 121 additions and 138 deletions
|
@ -455,27 +455,21 @@ impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
|
||||||
src_hash.hash_stable(hcx, hasher);
|
src_hash.hash_stable(hcx, hasher);
|
||||||
|
|
||||||
// We only hash the relative position within this filemap
|
// We only hash the relative position within this filemap
|
||||||
lines.with_lock(|lines| {
|
|
||||||
lines.len().hash_stable(hcx, hasher);
|
lines.len().hash_stable(hcx, hasher);
|
||||||
for &line in lines.iter() {
|
for &line in lines.iter() {
|
||||||
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
|
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// We only hash the relative position within this filemap
|
// We only hash the relative position within this filemap
|
||||||
multibyte_chars.with_lock(|multibyte_chars| {
|
|
||||||
multibyte_chars.len().hash_stable(hcx, hasher);
|
multibyte_chars.len().hash_stable(hcx, hasher);
|
||||||
for &char_pos in multibyte_chars.iter() {
|
for &char_pos in multibyte_chars.iter() {
|
||||||
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
|
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
non_narrow_chars.with_lock(|non_narrow_chars| {
|
|
||||||
non_narrow_chars.len().hash_stable(hcx, hasher);
|
non_narrow_chars.len().hash_stable(hcx, hasher);
|
||||||
for &char_pos in non_narrow_chars.iter() {
|
for &char_pos in non_narrow_chars.iter() {
|
||||||
stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
|
stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -623,7 +623,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
|
||||||
let len = BytePos::decode(self)?;
|
let len = BytePos::decode(self)?;
|
||||||
|
|
||||||
let file_lo = self.file_index_to_file(file_lo_index);
|
let file_lo = self.file_index_to_file(file_lo_index);
|
||||||
let lo = file_lo.lines.borrow()[line_lo - 1] + col_lo;
|
let lo = file_lo.lines[line_lo - 1] + col_lo;
|
||||||
let hi = lo + len;
|
let hi = lo + len;
|
||||||
|
|
||||||
let expn_info_tag = u8::decode(self)?;
|
let expn_info_tag = u8::decode(self)?;
|
||||||
|
|
|
@ -1138,9 +1138,9 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
src_hash,
|
src_hash,
|
||||||
start_pos,
|
start_pos,
|
||||||
end_pos,
|
end_pos,
|
||||||
lines,
|
mut lines,
|
||||||
multibyte_chars,
|
mut multibyte_chars,
|
||||||
non_narrow_chars,
|
mut non_narrow_chars,
|
||||||
name_hash,
|
name_hash,
|
||||||
.. } = filemap_to_import;
|
.. } = filemap_to_import;
|
||||||
|
|
||||||
|
@ -1151,15 +1151,12 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
// `CodeMap::new_imported_filemap()` will then translate those
|
// `CodeMap::new_imported_filemap()` will then translate those
|
||||||
// coordinates to their new global frame of reference when the
|
// coordinates to their new global frame of reference when the
|
||||||
// offset of the FileMap is known.
|
// offset of the FileMap is known.
|
||||||
let mut lines = lines.into_inner();
|
|
||||||
for pos in &mut lines {
|
for pos in &mut lines {
|
||||||
*pos = *pos - start_pos;
|
*pos = *pos - start_pos;
|
||||||
}
|
}
|
||||||
let mut multibyte_chars = multibyte_chars.into_inner();
|
|
||||||
for mbc in &mut multibyte_chars {
|
for mbc in &mut multibyte_chars {
|
||||||
mbc.pos = mbc.pos - start_pos;
|
mbc.pos = mbc.pos - start_pos;
|
||||||
}
|
}
|
||||||
let mut non_narrow_chars = non_narrow_chars.into_inner();
|
|
||||||
for swc in &mut non_narrow_chars {
|
for swc in &mut non_narrow_chars {
|
||||||
*swc = *swc - start_pos;
|
*swc = *swc - start_pos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,16 +250,7 @@ impl CodeMap {
|
||||||
/// Creates a new filemap and sets its line information.
|
/// Creates a new filemap and sets its line information.
|
||||||
/// This does not ensure that only one FileMap exists per file name.
|
/// This does not ensure that only one FileMap exists per file name.
|
||||||
pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc<FileMap> {
|
pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc<FileMap> {
|
||||||
let fm = self.new_filemap(filename.to_owned().into(), src.to_owned());
|
self.new_filemap(filename.to_owned().into(), src.to_owned())
|
||||||
let mut byte_pos: u32 = fm.start_pos.0;
|
|
||||||
for line in src.lines() {
|
|
||||||
// register the start of this line
|
|
||||||
fm.next_line(BytePos(byte_pos));
|
|
||||||
|
|
||||||
// update byte_pos to include this line and the \n at the end
|
|
||||||
byte_pos += line.len() as u32 + 1;
|
|
||||||
}
|
|
||||||
fm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,9 +296,9 @@ impl CodeMap {
|
||||||
external_src: Lock::new(ExternalSource::AbsentOk),
|
external_src: Lock::new(ExternalSource::AbsentOk),
|
||||||
start_pos,
|
start_pos,
|
||||||
end_pos,
|
end_pos,
|
||||||
lines: Lock::new(file_local_lines),
|
lines: file_local_lines,
|
||||||
multibyte_chars: Lock::new(file_local_multibyte_chars),
|
multibyte_chars: file_local_multibyte_chars,
|
||||||
non_narrow_chars: Lock::new(file_local_non_narrow_chars),
|
non_narrow_chars: file_local_non_narrow_chars,
|
||||||
name_hash,
|
name_hash,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -345,21 +336,22 @@ impl CodeMap {
|
||||||
match self.lookup_line(pos) {
|
match self.lookup_line(pos) {
|
||||||
Ok(FileMapAndLine { fm: f, line: a }) => {
|
Ok(FileMapAndLine { fm: f, line: a }) => {
|
||||||
let line = a + 1; // Line numbers start at 1
|
let line = a + 1; // Line numbers start at 1
|
||||||
let linebpos = (*f.lines.borrow())[a];
|
let linebpos = f.lines[a];
|
||||||
let linechpos = self.bytepos_to_file_charpos(linebpos);
|
let linechpos = self.bytepos_to_file_charpos(linebpos);
|
||||||
let col = chpos - linechpos;
|
let col = chpos - linechpos;
|
||||||
|
|
||||||
let col_display = {
|
let col_display = {
|
||||||
let non_narrow_chars = f.non_narrow_chars.borrow();
|
let start_width_idx = f
|
||||||
let start_width_idx = non_narrow_chars
|
.non_narrow_chars
|
||||||
.binary_search_by_key(&linebpos, |x| x.pos())
|
.binary_search_by_key(&linebpos, |x| x.pos())
|
||||||
.unwrap_or_else(|x| x);
|
.unwrap_or_else(|x| x);
|
||||||
let end_width_idx = non_narrow_chars
|
let end_width_idx = f
|
||||||
|
.non_narrow_chars
|
||||||
.binary_search_by_key(&pos, |x| x.pos())
|
.binary_search_by_key(&pos, |x| x.pos())
|
||||||
.unwrap_or_else(|x| x);
|
.unwrap_or_else(|x| x);
|
||||||
let special_chars = end_width_idx - start_width_idx;
|
let special_chars = end_width_idx - start_width_idx;
|
||||||
let non_narrow: usize =
|
let non_narrow: usize = f
|
||||||
non_narrow_chars[start_width_idx..end_width_idx]
|
.non_narrow_chars[start_width_idx..end_width_idx]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| x.width())
|
.map(|x| x.width())
|
||||||
.sum();
|
.sum();
|
||||||
|
@ -380,12 +372,12 @@ impl CodeMap {
|
||||||
}
|
}
|
||||||
Err(f) => {
|
Err(f) => {
|
||||||
let col_display = {
|
let col_display = {
|
||||||
let non_narrow_chars = f.non_narrow_chars.borrow();
|
let end_width_idx = f
|
||||||
let end_width_idx = non_narrow_chars
|
.non_narrow_chars
|
||||||
.binary_search_by_key(&pos, |x| x.pos())
|
.binary_search_by_key(&pos, |x| x.pos())
|
||||||
.unwrap_or_else(|x| x);
|
.unwrap_or_else(|x| x);
|
||||||
let non_narrow: usize =
|
let non_narrow: usize = f
|
||||||
non_narrow_chars[0..end_width_idx]
|
.non_narrow_chars[0..end_width_idx]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| x.width())
|
.map(|x| x.width())
|
||||||
.sum();
|
.sum();
|
||||||
|
@ -830,7 +822,7 @@ impl CodeMap {
|
||||||
// The number of extra bytes due to multibyte chars in the FileMap
|
// The number of extra bytes due to multibyte chars in the FileMap
|
||||||
let mut total_extra_bytes = 0;
|
let mut total_extra_bytes = 0;
|
||||||
|
|
||||||
for mbc in map.multibyte_chars.borrow().iter() {
|
for mbc in map.multibyte_chars.iter() {
|
||||||
debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
|
debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
|
||||||
if mbc.pos < bpos {
|
if mbc.pos < bpos {
|
||||||
// every character is at least one byte, so we only
|
// every character is at least one byte, so we only
|
||||||
|
|
|
@ -51,11 +51,7 @@ pub struct StringReader<'a> {
|
||||||
pub ch: Option<char>,
|
pub ch: Option<char>,
|
||||||
pub filemap: Lrc<syntax_pos::FileMap>,
|
pub filemap: Lrc<syntax_pos::FileMap>,
|
||||||
/// Stop reading src at this index.
|
/// Stop reading src at this index.
|
||||||
end_src_index: usize,
|
pub end_src_index: usize,
|
||||||
/// Whether to record new-lines and multibyte chars in filemap.
|
|
||||||
/// This is only necessary the first time a filemap is lexed.
|
|
||||||
/// If part of a filemap is being re-lexed, this should be set to false.
|
|
||||||
save_new_lines_and_multibyte: bool,
|
|
||||||
// cached:
|
// cached:
|
||||||
peek_tok: token::Token,
|
peek_tok: token::Token,
|
||||||
peek_span: Span,
|
peek_span: Span,
|
||||||
|
@ -188,7 +184,6 @@ impl<'a> StringReader<'a> {
|
||||||
ch: Some('\n'),
|
ch: Some('\n'),
|
||||||
filemap,
|
filemap,
|
||||||
end_src_index: src.len(),
|
end_src_index: src.len(),
|
||||||
save_new_lines_and_multibyte: true,
|
|
||||||
// dummy values; not read
|
// dummy values; not read
|
||||||
peek_tok: token::Eof,
|
peek_tok: token::Eof,
|
||||||
peek_span: syntax_pos::DUMMY_SP,
|
peek_span: syntax_pos::DUMMY_SP,
|
||||||
|
@ -225,7 +220,6 @@ impl<'a> StringReader<'a> {
|
||||||
let mut sr = StringReader::new_raw_internal(sess, begin.fm, None);
|
let mut sr = StringReader::new_raw_internal(sess, begin.fm, None);
|
||||||
|
|
||||||
// Seek the lexer to the right byte range.
|
// Seek the lexer to the right byte range.
|
||||||
sr.save_new_lines_and_multibyte = false;
|
|
||||||
sr.next_pos = span.lo();
|
sr.next_pos = span.lo();
|
||||||
sr.end_src_index = sr.src_index(span.hi());
|
sr.end_src_index = sr.src_index(span.hi());
|
||||||
|
|
||||||
|
@ -458,18 +452,6 @@ impl<'a> StringReader<'a> {
|
||||||
let next_ch = char_at(&self.src, next_src_index);
|
let next_ch = char_at(&self.src, next_src_index);
|
||||||
let next_ch_len = next_ch.len_utf8();
|
let next_ch_len = next_ch.len_utf8();
|
||||||
|
|
||||||
if self.ch.unwrap() == '\n' {
|
|
||||||
if self.save_new_lines_and_multibyte {
|
|
||||||
self.filemap.next_line(self.next_pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if next_ch_len > 1 {
|
|
||||||
if self.save_new_lines_and_multibyte {
|
|
||||||
self.filemap.record_multibyte_char(self.next_pos, next_ch_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.filemap.record_width(self.next_pos, next_ch);
|
|
||||||
|
|
||||||
self.ch = Some(next_ch);
|
self.ch = Some(next_ch);
|
||||||
self.pos = self.next_pos;
|
self.pos = self.next_pos;
|
||||||
self.next_pos = self.next_pos + Pos::from_usize(next_ch_len);
|
self.next_pos = self.next_pos + Pos::from_usize(next_ch_len);
|
||||||
|
|
|
@ -779,11 +779,11 @@ pub struct FileMap {
|
||||||
/// The end position of this source in the CodeMap
|
/// The end position of this source in the CodeMap
|
||||||
pub end_pos: BytePos,
|
pub end_pos: BytePos,
|
||||||
/// Locations of lines beginnings in the source code
|
/// Locations of lines beginnings in the source code
|
||||||
pub lines: Lock<Vec<BytePos>>,
|
pub lines: Vec<BytePos>,
|
||||||
/// Locations of multi-byte characters in the source code
|
/// Locations of multi-byte characters in the source code
|
||||||
pub multibyte_chars: Lock<Vec<MultiByteChar>>,
|
pub multibyte_chars: Vec<MultiByteChar>,
|
||||||
/// Width of characters that are not narrow in the source code
|
/// Width of characters that are not narrow in the source code
|
||||||
pub non_narrow_chars: Lock<Vec<NonNarrowChar>>,
|
pub non_narrow_chars: Vec<NonNarrowChar>,
|
||||||
/// A hash of the filename, used for speeding up the incr. comp. hashing.
|
/// A hash of the filename, used for speeding up the incr. comp. hashing.
|
||||||
pub name_hash: u128,
|
pub name_hash: u128,
|
||||||
}
|
}
|
||||||
|
@ -797,7 +797,7 @@ impl Encodable for FileMap {
|
||||||
s.emit_struct_field("start_pos", 4, |s| self.start_pos.encode(s))?;
|
s.emit_struct_field("start_pos", 4, |s| self.start_pos.encode(s))?;
|
||||||
s.emit_struct_field("end_pos", 5, |s| self.end_pos.encode(s))?;
|
s.emit_struct_field("end_pos", 5, |s| self.end_pos.encode(s))?;
|
||||||
s.emit_struct_field("lines", 6, |s| {
|
s.emit_struct_field("lines", 6, |s| {
|
||||||
let lines = self.lines.borrow();
|
let lines = &self.lines[..];
|
||||||
// store the length
|
// store the length
|
||||||
s.emit_u32(lines.len() as u32)?;
|
s.emit_u32(lines.len() as u32)?;
|
||||||
|
|
||||||
|
@ -843,10 +843,10 @@ impl Encodable for FileMap {
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
s.emit_struct_field("multibyte_chars", 7, |s| {
|
s.emit_struct_field("multibyte_chars", 7, |s| {
|
||||||
(*self.multibyte_chars.borrow()).encode(s)
|
self.multibyte_chars.encode(s)
|
||||||
})?;
|
})?;
|
||||||
s.emit_struct_field("non_narrow_chars", 8, |s| {
|
s.emit_struct_field("non_narrow_chars", 8, |s| {
|
||||||
(*self.non_narrow_chars.borrow()).encode(s)
|
self.non_narrow_chars.encode(s)
|
||||||
})?;
|
})?;
|
||||||
s.emit_struct_field("name_hash", 9, |s| {
|
s.emit_struct_field("name_hash", 9, |s| {
|
||||||
self.name_hash.encode(s)
|
self.name_hash.encode(s)
|
||||||
|
@ -914,9 +914,9 @@ impl Decodable for FileMap {
|
||||||
src: None,
|
src: None,
|
||||||
src_hash,
|
src_hash,
|
||||||
external_src: Lock::new(ExternalSource::AbsentOk),
|
external_src: Lock::new(ExternalSource::AbsentOk),
|
||||||
lines: Lock::new(lines),
|
lines,
|
||||||
multibyte_chars: Lock::new(multibyte_chars),
|
multibyte_chars,
|
||||||
non_narrow_chars: Lock::new(non_narrow_chars),
|
non_narrow_chars,
|
||||||
name_hash,
|
name_hash,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -949,6 +949,9 @@ impl FileMap {
|
||||||
};
|
};
|
||||||
let end_pos = start_pos.to_usize() + src.len();
|
let end_pos = start_pos.to_usize() + src.len();
|
||||||
|
|
||||||
|
let (lines, multibyte_chars, non_narrow_chars) =
|
||||||
|
Self::find_newlines_and_special_chars(&src[..], start_pos);
|
||||||
|
|
||||||
FileMap {
|
FileMap {
|
||||||
name,
|
name,
|
||||||
name_was_remapped,
|
name_was_remapped,
|
||||||
|
@ -959,34 +962,81 @@ impl FileMap {
|
||||||
external_src: Lock::new(ExternalSource::Unneeded),
|
external_src: Lock::new(ExternalSource::Unneeded),
|
||||||
start_pos,
|
start_pos,
|
||||||
end_pos: Pos::from_usize(end_pos),
|
end_pos: Pos::from_usize(end_pos),
|
||||||
lines: Lock::new(Vec::new()),
|
lines,
|
||||||
multibyte_chars: Lock::new(Vec::new()),
|
multibyte_chars,
|
||||||
non_narrow_chars: Lock::new(Vec::new()),
|
non_narrow_chars,
|
||||||
name_hash,
|
name_hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EFFECT: register a start-of-line offset in the
|
fn find_newlines_and_special_chars(src: &str, filemap_start_pos: BytePos)
|
||||||
/// table of line-beginnings.
|
-> (Vec<BytePos>, Vec<MultiByteChar>, Vec<NonNarrowChar>) {
|
||||||
/// UNCHECKED INVARIANT: these offsets must be added in the right
|
|
||||||
/// order and must be in the right places; there is shared knowledge
|
let mut index = 0;
|
||||||
/// about what ends a line between this file and parse.rs
|
let mut lines = vec![filemap_start_pos];
|
||||||
/// WARNING: pos param here is the offset relative to start of CodeMap,
|
let mut multibyte_chars = vec![];
|
||||||
/// and CodeMap will append a newline when adding a filemap without a newline at the end,
|
let mut non_narrow_chars = vec![];
|
||||||
/// so the safe way to call this is with value calculated as
|
|
||||||
/// filemap.start_pos + newline_offset_relative_to_the_start_of_filemap.
|
while index < src.len() {
|
||||||
pub fn next_line(&self, pos: BytePos) {
|
let byte_pos = BytePos::from_usize(index) + filemap_start_pos;
|
||||||
// the new charpos must be > the last one (or it's the first one).
|
let byte = src.as_bytes()[index];
|
||||||
let mut lines = self.lines.borrow_mut();
|
|
||||||
let line_len = lines.len();
|
if byte.is_ascii() {
|
||||||
assert!(line_len == 0 || ((*lines)[line_len - 1] < pos));
|
match byte {
|
||||||
lines.push(pos);
|
b'\n' => {
|
||||||
|
lines.push(byte_pos + BytePos(1));
|
||||||
|
}
|
||||||
|
b'\t' => {
|
||||||
|
// Tabs will consume 4 columns.
|
||||||
|
non_narrow_chars.push(NonNarrowChar::new(byte_pos, 4));
|
||||||
|
}
|
||||||
|
c => if c.is_ascii_control() {
|
||||||
|
// Assume control characters are zero width.
|
||||||
|
non_narrow_chars.push(NonNarrowChar::new(byte_pos, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
} else {
|
||||||
|
let c = (&src[index..]).chars().next().unwrap();
|
||||||
|
let c_len = c.len_utf8();
|
||||||
|
|
||||||
|
if c_len > 1 {
|
||||||
|
assert!(c_len >=2 && c_len <= 4);
|
||||||
|
let mbc = MultiByteChar {
|
||||||
|
pos: byte_pos,
|
||||||
|
bytes: c_len,
|
||||||
|
};
|
||||||
|
multibyte_chars.push(mbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume control characters are zero width.
|
||||||
|
// FIXME: How can we decide between `width` and `width_cjk`?
|
||||||
|
let c_width = unicode_width::UnicodeWidthChar::width(c).unwrap_or(0);
|
||||||
|
|
||||||
|
if c_width != 1 {
|
||||||
|
non_narrow_chars.push(NonNarrowChar::new(byte_pos, c_width));
|
||||||
|
}
|
||||||
|
|
||||||
|
index += c_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The loop above optimistically registers a new line *after* each of \n
|
||||||
|
// it encounters. If that point is already outside the filemap, remove
|
||||||
|
// it again.
|
||||||
|
if let Some(&last_line_start) = lines.last() {
|
||||||
|
if last_line_start == filemap_start_pos + BytePos::from_usize(src.len()) {
|
||||||
|
lines.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(lines, multibyte_chars, non_narrow_chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the BytePos of the beginning of the current line.
|
/// Return the BytePos of the beginning of the current line.
|
||||||
pub fn line_begin_pos(&self) -> BytePos {
|
pub fn line_begin_pos(&self) -> BytePos {
|
||||||
let lines = self.lines.borrow();
|
match self.lines.last() {
|
||||||
match lines.last() {
|
|
||||||
Some(&line_pos) => line_pos,
|
Some(&line_pos) => line_pos,
|
||||||
None => self.start_pos,
|
None => self.start_pos,
|
||||||
}
|
}
|
||||||
|
@ -1040,8 +1090,7 @@ impl FileMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
let begin = {
|
let begin = {
|
||||||
let lines = self.lines.borrow();
|
let line = if let Some(line) = self.lines.get(line_number) {
|
||||||
let line = if let Some(line) = lines.get(line_number) {
|
|
||||||
line
|
line
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
@ -1059,35 +1108,6 @@ impl FileMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_multibyte_char(&self, pos: BytePos, bytes: usize) {
|
|
||||||
assert!(bytes >=2 && bytes <= 4);
|
|
||||||
let mbc = MultiByteChar {
|
|
||||||
pos,
|
|
||||||
bytes,
|
|
||||||
};
|
|
||||||
self.multibyte_chars.borrow_mut().push(mbc);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn record_width(&self, pos: BytePos, ch: char) {
|
|
||||||
let width = match ch {
|
|
||||||
'\t' =>
|
|
||||||
// Tabs will consume 4 columns.
|
|
||||||
4,
|
|
||||||
'\n' =>
|
|
||||||
// Make newlines take one column so that displayed spans can point them.
|
|
||||||
1,
|
|
||||||
ch =>
|
|
||||||
// Assume control characters are zero width.
|
|
||||||
// FIXME: How can we decide between `width` and `width_cjk`?
|
|
||||||
unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0),
|
|
||||||
};
|
|
||||||
// Only record non-narrow characters.
|
|
||||||
if width != 1 {
|
|
||||||
self.non_narrow_chars.borrow_mut().push(NonNarrowChar::new(pos, width));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_real_file(&self) -> bool {
|
pub fn is_real_file(&self) -> bool {
|
||||||
self.name.is_real()
|
self.name.is_real()
|
||||||
}
|
}
|
||||||
|
@ -1100,7 +1120,7 @@ impl FileMap {
|
||||||
self.end_pos.0 - self.start_pos.0
|
self.end_pos.0 - self.start_pos.0
|
||||||
}
|
}
|
||||||
pub fn count_lines(&self) -> usize {
|
pub fn count_lines(&self) -> usize {
|
||||||
self.lines.borrow().len()
|
self.lines.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the line containing the given position. The return value is the
|
/// Find the line containing the given position. The return value is the
|
||||||
|
@ -1108,13 +1128,12 @@ impl FileMap {
|
||||||
/// number. If the filemap is empty or the position is located before the
|
/// number. If the filemap is empty or the position is located before the
|
||||||
/// first line, None is returned.
|
/// first line, None is returned.
|
||||||
pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
|
pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
|
||||||
let lines = self.lines.borrow();
|
if self.lines.len() == 0 {
|
||||||
if lines.len() == 0 {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let line_index = lookup_line(&lines[..], pos);
|
let line_index = lookup_line(&self.lines[..], pos);
|
||||||
assert!(line_index < lines.len() as isize);
|
assert!(line_index < self.lines.len() as isize);
|
||||||
if line_index >= 0 {
|
if line_index >= 0 {
|
||||||
Some(line_index as usize)
|
Some(line_index as usize)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1127,12 +1146,11 @@ impl FileMap {
|
||||||
return (self.start_pos, self.end_pos);
|
return (self.start_pos, self.end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lines = self.lines.borrow();
|
assert!(line_index < self.lines.len());
|
||||||
assert!(line_index < lines.len());
|
if line_index == (self.lines.len() - 1) {
|
||||||
if line_index == (lines.len() - 1) {
|
(self.lines[line_index], self.end_pos)
|
||||||
(lines[line_index], self.end_pos)
|
|
||||||
} else {
|
} else {
|
||||||
(lines[line_index], lines[line_index + 1])
|
(self.lines[line_index], self.lines[line_index + 1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue