Skip to content

Commit 76b445b

Browse files
committed
Fix unicode
1 parent f523c59 commit 76b445b

3 files changed

Lines changed: 56 additions & 60 deletions

File tree

crates/emmylua_check/src/terminal_display/display.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::path::PathBuf;
22

3-
use emmylua_code_analysis::{DbIndex, FileId};
3+
use emmylua_code_analysis::{DbIndex, FileId, LuaDocument};
44
use lsp_types::{Diagnostic, DiagnosticSeverity};
55

66
#[derive(Debug)]
@@ -32,6 +32,7 @@ impl TerminalDisplay {
3232
let file_path = self.get_relative_path(db, file_id);
3333
let document = db.get_vfs().get_document(&file_id).unwrap();
3434
let text = document.get_text();
35+
let text_lines = text.lines().collect::<Vec<&str>>();
3536

3637
// Group statistics by severity level
3738
let mut error_count = 0;
@@ -60,7 +61,7 @@ impl TerminalDisplay {
6061

6162
// Display each diagnostic individually
6263
for diagnostic in diagnostics {
63-
self.display_single_diagnostic(&file_path, text, diagnostic, db, file_id);
64+
self.display_single_diagnostic(&file_path, &document, &text_lines, diagnostic);
6465
}
6566

6667
println!(); // Add blank line separator
@@ -162,18 +163,11 @@ impl TerminalDisplay {
162163
fn display_single_diagnostic(
163164
&mut self,
164165
file_path: &str,
165-
text: &str,
166+
document: &LuaDocument,
167+
lines: &[&str],
166168
diagnostic: Diagnostic,
167-
document: &emmylua_code_analysis::DbIndex,
168-
file_id: FileId,
169169
) {
170170
let range = diagnostic.range;
171-
let doc = document.get_vfs().get_document(&file_id).unwrap();
172-
let _span = match doc.get_range_span(range) {
173-
Some(span) => span,
174-
None => return,
175-
};
176-
177171
// Get severity level colors and symbols
178172
let (level_color, level_symbol, _level_name) = match diagnostic.severity {
179173
Some(DiagnosticSeverity::ERROR) => ("\x1b[1;31m", "error", "error"),
@@ -194,12 +188,17 @@ impl TerminalDisplay {
194188

195189
// Calculate line and column numbers
196190
let start_line = range.start.line as usize;
197-
let start_col = range.start.character as usize;
191+
let start_character = range.start.character as usize;
192+
let Some(start_col) = document.get_col_offset_at_line(start_line, start_character) else {
193+
return;
194+
};
195+
let start_col = u32::from(start_col) as usize;
198196
let end_line = range.end.line as usize;
199-
let end_col = range.end.character as usize;
200-
201-
// Split text into lines
202-
let lines: Vec<&str> = text.lines().collect();
197+
let end_character = range.end.character as usize;
198+
let Some(end_col) = document.get_col_offset_at_line(end_line, end_character) else {
199+
return;
200+
};
201+
let end_col = u32::from(end_col) as usize;
203202

204203
if start_line >= lines.len() {
205204
return;
@@ -226,10 +225,15 @@ impl TerminalDisplay {
226225
" \x1b[90m-->\x1b[0m {}:{}:{}",
227226
file_path,
228227
start_line + 1,
229-
start_col + 1
228+
start_character + 1
230229
);
231230
} else {
232-
println!(" --> {}:{}:{}", file_path, start_line + 1, start_col + 1);
231+
println!(
232+
" --> {}:{}:{}",
233+
file_path,
234+
start_line + 1,
235+
start_character + 1
236+
);
233237
}
234238

235239
// Calculate context range to display (one line before and after for context)

crates/emmylua_code_analysis/src/vfs/document.rs

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ impl<'a> LuaDocument<'a> {
7373
self.line_index.get_offset(line, col, self.text)
7474
}
7575

76+
pub fn get_col_offset_at_line(&self, line: usize, col: usize) -> Option<TextSize> {
77+
self.line_index.get_col_offset_at_line(line, col, self.text)
78+
}
79+
7680
pub fn get_line_range(&self, line: usize) -> Option<TextRange> {
7781
let start = self.line_index.get_line_offset(line)?;
7882
if let Some(end) = self.line_index.get_line_offset(line + 1) {
@@ -135,30 +139,13 @@ impl<'a> LuaDocument<'a> {
135139
},
136140
}
137141
}
138-
139-
pub fn get_range_span(&self, range: lsp_types::Range) -> Option<(usize, usize)> {
140-
let text = self.get_text();
141-
let start = self.get_offset(range.start.line as usize, range.start.character as usize)?;
142-
let end = self.get_offset(range.end.line as usize, range.end.character as usize)?;
143-
// char count
144-
let start = text
145-
.get(..start.into())
146-
.map(|s| s.chars().count())
147-
.unwrap_or(0);
148-
let end = text
149-
.get(..end.into())
150-
.map(|s| s.chars().count())
151-
.unwrap_or(0);
152-
153-
Some((start.into(), end.into()))
154-
}
155142
}
156143

157144
#[cfg(test)]
158145
mod tests {
159146
use super::*;
160147
use crate::{Emmyrc, Vfs, VirtualUrlGenerator};
161-
use lsp_types::{Position, Range};
148+
use lsp_types::Position;
162149

163150
fn create_vfs() -> Vfs {
164151
let mut vfs = Vfs::new();
@@ -240,30 +227,6 @@ mod tests {
240227
assert_eq!(rowan_range.end(), TextSize::from(11));
241228
}
242229

243-
#[test]
244-
fn test_range_span() {
245-
let code = "abcde";
246-
let mut vfs = create_vfs();
247-
let vg = VirtualUrlGenerator::new();
248-
let uri = vg.new_uri("span.lua");
249-
let id = vfs.set_file_content(&uri, Some(code.to_string()));
250-
let document = vfs.get_document(&id).unwrap();
251-
252-
let lsp_range = Range {
253-
start: Position {
254-
line: 0,
255-
character: 1,
256-
},
257-
end: Position {
258-
line: 0,
259-
character: 4,
260-
},
261-
};
262-
let span = document.get_range_span(lsp_range).unwrap();
263-
// Expecting span (1, 4) which corresponds to substring "bcd".
264-
assert_eq!(span, (1, 4));
265-
}
266-
267230
#[test]
268231
fn test_file_name_and_uri() {
269232
let code = "";

crates/emmylua_parser/src/text/line_index.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,33 @@ impl LineIndex {
128128
Some(start_offset + TextSize::from(offset as u32))
129129
}
130130
}
131+
132+
pub fn get_col_offset_at_line(
133+
&self,
134+
line: usize,
135+
col: usize,
136+
source_text: &str,
137+
) -> Option<TextSize> {
138+
let start_offset = self.get_line_offset(line)?;
139+
if col == 0 {
140+
return Some(0.into());
141+
}
142+
143+
if self.is_line_only_ascii(line.try_into().unwrap()) {
144+
let col = col.min(source_text.len());
145+
Some(TextSize::from(col as u32))
146+
} else {
147+
let mut offset = 0;
148+
let mut col = col;
149+
for c in source_text[usize::from(start_offset)..].chars() {
150+
if col == 0 {
151+
break;
152+
}
153+
154+
offset += c.len_utf8();
155+
col -= 1;
156+
}
157+
Some(TextSize::from(offset as u32))
158+
}
159+
}
131160
}

0 commit comments

Comments
 (0)