From 838db689ad7787868ac55645352e1523544aebfc Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Thu, 28 Apr 2022 16:18:16 -0400 Subject: [PATCH] tamer: diagnose::report: Render labels on mark line Note that, if a span is first encountered with a mark but with _no_ label, the first label (if collapsed) will be on the next line. This allows a span to be marked without extra visual noise if it's not necessary, and to be able to trust that it'll stay that way. Until coloring is introduced, this may or may not be easier to read depending on context. This is also not yet taking into account where on the line it begins, and so may render poorly if the span is at the end of a line. That will be fixed later on. DEV-12151 --- tamer/src/diagnose/report.rs | 36 +++++++----- tamer/src/diagnose/report/test/integration.rs | 55 ++++++++----------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/tamer/src/diagnose/report.rs b/tamer/src/diagnose/report.rs index e60a8c35..c3f8871b 100644 --- a/tamer/src/diagnose/report.rs +++ b/tamer/src/diagnose/report.rs @@ -556,27 +556,35 @@ struct LineMark<'d> { impl<'d> Display for LineMark<'d> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.col { - Some(col) => { - let underline = - self.level.mark_char().to_string().repeat( - (col.end().get() - col.start().get()) as usize + 1, - ); + write!(f, " |")?; - let lpad = col.start().get() as usize - 1; + if let Some(col) = self.col { + let underline = self + .level + .mark_char() + .to_string() + .repeat((col.end().get() - col.start().get()) as usize + 1); - write!(f, " | {:lpad$}{underline}\n", "")?; - } - _ => { - write!(f, " |\n")?; - } + let lpad = col.start().get() as usize - 1; + + write!(f, " {:lpad$}{underline}", "")?; + } else { + write!(f, "\n")?; } if let Some(label) = self.label.as_ref() { - write!(f, " = {level}: {label}\n", level = self.level)?; + if self.col.is_none() { + // Render as a footnote. + write!(f, " =")?; + } + + // TODO: If the span is at the end of a long line, + // this is more likely to wrap on the user's terminal and be + // unpleasant to read. + write!(f, " {level}: {label}", level = self.level)?; } - Ok(()) + write!(f, "\n") } } diff --git a/tamer/src/diagnose/report/test/integration.rs b/tamer/src/diagnose/report/test/integration.rs index cab98876..d0179c82 100644 --- a/tamer/src/diagnose/report/test/integration.rs +++ b/tamer/src/diagnose/report/test/integration.rs @@ -170,8 +170,7 @@ error: single span with label --> bar/baz:3:1 | | bar/baz line 3 - | ^^^ - = error: span label here + | ^^^ error: span label here " ); } @@ -217,8 +216,7 @@ error: multiple adjacent same span with labels --> bar/baz:1:9 | | bar/baz line 1 - | ^^^^^^ - = error: A label + | ^^^^^^ error: A label = error: C label " ); @@ -233,7 +231,10 @@ fn adjacent_eq_context_neq_offset_len_spans_not_collapsed() { vec![ // --> ctx.span(0, 3).mark_error(), - ctx.span(0, 3).error("A, first label"), // collapse + // Note that this appears _after_ a marked span, + // and so the error will not be displayed on the same line as + // the mark. + ctx.span(0, 3).error("A, first label, after mark"), // collapse // --> ctx.span(0, 7).error("B, different length"), ctx.span(0, 7).mark_error(), // collapse @@ -250,26 +251,23 @@ error: eq context neq offset/len | | bar/baz line 1 | ^^^ - = error: A, first label + = error: A, first label, after mark --> bar/baz:1:1 | | bar/baz line 1 - | ^^^^^^^ - = error: B, different length + | ^^^^^^^ error: B, different length = error: B, collapse --> bar/baz:2:1 | | bar/baz line 2 - | ^^^^ - = error: C, different offset + | ^^^^ error: C, different offset --> bar/baz:1:1 | | bar/baz line 1 - | ^^^^^^^ - = error: B', not adjacent + | ^^^^^^^ error: B', not adjacent " ); } @@ -286,11 +284,14 @@ fn adjacent_neq_context_spans_not_collapsed() { vec![ // --> span_a.mark_error(), - span_a.error("A, first"), + // Note that this appears _after_ a marked span, + // and so the error will not be displayed on the same line as + // the mark. + span_a.error("A, first, after marked"), span_a.error("A, collapsed"), span_a.mark_error(), // collapsed, same // --> - span_b.error("B, first"), + span_b.error("B, first, no marked"), span_b.error("B, collapsed"), span_b.mark_error(), // collapsed, same // --> @@ -310,21 +311,19 @@ error: multiple adjacent different context | | foo/bar line 1 | ^^^^^^^ - = error: A, first + = error: A, first, after marked = error: A, collapsed --> bar/baz:1:1 | | bar/baz line 1 - | ^^^^^^^ - = error: B, first + | ^^^^^^^ error: B, first, no marked = error: B, collapsed --> foo/bar:1:1 | | foo/bar line 1 - | ^^^^^^^ - = error: A, not collapsed + | ^^^^^^^ error: A, not collapsed --> bar/baz:1:1 | @@ -357,8 +356,7 @@ internal error: multiple spans with labels of different severity level --> foo/bar:4:9 | | foo/bar line 4 - | !!!!!! - = internal error: an internal error + | !!!!!! internal error: an internal error = error: an error = note: a note = help: a help message @@ -386,8 +384,7 @@ error: multi-line span | ^^^^^^ | | foo/bar line 2 - | ^^^^^^^^^^^^ - = error: label to be on last line + | ^^^^^^^^^^^^ error: label to be on last line " ); } @@ -524,26 +521,22 @@ internal error: multiple level mark styles --> foo/bar:1:1 | | foo/bar line 1 - | !!!!!!! - = internal error: A + | !!!!!!! internal error: A --> foo/bar:2:1 | | foo/bar line 2 - | ^^^^^^^ - = error: B + | ^^^^^^^ error: B --> foo/bar:3:1 | | foo/bar line 3 - | ------- - = note: C + | ------- note: C --> foo/bar:4:1 | | foo/bar line 4 - | ------- - = help: D + | ------- help: D " ); }