Make sure all full-line spans are highlighted properly Even if the context covers lines after the fully-covered line, the span shouldn't point to them.
diff --git a/pkgs/source_span/lib/src/highlighter.dart b/pkgs/source_span/lib/src/highlighter.dart index a05412a..97d696d 100644 --- a/pkgs/source_span/lib/src/highlighter.dart +++ b/pkgs/source_span/lib/src/highlighter.dart
@@ -99,6 +99,22 @@ newSpan = new SourceSpanWithContext(start, end, text, context); } + // Normalize [span] so that the end location is at the end of a line, rather + // than on the beginning of the next line. + if (newSpan.end.column == 0 && newSpan.end.line != newSpan.start.line) { + assert(newSpan.text.endsWith("\n")); + + var text = newSpan.text.substring(0, newSpan.text.length - 1); + newSpan = new SourceSpanWithContext( + newSpan.start, + new SourceLocation(span.end.offset - 1, + sourceUrl: span.sourceUrl, + line: span.end.line - 1, + column: _lastColumn(text)), + text, + newSpan.context); + } + return new Highlighter._(newSpan, color); }
diff --git a/pkgs/source_span/test/highlight_test.dart b/pkgs/source_span/test/highlight_test.dart index 71b58c3..e2536ba 100644 --- a/pkgs/source_span/test/highlight_test.dart +++ b/pkgs/source_span/test/highlight_test.dart
@@ -316,21 +316,57 @@ }); }); - test("supports lines of preceding and following context", () { - var span = new SourceSpanWithContext( - new SourceLocation(5, line: 2, column: 5, sourceUrl: "foo.dart"), - new SourceLocation(12, line: 2, column: 12, sourceUrl: "foo.dart"), - "foo bar", - "previous\nlines\n-----foo bar-----\nfollowing line\n"); + group("supports lines of preceding and following context for a span", () { + test("within a single line", () { + var span = new SourceSpanWithContext( + new SourceLocation(20, line: 2, column: 5, sourceUrl: "foo.dart"), + new SourceLocation(27, line: 2, column: 12, sourceUrl: "foo.dart"), + "foo bar", + "previous\nlines\n-----foo bar-----\nfollowing line\n"); - expect(span.highlight(color: colors.YELLOW), equals(""" -${colors.BLUE} ,${colors.NONE} -${colors.BLUE}1 |${colors.NONE} previous -${colors.BLUE}2 |${colors.NONE} lines -${colors.BLUE}3 |${colors.NONE} -----${colors.YELLOW}foo bar${colors.NONE}----- -${colors.BLUE} |${colors.NONE} ${colors.YELLOW}^^^^^^^${colors.NONE} -${colors.BLUE}4 |${colors.NONE} following line -${colors.BLUE} '${colors.NONE}""")); + expect(span.highlight(), equals(""" + , +1 | previous +2 | lines +3 | -----foo bar----- + | ^^^^^^^ +4 | following line + '""")); + }); + + test("covering a full line", () { + var span = new SourceSpanWithContext( + new SourceLocation(15, line: 2, column: 0, sourceUrl: "foo.dart"), + new SourceLocation(33, line: 3, column: 0, sourceUrl: "foo.dart"), + "-----foo bar-----\n", + "previous\nlines\n-----foo bar-----\nfollowing line\n"); + + expect(span.highlight(), equals(""" + , +1 | previous +2 | lines +3 | -----foo bar----- + | ^^^^^^^^^^^^^^^^^ +4 | following line + '""")); + }); + + test("covering multiple full lines", () { + var span = new SourceSpanWithContext( + new SourceLocation(15, line: 2, column: 0, sourceUrl: "foo.dart"), + new SourceLocation(23, line: 4, column: 0, sourceUrl: "foo.dart"), + "foo\nbar\n", + "previous\nlines\nfoo\nbar\nfollowing line\n"); + + expect(span.highlight(), equals(""" + , +1 | previous +2 | lines +3 | / foo +4 | \\ bar +5 | following line + '""")); + }); }); group("colors", () {