Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b5a0af2

Browse files
authored
Merge pull request #131 from Muscraft/fix-no-highlght-line-end
Fix annotating line endings
2 parents ca313bf + c68600d commit b5a0af2

File tree

5 files changed

+514
-36
lines changed

5 files changed

+514
-36
lines changed

‎src/renderer/display_list.rs‎

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ pub(crate) enum DisplaySourceLine<'a> {
524524
Content {
525525
text: &'a str,
526526
range: (usize, usize), // meta information for annotation placement.
527+
end_line: EndLine,
527528
},
528529
/// An empty source line.
529530
Empty,
@@ -658,7 +659,8 @@ impl<'a> CursorLines<'a> {
658659
}
659660
}
660661

661-
enum EndLine {
662+
#[derive(Copy, Clone, Debug, PartialEq)]
663+
pub(crate) enum EndLine {
662664
Eof = 0,
663665
Crlf = 1,
664666
Lf = 2,
@@ -847,13 +849,20 @@ fn format_header<'a>(
847849

848850
for item in body {
849851
if let DisplayLine::Source {
850-
line: DisplaySourceLine::Content { text, range },
852+
line:
853+
DisplaySourceLine::Content {
854+
text,
855+
range,
856+
end_line,
857+
},
851858
lineno,
852859
..
853860
} = item
854861
{
855-
if main_range >= range.0 && main_range <= range.1 {
856-
let char_column = text[0..(main_range - range.0)].chars().count();
862+
if main_range >= range.0 && main_range <= range.1 + *end_line as usize {
863+
let char_column = text[0..(main_range - range.0).min(text.len())]
864+
.chars()
865+
.count();
857866
col = char_column + 1;
858867
line_offset = lineno.unwrap_or(1);
859868
break;
@@ -927,8 +936,18 @@ fn fold_body(body: Vec<DisplayLine<'_>>) -> Vec<DisplayLine<'_>> {
927936
let mut unhighlighed_lines = vec![];
928937
for line in body {
929938
match &line {
930-
DisplayLine::Source { annotations, .. } => {
931-
if annotations.is_empty() {
939+
DisplayLine::Source {
940+
annotations,
941+
inline_marks,
942+
..
943+
} => {
944+
if annotations.is_empty()
945+
// A multiline start mark (`/`) needs be treated as an
946+
// annotation or the line could get folded.
947+
&& inline_marks
948+
.iter()
949+
.all(|m| m.mark_type != DisplayMarkType::AnnotationStart)
950+
{
932951
unhighlighed_lines.push(line);
933952
} else {
934953
if lines.is_empty() {
@@ -1016,12 +1035,14 @@ fn format_body(
10161035
for (idx, (line, end_line)) in CursorLines::new(snippet.source).enumerate() {
10171036
let line_length: usize = line.len();
10181037
let line_range = (current_index, current_index + line_length);
1038+
let end_line_size = end_line as usize;
10191039
body.push(DisplayLine::Source {
10201040
lineno: Some(current_line),
10211041
inline_marks: vec![],
10221042
line: DisplaySourceLine::Content {
10231043
text: line,
10241044
range: line_range,
1045+
end_line,
10251046
},
10261047
annotations: vec![],
10271048
});
@@ -1045,7 +1066,7 @@ fn format_body(
10451066
let line_start_index = line_range.0;
10461067
let line_end_index = line_range.1;
10471068
current_line += 1;
1048-
current_index += line_length + end_line asusize;
1069+
current_index += line_length + end_line_size;
10491070

10501071
// It would be nice to use filter_drain here once it's stable.
10511072
annotations.retain(|annotation| {
@@ -1057,18 +1078,24 @@ fn format_body(
10571078
};
10581079
let label_right = annotation.label.map_or(0, |label| label.len() + 1);
10591080
match annotation.range {
1060-
Range { start, .. } if start > line_end_index => true,
1081+
// This handles if the annotation is on the next line. We add
1082+
// the `end_line_size` to account for annotating the line end.
1083+
Range { start, .. } if start > line_end_index + end_line_size => true,
1084+
// This handles the case where an annotation is contained
1085+
// within the current line including any line-end characters.
10611086
Range { start, end }
1062-
if start >= line_start_index && end <= line_end_index
1063-
// Allow annotating eof or stripped eol
1064-
|| start == line_end_index && end - start <= 1 =>
1087+
if start >= line_start_index
1088+
// We add at least one to `line_end_index` to allow
1089+
// highlighting the end of a file
1090+
&& end <= line_end_index + max(end_line_size, 1) =>
10651091
{
10661092
if let DisplayLine::Source {
10671093
ref mut annotations,
10681094
..
10691095
} = body[body_idx]
10701096
{
1071-
let annotation_start_col = line[0..(start - line_start_index)]
1097+
let annotation_start_col = line
1098+
[0..(start - line_start_index).min(line_length)]
10721099
.chars()
10731100
.map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
10741101
.sum::<usize>();
@@ -1101,11 +1128,16 @@ fn format_body(
11011128
}
11021129
false
11031130
}
1131+
// This handles the case where a multiline annotation starts
1132+
// somewhere on the current line, including any line-end chars
11041133
Range { start, end }
11051134
if start >= line_start_index
1106-
&& start <= line_end_index
1135+
// The annotation can start on a line ending
1136+
&& start <= line_end_index + end_line_size.saturating_sub(1)
11071137
&& end > line_end_index =>
11081138
{
1139+
// Special case for multiline annotations that start at the
1140+
// beginning of a line, which requires a special mark (`/`)
11091141
if start - line_start_index == 0 {
11101142
if let DisplayLine::Source {
11111143
ref mut inline_marks,
@@ -1122,7 +1154,8 @@ fn format_body(
11221154
..
11231155
} = body[body_idx]
11241156
{
1125-
let annotation_start_col = line[0..(start - line_start_index)]
1157+
let annotation_start_col = line
1158+
[0..(start - line_start_index).min(line_length)]
11261159
.chars()
11271160
.map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
11281161
.sum::<usize>();
@@ -1147,7 +1180,11 @@ fn format_body(
11471180
}
11481181
true
11491182
}
1150-
Range { start, end } if start < line_start_index && end > line_end_index => {
1183+
// This handles the case where a multiline annotation starts
1184+
// somewhere before this line and ends after it as well
1185+
Range { start, end }
1186+
if start < line_start_index && end > line_end_index + max(end_line_size, 1) =>
1187+
{
11511188
if let DisplayLine::Source {
11521189
ref mut inline_marks,
11531190
..
@@ -1160,10 +1197,14 @@ fn format_body(
11601197
}
11611198
true
11621199
}
1200+
// This handles the case where a multiline annotation ends
1201+
// somewhere on the current line, including any line-end chars
11631202
Range { start, end }
11641203
if start < line_start_index
11651204
&& end >= line_start_index
1166-
&& end <= line_end_index =>
1205+
// We add at least one to `line_end_index` to allow
1206+
// highlighting the end of a file
1207+
&& end <= line_end_index + max(end_line_size, 1) =>
11671208
{
11681209
if let DisplayLine::Source {
11691210
ref mut inline_marks,
@@ -1175,13 +1216,21 @@ fn format_body(
11751216
mark_type: DisplayMarkType::AnnotationThrough,
11761217
annotation_type: DisplayAnnotationType::from(annotation.level),
11771218
});
1178-
let end_mark = line[0..(end - line_start_index)]
1219+
let end_mark = line[0..(end - line_start_index).min(line_length)]
11791220
.chars()
11801221
.map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
11811222
.sum::<usize>()
11821223
.saturating_sub(1);
1183-
1184-
let end_plus_one = end_mark + 1;
1224+
// If the annotation ends on a line-end character, we
1225+
// need to annotate one past the end of the line
1226+
let (end_mark, end_plus_one) = if end > line_end_index
1227+
// Special case for highlighting the end of a file
1228+
|| (end == line_end_index + 1 && end_line_size == 0)
1229+
{
1230+
(end_mark + 1, end_mark + 2)
1231+
} else {
1232+
(end_mark, end_mark + 1)
1233+
};
11851234

11861235
span_left_margin = min(span_left_margin, end_mark);
11871236
span_right_margin = max(span_right_margin, end_plus_one);

‎tests/fixtures/no-color/ann_multiline2.svg‎

Lines changed: 6 additions & 8 deletions
Loading[フレーム]

‎tests/fixtures/no-color/ann_multiline2.toml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ title = "spacing error found"
55

66
[[message.snippets]]
77
source = """
8-
This is an exampl
9-
e of an edge case of an annotation overflowing
8+
This is an example
9+
of an edge case of an annotation overflowing
1010
to exactly one character on next line.
1111
"""
1212
line_start = 26
@@ -15,4 +15,4 @@ fold = false
1515
[[message.snippets.annotations]]
1616
label = "this should not be on separate lines"
1717
level = "Error"
18-
range = [11, 18]
18+
range = [11, 19]

‎tests/fixtures/no-color/fold_ann_multiline.svg‎

Lines changed: 8 additions & 6 deletions
Loading[フレーム]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /