| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // ignore_for_file: prefer_interpolation_to_compose_strings |
| |
| import 'package:source_span/source_span.dart'; |
| import 'package:source_span/src/colors.dart' as colors; |
| import 'package:term_glyph/term_glyph.dart' as glyph; |
| import 'package:test/test.dart'; |
| |
| void main() { |
| late bool oldAscii; |
| setUpAll(() { |
| oldAscii = glyph.ascii; |
| glyph.ascii = true; |
| }); |
| |
| tearDownAll(() { |
| glyph.ascii = oldAscii; |
| }); |
| |
| late SourceFile file; |
| setUp(() { |
| file = SourceFile.fromString(''' |
| foo bar baz |
| whiz bang boom |
| zip zap zop |
| '''); |
| }); |
| |
| test('points to the span in the source', () { |
| expect(file.span(4, 7).highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| |
| test('gracefully handles a missing source URL', () { |
| final span = SourceFile.fromString('foo bar baz').span(4, 7); |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| |
| group('highlights a point span', () { |
| test('in the middle of a line', () { |
| expect(file.location(4).pointSpan().highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^ |
| '""")); |
| }); |
| |
| test('at the beginning of the file', () { |
| expect(file.location(0).pointSpan().highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^ |
| '""")); |
| }); |
| |
| test('at the beginning of a line', () { |
| expect(file.location(12).pointSpan().highlight(), equals(""" |
| , |
| 2 | whiz bang boom |
| | ^ |
| '""")); |
| }); |
| |
| test('at the end of a line', () { |
| expect(file.location(11).pointSpan().highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^ |
| '""")); |
| }); |
| |
| test('at the end of the file', () { |
| expect(file.location(38).pointSpan().highlight(), equals(""" |
| , |
| 3 | zip zap zop |
| | ^ |
| '""")); |
| }); |
| |
| test('after the end of the file', () { |
| expect(file.location(39).pointSpan().highlight(), equals(""" |
| , |
| 4 | |
| | ^ |
| '""")); |
| }); |
| |
| test('at the end of the file with no trailing newline', () { |
| file = SourceFile.fromString('zip zap zop'); |
| expect(file.location(10).pointSpan().highlight(), equals(""" |
| , |
| 1 | zip zap zop |
| | ^ |
| '""")); |
| }); |
| |
| test('after the end of the file with no trailing newline', () { |
| file = SourceFile.fromString('zip zap zop'); |
| expect(file.location(11).pointSpan().highlight(), equals(""" |
| , |
| 1 | zip zap zop |
| | ^ |
| '""")); |
| }); |
| |
| test('in an empty file', () { |
| expect(SourceFile.fromString('').location(0).pointSpan().highlight(), |
| equals(""" |
| , |
| 1 | |
| | ^ |
| '""")); |
| }); |
| |
| test('on an empty line', () { |
| final file = SourceFile.fromString('foo\n\nbar'); |
| expect(file.location(4).pointSpan().highlight(), equals(""" |
| , |
| 2 | |
| | ^ |
| '""")); |
| }); |
| }); |
| |
| test('highlights a single-line file without a newline', () { |
| expect(SourceFile.fromString('foo bar').span(0, 7).highlight(), equals(""" |
| , |
| 1 | foo bar |
| | ^^^^^^^ |
| '""")); |
| }); |
| |
| test('highlights text including a trailing newline', () { |
| expect(file.span(8, 12).highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| |
| test('highlights a single empty line', () { |
| expect( |
| SourceFile.fromString('foo\n\nbar').span(4, 5).highlight(), equals(""" |
| , |
| 2 | |
| | ^ |
| '""")); |
| }); |
| |
| test('highlights a trailing newline', () { |
| expect(file.span(11, 12).highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^ |
| '""")); |
| }); |
| |
| group('with a multiline span', () { |
| test('highlights the middle of the first and last lines', () { |
| expect(file.span(4, 34).highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| 3 | | zip zap zop |
| | '-------^ |
| '""")); |
| }); |
| |
| test('works when it begins at the end of a line', () { |
| expect(file.span(11, 34).highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,------------^ |
| 2 | | whiz bang boom |
| 3 | | zip zap zop |
| | '-------^ |
| '""")); |
| }); |
| |
| test('works when it ends at the beginning of a line', () { |
| expect(file.span(4, 28).highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| 3 | | zip zap zop |
| | '-^ |
| '""")); |
| }); |
| |
| test('highlights the full first line', () { |
| expect(file.span(0, 34).highlight(), equals(""" |
| , |
| 1 | / foo bar baz |
| 2 | | whiz bang boom |
| 3 | | zip zap zop |
| | '-------^ |
| '""")); |
| }); |
| |
| test("highlights the full first line even if it's indented", () { |
| final file = SourceFile.fromString(''' |
| foo bar baz |
| whiz bang boom |
| zip zap zop |
| '''); |
| |
| expect(file.span(2, 38).highlight(), equals(""" |
| , |
| 1 | / foo bar baz |
| 2 | | whiz bang boom |
| 3 | | zip zap zop |
| | '-------^ |
| '""")); |
| }); |
| |
| test("highlights the full first line if it's empty", () { |
| final file = SourceFile.fromString(''' |
| foo |
| |
| bar |
| '''); |
| |
| expect(file.span(4, 9).highlight(), equals(r""" |
| , |
| 2 | / |
| 3 | \ bar |
| '""")); |
| }); |
| |
| test('highlights the full last line', () { |
| expect(file.span(4, 27).highlight(), equals(r""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | \ whiz bang boom |
| '""")); |
| }); |
| |
| test('highlights the full last line with no trailing newline', () { |
| expect(file.span(4, 26).highlight(), equals(r""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | \ whiz bang boom |
| '""")); |
| }); |
| |
| test('highlights the full last line with a trailing Windows newline', () { |
| final file = SourceFile.fromString(''' |
| foo bar baz\r |
| whiz bang boom\r |
| zip zap zop\r |
| '''); |
| |
| expect(file.span(4, 29).highlight(), equals(r""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | \ whiz bang boom |
| '""")); |
| }); |
| |
| test('highlights the full last line at the end of the file', () { |
| expect(file.span(4, 39).highlight(), equals(r""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| 3 | \ zip zap zop |
| '""")); |
| }); |
| |
| test( |
| 'highlights the full last line at the end of the file with no trailing ' |
| 'newline', () { |
| final file = SourceFile.fromString(''' |
| foo bar baz |
| whiz bang boom |
| zip zap zop'''); |
| |
| expect(file.span(4, 38).highlight(), equals(r""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| 3 | \ zip zap zop |
| '""")); |
| }); |
| |
| test("highlights the full last line if it's empty", () { |
| final file = SourceFile.fromString(''' |
| foo |
| |
| bar |
| '''); |
| |
| expect(file.span(0, 5).highlight(), equals(r""" |
| , |
| 1 | / foo |
| 2 | \ |
| '""")); |
| }); |
| |
| test('highlights multiple empty lines', () { |
| final file = SourceFile.fromString('foo\n\n\n\nbar'); |
| expect(file.span(4, 7).highlight(), equals(r""" |
| , |
| 2 | / |
| 3 | | |
| 4 | \ |
| '""")); |
| }); |
| |
| // Regression test for #32 |
| test('highlights the end of a line and an empty line', () { |
| final file = SourceFile.fromString('foo\n\n'); |
| expect(file.span(3, 5).highlight(), equals(r""" |
| , |
| 1 | foo |
| | ,----^ |
| 2 | \ |
| '""")); |
| }); |
| }); |
| |
| group('prints tabs as spaces', () { |
| group('in a single-line span', () { |
| test('before the highlighted section', () { |
| final span = SourceFile.fromString('foo\tbar baz').span(4, 7); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| |
| test('within the highlighted section', () { |
| final span = SourceFile.fromString('foo bar\tbaz bang').span(4, 11); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz bang |
| | ^^^^^^^^^^ |
| '""")); |
| }); |
| |
| test('after the highlighted section', () { |
| final span = SourceFile.fromString('foo bar\tbaz').span(4, 7); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| }); |
| |
| group('in a multi-line span', () { |
| test('before the highlighted section', () { |
| final span = SourceFile.fromString(''' |
| foo\tbar baz |
| whiz bang boom |
| ''').span(4, 21); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,--------^ |
| 2 | | whiz bang boom |
| | '---------^ |
| '""")); |
| }); |
| |
| test('within the first highlighted line', () { |
| final span = SourceFile.fromString(''' |
| foo bar\tbaz |
| whiz bang boom |
| ''').span(4, 21); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| | '---------^ |
| '""")); |
| }); |
| |
| test('at the beginning of the first highlighted line', () { |
| final span = SourceFile.fromString(''' |
| foo bar\tbaz |
| whiz bang boom |
| ''').span(7, 21); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,--------^ |
| 2 | | whiz bang boom |
| | '---------^ |
| '""")); |
| }); |
| |
| test('within a middle highlighted line', () { |
| final span = SourceFile.fromString(''' |
| foo bar baz |
| whiz\tbang boom |
| zip zap zop |
| ''').span(4, 34); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| 3 | | zip zap zop |
| | '-------^ |
| '""")); |
| }); |
| |
| test('within the last highlighted line', () { |
| final span = SourceFile.fromString(''' |
| foo bar baz |
| whiz\tbang boom |
| ''').span(4, 21); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| | '------------^ |
| '""")); |
| }); |
| |
| test('at the end of the last highlighted line', () { |
| final span = SourceFile.fromString(''' |
| foo bar baz |
| whiz\tbang boom |
| ''').span(4, 17); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| | '--------^ |
| '""")); |
| }); |
| |
| test('after the highlighted section', () { |
| final span = SourceFile.fromString(''' |
| foo bar baz |
| whiz bang\tboom |
| ''').span(4, 21); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | foo bar baz |
| | ,-----^ |
| 2 | | whiz bang boom |
| | '---------^ |
| '""")); |
| }); |
| }); |
| }); |
| |
| group('supports lines of preceding and following context for a span', () { |
| test('within a single line', () { |
| final span = SourceSpanWithContext( |
| SourceLocation(20, line: 2, column: 5, sourceUrl: 'foo.dart'), |
| SourceLocation(27, line: 2, column: 12, sourceUrl: 'foo.dart'), |
| 'foo bar', |
| 'previous\nlines\n-----foo bar-----\nfollowing line\n'); |
| |
| expect(span.highlight(), equals(""" |
| , |
| 1 | previous |
| 2 | lines |
| 3 | -----foo bar----- |
| | ^^^^^^^ |
| 4 | following line |
| '""")); |
| }); |
| |
| test('covering a full line', () { |
| final span = SourceSpanWithContext( |
| SourceLocation(15, line: 2, column: 0, sourceUrl: 'foo.dart'), |
| 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', () { |
| final span = SourceSpanWithContext( |
| SourceLocation(15, line: 2, column: 0, sourceUrl: 'foo.dart'), |
| SourceLocation(23, line: 4, column: 0, sourceUrl: 'foo.dart'), |
| 'foo\nbar\n', |
| 'previous\nlines\nfoo\nbar\nfollowing line\n'); |
| |
| expect(span.highlight(), equals(r""" |
| , |
| 1 | previous |
| 2 | lines |
| 3 | / foo |
| 4 | \ bar |
| 5 | following line |
| '""")); |
| }); |
| }); |
| |
| group('colors', () { |
| test("doesn't colorize if color is false", () { |
| expect(file.span(4, 7).highlight(color: false), equals(""" |
| , |
| 1 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| |
| test('colorizes if color is true', () { |
| expect(file.span(4, 7).highlight(color: true), equals(''' |
| ${colors.blue} ,${colors.none} |
| ${colors.blue}1 |${colors.none} foo ${colors.red}bar${colors.none} baz |
| ${colors.blue} |${colors.none} ${colors.red} ^^^${colors.none} |
| ${colors.blue} '${colors.none}''')); |
| }); |
| |
| test("uses the given color if it's passed", () { |
| expect(file.span(4, 7).highlight(color: colors.yellow), equals(''' |
| ${colors.blue} ,${colors.none} |
| ${colors.blue}1 |${colors.none} foo ${colors.yellow}bar${colors.none} baz |
| ${colors.blue} |${colors.none} ${colors.yellow} ^^^${colors.none} |
| ${colors.blue} '${colors.none}''')); |
| }); |
| |
| test('colorizes a multiline span', () { |
| expect(file.span(4, 34).highlight(color: true), equals(''' |
| ${colors.blue} ,${colors.none} |
| ${colors.blue}1 |${colors.none} foo ${colors.red}bar baz${colors.none} |
| ${colors.blue} |${colors.none} ${colors.red},${colors.none}${colors.red}-----^${colors.none} |
| ${colors.blue}2 |${colors.none} ${colors.red}|${colors.none} ${colors.red}whiz bang boom${colors.none} |
| ${colors.blue}3 |${colors.none} ${colors.red}|${colors.none} ${colors.red}zip zap${colors.none} zop |
| ${colors.blue} |${colors.none} ${colors.red}'${colors.none}${colors.red}-------^${colors.none} |
| ${colors.blue} '${colors.none}''')); |
| }); |
| |
| test('colorizes a multiline span that highlights full lines', () { |
| expect(file.span(0, 39).highlight(color: true), equals(''' |
| ${colors.blue} ,${colors.none} |
| ${colors.blue}1 |${colors.none} ${colors.red}/${colors.none} ${colors.red}foo bar baz${colors.none} |
| ${colors.blue}2 |${colors.none} ${colors.red}|${colors.none} ${colors.red}whiz bang boom${colors.none} |
| ${colors.blue}3 |${colors.none} ${colors.red}\\${colors.none} ${colors.red}zip zap zop${colors.none} |
| ${colors.blue} '${colors.none}''')); |
| }); |
| }); |
| |
| group('line numbers have appropriate padding', () { |
| test('with line number 9', () { |
| expect( |
| SourceFile.fromString('\n' * 8 + 'foo bar baz\n') |
| .span(8, 11) |
| .highlight(), |
| equals(""" |
| , |
| 9 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| |
| test('with line number 10', () { |
| expect( |
| SourceFile.fromString('\n' * 9 + 'foo bar baz\n') |
| .span(9, 12) |
| .highlight(), |
| equals(""" |
| , |
| 10 | foo bar baz |
| | ^^^ |
| '""")); |
| }); |
| }); |
| } |