@@ -390,6 +390,108 @@ class DiagnosticConsoleWriterDefaultFormattingTest: XCTestCase {
390
390
}
391
391
}
392
392
393
+ func testClampsDiagnosticRangeToSourceRange( ) throws {
394
+ let fs = try TestFileSystem ( folders: [
395
+ Folder ( name: " Something.docc " , content: [
396
+ TextFile ( name: " Article.md " , utf8Content: """
397
+ # Title
398
+
399
+ A very short article with only an abstract.
400
+ """ )
401
+ ] )
402
+ ] )
403
+
404
+ let summary = " Test diagnostic summary "
405
+ let explanation = " Test diagnostic explanation. "
406
+
407
+ let bundle = try XCTUnwrap ( fs. bundles ( ) . first)
408
+ let baseURL = bundle. baseURL
409
+ let source = try XCTUnwrap ( bundle. markupURLs. first)
410
+
411
+ typealias Location = ( line: Int , column: Int )
412
+ func logMessageFor( start: Location , end: Location ) throws -> String {
413
+ let range = SourceLocation ( line: start. line, column: start. column, source: source) ..< SourceLocation ( line: end. line, column: end. column, source: source)
414
+
415
+ let logStorage = LogHandle . LogStorage ( )
416
+ let consumer = DiagnosticConsoleWriter ( LogHandle . memory ( logStorage) , baseURL: baseURL, highlight: true , fileManager: fs)
417
+
418
+ let diagnostic = Diagnostic ( source: source, severity: . warning, range: range, identifier: " org.swift.docc.test-identifier " , summary: summary, explanation: explanation)
419
+ consumer. receive ( [ Problem ( diagnostic: diagnostic, possibleSolutions: [ ] ) ] )
420
+ try consumer. flush ( )
421
+
422
+ // There are no lines before line 1
423
+ return logStorage. text
424
+ }
425
+
426
+ // Highlight the "Title" word on line 1
427
+ XCTAssertEqual ( try logMessageFor ( start: ( line: 1 , column: 3 ) , end: ( line: 1 , column: 8 ) ) , """
428
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
429
+ \( explanation)
430
+ --> Something.docc/Article.md:1:3-1:8
431
+ 1 + # \u{001B} [1;32mTitle \u{001B} [0;0m
432
+ 2 |
433
+ 3 | A very short article with only an abstract.
434
+ """ )
435
+
436
+ // Highlight the "short" word on line 3
437
+ XCTAssertEqual ( try logMessageFor ( start: ( line: 3 , column: 8 ) , end: ( line: 3 , column: 13 ) ) , """
438
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
439
+ \( explanation)
440
+ --> Something.docc/Article.md:3:8-3:13
441
+ 1 | # Title
442
+ 2 |
443
+ 3 + A very \u{001B} [1;32mshort \u{001B} [0;0m article with only an abstract.
444
+ """ )
445
+
446
+ // Extend the highlight beyond the end of that line
447
+ XCTAssertEqual ( try logMessageFor ( start: ( line: 3 , column: 8 ) , end: ( line: 3 , column: 100 ) ) , """
448
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
449
+ \( explanation)
450
+ --> Something.docc/Article.md:3:8-3:100
451
+ 1 | # Title
452
+ 2 |
453
+ 3 + A very \u{001B} [1;32mshort article with only an abstract. \u{001B} [0;0m
454
+ """ )
455
+
456
+ // Extend the highlight beyond the start of that line
457
+ XCTAssertEqual ( try logMessageFor ( start: ( line: 3 , column: - 4 ) , end: ( line: 3 , column: 13 ) ) , """
458
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
459
+ \( explanation)
460
+ --> Something.docc/Article.md:3:1-3:13
461
+ 1 | # Title
462
+ 2 |
463
+ 3 + \u{001B} [1;32mA very short \u{001B} [0;0m article with only an abstract.
464
+ """ )
465
+
466
+ // Highlight a line before the start of the file
467
+ XCTAssertEqual ( try logMessageFor ( start: ( line: - 4 , column: 1 ) , end: ( line: - 4 , column: 5 ) ) , """
468
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
469
+ \( explanation)
470
+ --> Something.docc/Article.md:1:1-1:5
471
+ """ )
472
+
473
+ // Highlight a line after the end of the file
474
+ XCTAssertEqual ( try logMessageFor ( start: ( line: 100 , column: 1 ) , end: ( line: 100 , column: 5 ) ) , """
475
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
476
+ \( explanation)
477
+ --> Something.docc/Article.md:100:1-100:5
478
+ """ )
479
+
480
+ // Extended the highlighted lines before the start of the file
481
+ XCTAssertEqual ( try logMessageFor ( start: ( line: - 4 , column: 1 ) , end: ( line: 1 , column: 5 ) ) , """
482
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
483
+ \( explanation)
484
+ --> Something.docc/Article.md:1:1-1:5
485
+ """ )
486
+
487
+ // Extended the highlighted lines after the end of the file
488
+ XCTAssertEqual ( try logMessageFor ( start: ( line: 1 , column: 1 ) , end: ( line: 100 , column: 5 ) ) , """
489
+ \u{001B} [1;33mwarning: \( summary) \u{001B} [0;0m
490
+ \( explanation)
491
+ --> Something.docc/Article.md:1:1-100:5
492
+ """ )
493
+ }
494
+
393
495
func testEmitAdditionReplacementSolution( ) throws {
394
496
func problemsLoggerOutput( possibleSolutions: [ Solution ] ) -> String {
395
497
let logger = Logger ( )
@@ -399,8 +501,8 @@ class DiagnosticConsoleWriterDefaultFormattingTest: XCTestCase {
399
501
try ? consumer. flush ( )
400
502
return logger. output
401
503
}
402
- let sourcelocation = SourceLocation ( line: 1 , column: 1 , source: nil )
403
- let range = sourcelocation ..< sourcelocation
504
+ let sourceLocation = SourceLocation ( line: 1 , column: 1 , source: nil )
505
+ let range = sourceLocation ..< sourceLocation
404
506
XCTAssertEqual (
405
507
problemsLoggerOutput ( possibleSolutions: [
406
508
Solution ( summary: " Create a sloth. " , replacements: [
0 commit comments