Skip to content

Commit 66bbd82

Browse files
committed
feat: Match Rust's multiline start special case
1 parent 0175871 commit 66bbd82

File tree

3 files changed

+73
-71
lines changed

3 files changed

+73
-71
lines changed

examples/format.svg

+25-27
Loading

src/renderer/display_list.rs

+46-40
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,42 @@ impl<'a> DisplaySet<'a> {
442442
line_len += 1;
443443
}
444444

445+
// This is a special case where we have a multiline
446+
// annotation that is at the start of the line disregarding
447+
// any leading whitespace, and no other multiline
448+
// annotations overlap it. In this case, we want to draw
449+
//
450+
// 2 | fn foo() {
451+
// | _^
452+
// 3 | |
453+
// 4 | | }
454+
// | |_^ test
455+
//
456+
// we simplify the output to:
457+
//
458+
// 2 | / fn foo() {
459+
// 3 | |
460+
// 4 | | }
461+
// | |_^ test
462+
if multiline_depth == 1
463+
&& annotations_positions.len() == 1
464+
&& annotations_positions
465+
.first()
466+
.map_or(false, |(_, annotation)| {
467+
matches!(
468+
annotation.annotation_part,
469+
DisplayAnnotationPart::MultilineStart(_)
470+
) && text
471+
.chars()
472+
.take(annotation.range.0)
473+
.all(|c| c.is_whitespace())
474+
})
475+
{
476+
let (_, ann) = annotations_positions.remove(0);
477+
let style = get_annotation_style(&ann.annotation_type, stylesheet);
478+
buffer.putc(line_offset, 3 + lineno_width, '/', *style);
479+
}
480+
445481
// Draw the column separator for any extra lines that were
446482
// created
447483
//
@@ -535,15 +571,13 @@ impl<'a> DisplaySet<'a> {
535571
// Add in any inline marks for any extra lines that have
536572
// been created. Output should look like above.
537573
for inline_mark in inline_marks {
538-
if let DisplayMarkType::AnnotationThrough(depth) = inline_mark.mark_type {
539-
let style =
540-
get_annotation_style(&inline_mark.annotation_type, stylesheet);
541-
if annotations_positions.is_empty() {
542-
buffer.putc(line_offset, width_offset + depth, '|', *style);
543-
} else {
544-
for p in line_offset..=line_offset + line_len + 1 {
545-
buffer.putc(p, width_offset + depth, '|', *style);
546-
}
574+
let DisplayMarkType::AnnotationThrough(depth) = inline_mark.mark_type;
575+
let style = get_annotation_style(&inline_mark.annotation_type, stylesheet);
576+
if annotations_positions.is_empty() {
577+
buffer.putc(line_offset, width_offset + depth, '|', *style);
578+
} else {
579+
for p in line_offset..=line_offset + line_len + 1 {
580+
buffer.putc(p, width_offset + depth, '|', *style);
547581
}
548582
}
549583
}
@@ -823,8 +857,6 @@ pub(crate) struct DisplayMark {
823857
pub(crate) enum DisplayMarkType {
824858
/// A mark indicating a multiline annotation going through the current line.
825859
AnnotationThrough(usize),
826-
/// A mark indicating a multiline annotation starting on the given line.
827-
AnnotationStart,
828860
}
829861

830862
/// A type of the `Annotation` which may impact the sigils, style or text displayed.
@@ -1153,18 +1185,8 @@ fn fold_body(body: Vec<DisplayLine<'_>>) -> Vec<DisplayLine<'_>> {
11531185
let mut unhighlighed_lines = vec![];
11541186
for line in body {
11551187
match &line {
1156-
DisplayLine::Source {
1157-
annotations,
1158-
inline_marks,
1159-
..
1160-
} => {
1161-
if annotations.is_empty()
1162-
// A multiline start mark (`/`) needs be treated as an
1163-
// annotation or the line could get folded.
1164-
&& inline_marks
1165-
.iter()
1166-
.all(|m| m.mark_type != DisplayMarkType::AnnotationStart)
1167-
{
1188+
DisplayLine::Source { annotations, .. } => {
1189+
if annotations.is_empty() {
11681190
unhighlighed_lines.push(line);
11691191
} else {
11701192
if lines.is_empty() {
@@ -1407,20 +1429,7 @@ fn format_body(
14071429
&& start <= line_end_index + end_line_size.saturating_sub(1)
14081430
&& end > line_end_index =>
14091431
{
1410-
// Special case for multiline annotations that start at the
1411-
// beginning of a line, which requires a special mark (`/`)
1412-
if start - line_start_index == 0 {
1413-
if let DisplayLine::Source {
1414-
ref mut inline_marks,
1415-
..
1416-
} = body[body_idx]
1417-
{
1418-
inline_marks.push(DisplayMark {
1419-
mark_type: DisplayMarkType::AnnotationStart,
1420-
annotation_type: DisplayAnnotationType::from(annotation.level),
1421-
});
1422-
}
1423-
} else if let DisplayLine::Source {
1432+
if let DisplayLine::Source {
14241433
ref mut annotations,
14251434
..
14261435
} = body[body_idx]
@@ -1679,9 +1688,6 @@ fn format_inline_marks(
16791688
DisplayMarkType::AnnotationThrough(depth) => {
16801689
buf.putc(line, 3 + lineno_width + depth, '|', *annotation_style);
16811690
}
1682-
DisplayMarkType::AnnotationStart => {
1683-
buf.putc(line, 3 + lineno_width, '/', *annotation_style);
1684-
}
16851691
};
16861692
}
16871693
Ok(())

tests/rustc_tests.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,7 @@ fn foo() {
254254
error: foo
255255
--> test.rs:3:3
256256
|
257-
3 | X0 Y0 Z0
258-
| ___^
257+
3 | / X0 Y0 Z0
259258
4 | | X1 Y1 Z1
260259
5 | | X2 Y2 Z2
261260
| | -
@@ -340,8 +339,7 @@ fn foo() {
340339
error: foo
341340
--> test.rs:3:3
342341
|
343-
3 | X0 Y0 Z0
344-
| ___^
342+
3 | / X0 Y0 Z0
345343
4 | | X1 Y1 Z1
346344
| |____^ `X` is a good letter
347345
5 | X2 Y2 Z2

0 commit comments

Comments
 (0)