Skip to content

Commit 020a20b

Browse files
committed
Code coverage: 99%
1 parent 8226a15 commit 020a20b

File tree

6 files changed

+117
-137
lines changed

6 files changed

+117
-137
lines changed

Sources/swift-doc-coverage/main.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,7 @@ struct SwiftDocCoverage: ParsableCommand {
229229
}()
230230

231231
static func string(from timeInterval: TimeInterval) -> String {
232-
guard var time = dateFormatter.string(from: timeInterval) else {
233-
return ""
234-
}
232+
var time = dateFormatter.string(from: timeInterval)!
235233

236234
guard let fraction = String(format: "%.3f", timeInterval).split(separator: ".").last, fraction != "000" else {
237235
return time
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// An absolute position in a source file as text - the absolute utf8Offset from
14+
/// the start of the file.
15+
public struct AbsolutePosition: Comparable, Hashable {
16+
public let utf8Offset: Int
17+
18+
static let startOfFile = AbsolutePosition(utf8Offset: 0)
19+
20+
public init(utf8Offset: Int) {
21+
self.utf8Offset = utf8Offset
22+
}
23+
24+
public func advanced(by offset: Int) -> AbsolutePosition {
25+
return AbsolutePosition(utf8Offset: self.utf8Offset + offset)
26+
}
27+
28+
public static func < (lhs: AbsolutePosition, rhs: AbsolutePosition) -> Bool {
29+
return lhs.utf8Offset < rhs.utf8Offset
30+
}
31+
}

Tests/SwiftDocCoverageTests/Resources/Rect/AlternativeRect.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

Tests/SwiftDocCoverageTests/Resources/Rect/CompactRect.swift

Lines changed: 0 additions & 18 deletions
This file was deleted.

Tests/SwiftDocCoverageTests/Resources/Rect/Rect.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import Foundation
22

33
/// Doc line
4-
public struct Rect {
4+
open struct Rect {
5+
fileprivate let index = 0
6+
57
/** Doc block */
6-
public var origin = Point()
8+
private var origin = Point()
79

8-
// Line
9-
public var size = Size()
10+
// Comment line
11+
var size = Size()
1012

11-
/* Block */
13+
/* Comment block */
1214
public var center: Point {
1315
get {
1416
let centerX = origin.x + (size.width / 2)

Tests/SwiftDocCoverageTests/SwiftDocCoverageTests.swift

Lines changed: 78 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ func createTempDirectory() -> URL {
1010
return url
1111
}
1212

13+
let resourcesUrl = Bundle.module.url(forResource: "Resources", withExtension: nil, subdirectory: nil)!
14+
let rectUrl = Bundle.module.url(forResource: "Rect", withExtension: "swift", subdirectory: "Resources/Rect")!
15+
let sizeUrl = Bundle.module.url(forResource: "Size", withExtension: "swift", subdirectory: "Resources")!
16+
let readmeUrl = Bundle.module.url(forResource: "README", withExtension: "md", subdirectory: "Resources")!
17+
1318
final class SourceCodeTests: XCTestCase {
1419

1520
func test_typealias() {
@@ -420,30 +425,20 @@ final class SourceCodeTests: XCTestCase {
420425
final class SourceFileTests: XCTestCase {
421426

422427
func test_no_file() {
423-
let directoryURL = Bundle.module.url(forResource: "Resources", withExtension: nil, subdirectory: nil)!
424-
let fileURL = directoryURL.appendingPathComponent("File.swift")
428+
let fileURL = resourcesUrl.appendingPathComponent("File.swift")
425429
XCTAssertThrowsError(try SwiftSource(fileURL: fileURL)) { error in
426430
XCTAssert(error.localizedDescription == "The file “File.swift” couldn’t be opened because there is no such file.")
427431
}
428432
}
429433

430434
func test_file() throws {
431-
let fileURL = Bundle.module.url(forResource: "Rect", withExtension: "swift", subdirectory: "Resources/Rect")!
432-
let source = try SwiftSource(fileURL: fileURL)
433-
XCTAssert(source.declarations.count == 4)
435+
let source = try SwiftSource(fileURL: rectUrl)
436+
XCTAssert(source.declarations.count == 5)
434437
}
435438
}
436439

437440
final class SwiftDocCoverageTests: XCTestCase {
438441

439-
lazy var executableURL: URL = {
440-
Bundle(for: Self.self).bundleURL.deletingLastPathComponent().appendingPathComponent("swift-doc-coverage")
441-
}()
442-
443-
let rectFileURL = Bundle.module.url(forResource: "Rect", withExtension: "swift", subdirectory: "Resources/Rect")!
444-
let compactRectFileURL = Bundle.module.url(forResource: "CompactRect", withExtension: "swift", subdirectory: "Resources/Rect")!
445-
let alternativeRectFileURL = Bundle.module.url(forResource: "AlternativeRect", withExtension: "swift", subdirectory: "Resources/Rect")!
446-
447442
func test_no_params() throws {
448443
XCTAssertThrowsError(try SwiftDocCoverage.run()) { error in
449444
// Error: Missing expected argument '<inputs> ...'
@@ -465,79 +460,101 @@ final class SwiftDocCoverageTests: XCTestCase {
465460
}
466461
}
467462

468-
func test_access_levels() throws {
469-
XCTAssertThrowsError(try SwiftDocCoverage.run(rectFileURL.path, "--minimum-access-level", "open")) { error in
463+
func test_not_swift_file() throws {
464+
XCTAssertThrowsError(try SwiftDocCoverage.run(readmeUrl.path)) { error in
465+
XCTAssert(error.localizedDescription == Errors.notSwiftFile.rawValue)
466+
}
467+
}
468+
469+
func test_declarations_not_found() throws {
470+
XCTAssertThrowsError(try SwiftDocCoverage.run(sizeUrl.path, "--minimum-access-level", "open")) { error in
470471
XCTAssert(error.localizedDescription == Errors.declarationsNotFound.rawValue)
471472
}
473+
}
474+
475+
func test_access_levels() throws {
476+
var cmd = try SwiftDocCoverage.run(rectUrl.path, "--minimum-access-level", "open")
477+
XCTAssert(cmd.sources.count == 1)
478+
XCTAssert(cmd.sources[0].declarations.count == 5)
479+
XCTAssert(cmd.sources[0].declarations(level: .open).count == 1)
472480

473-
var cmd = try SwiftDocCoverage.run(rectFileURL.path, "--minimum-access-level", "public")
481+
cmd = try SwiftDocCoverage.run(rectUrl.path, "--minimum-access-level", "public")
474482
XCTAssert(cmd.sources.count == 1)
475-
XCTAssert(cmd.sources[0].declarations.count == 4)
476-
XCTAssert(cmd.sources[0].declarations(level: .public).count == 4)
483+
XCTAssert(cmd.sources[0].declarations(level: .public).count == 2)
477484

478-
cmd = try SwiftDocCoverage.run(compactRectFileURL.path, "--minimum-access-level", "internal")
485+
cmd = try SwiftDocCoverage.run(rectUrl.path, "--minimum-access-level", "internal")
479486
XCTAssert(cmd.sources.count == 1)
480-
XCTAssert(cmd.sources[0].declarations.count == 4)
481-
XCTAssert(cmd.sources[0].declarations(level: .internal).count == 4)
487+
XCTAssert(cmd.sources[0].declarations(level: .internal).count == 3)
482488

483-
cmd = try SwiftDocCoverage.run(alternativeRectFileURL.path, "--minimum-access-level", "fileprivate")
489+
cmd = try SwiftDocCoverage.run(rectUrl.path, "--minimum-access-level", "fileprivate")
484490
XCTAssert(cmd.sources.count == 1)
485-
XCTAssert(cmd.sources[0].declarations.count == 4)
486-
XCTAssert(cmd.sources[0].declarations(level: .fileprivate).count == 3)
491+
XCTAssert(cmd.sources[0].declarations(level: .fileprivate).count == 4)
487492

488-
cmd = try SwiftDocCoverage.run(alternativeRectFileURL.path, "--minimum-access-level", "private")
493+
cmd = try SwiftDocCoverage.run(rectUrl.path, "--minimum-access-level", "private")
489494
XCTAssert(cmd.sources.count == 1)
490-
XCTAssert(cmd.sources[0].declarations.count == 4)
491-
XCTAssert(cmd.sources[0].declarations(level: .private).count == 4)
495+
XCTAssert(cmd.sources[0].declarations(level: .private).count == 5)
496+
}
497+
498+
func test_ignore_filename_regex() throws {
499+
let cmd = try SwiftDocCoverage.run(resourcesUrl.path, "--ignore-filename-regex", "Rect.swift")
500+
XCTAssert(cmd.sources.count == 2)
501+
502+
XCTAssert(cmd.sources[0].url?.lastPathComponent == "Size.swift")
503+
XCTAssert(cmd.sources[0].declarations.count == 2)
504+
505+
XCTAssert(cmd.sources[1].url?.lastPathComponent == "Point.swift")
506+
XCTAssert(cmd.sources[1].declarations.count == 2)
492507
}
493508

494509
func test_warnings() throws {
495510
let output = Output()
496-
_ = try SwiftDocCoverage.run(output: output, rectFileURL.path, "--report", "warnings")
497-
XCTAssert(output.buffer.contains("Rect.swift:9:3: warning: No documentation for 'var Rect.size'.") == true)
498-
XCTAssert(output.buffer.contains("Rect.swift:12:3: warning: No documentation for 'var Rect.center'.") == true)
511+
_ = try SwiftDocCoverage.run(output: output, rectUrl.path, "--report", "warnings")
512+
XCTAssert(output.buffer.contains("Rect.swift:14:3: warning: No documentation for 'var Rect.center'.") == true)
499513
}
500514

501515
func test_json() throws {
502516
let output = Output()
503-
_ = try SwiftDocCoverage.run(output: output, rectFileURL.path, "--report", "json")
517+
_ = try SwiftDocCoverage.run(output: output, rectUrl.path, "--report", "json")
504518
let sources = try JSONDecoder().decode([SwiftSource].self, from: output.buffer.data(using: .utf8)!)
505519
XCTAssert(sources.count == 1)
506-
XCTAssert(sources[0].declarations.count == 4)
507-
}
508-
509-
func test_file() throws {
510-
let cmd = try SwiftDocCoverage.run(rectFileURL.path)
511-
XCTAssert(cmd.sources.count == 1)
512-
XCTAssert(cmd.sources[0].declarations.count == 4)
520+
XCTAssert(sources[0].declarations.count == 5)
513521
}
514522

515523
func test_directory() throws {
516-
let directoryURL = Bundle.module.url(forResource: "Resources", withExtension: nil, subdirectory: nil)!
517-
518-
let cmd = try SwiftDocCoverage.run(directoryURL.path)
524+
let cmd = try SwiftDocCoverage.run(resourcesUrl.path)
519525

520-
XCTAssert(cmd.sources.count == 5)
526+
XCTAssert(cmd.sources.count == 3)
521527

522528
XCTAssert(cmd.sources[0].url?.lastPathComponent == "Rect.swift")
523-
XCTAssert(cmd.sources[0].declarations.count == 4)
529+
XCTAssert(cmd.sources[0].declarations.count == 5)
524530

525-
XCTAssert(cmd.sources[1].url?.lastPathComponent == "CompactRect.swift")
526-
XCTAssert(cmd.sources[1].declarations.count == 4)
531+
XCTAssert(cmd.sources[1].url?.lastPathComponent == "Size.swift")
532+
XCTAssert(cmd.sources[1].declarations.count == 2)
527533

528-
XCTAssert(cmd.sources[2].url?.lastPathComponent == "AlternativeRect.swift")
529-
XCTAssert(cmd.sources[2].declarations.count == 4)
534+
XCTAssert(cmd.sources[2].url?.lastPathComponent == "Point.swift")
535+
XCTAssert(cmd.sources[2].declarations.count == 2)
536+
}
537+
538+
func test_skips_hidden_files_false() throws {
539+
let cmd = try SwiftDocCoverage.run(resourcesUrl.path, "--skips-hidden-files", "false")
540+
XCTAssert(cmd.sources.count == 4)
530541

531-
XCTAssert(cmd.sources[3].url?.lastPathComponent == "Size.swift")
532-
XCTAssert(cmd.sources[3].declarations.count == 2)
542+
XCTAssert(cmd.sources[0].url?.lastPathComponent == "AbsolutePosition.swift")
543+
XCTAssert(cmd.sources[0].declarations.count == 6)
544+
545+
XCTAssert(cmd.sources[1].url?.lastPathComponent == "Rect.swift")
546+
XCTAssert(cmd.sources[1].declarations.count == 5)
533547

534-
XCTAssert(cmd.sources[4].url?.lastPathComponent == "Point.swift")
535-
XCTAssert(cmd.sources[4].declarations.count == 2)
548+
XCTAssert(cmd.sources[2].url?.lastPathComponent == "Size.swift")
549+
XCTAssert(cmd.sources[2].declarations.count == 2)
550+
551+
XCTAssert(cmd.sources[3].url?.lastPathComponent == "Point.swift")
552+
XCTAssert(cmd.sources[3].declarations.count == 2)
536553
}
537554

538555
func test_output() throws {
539556
let output = Output()
540-
_ = try SwiftDocCoverage.run(output: output, rectFileURL.path)
557+
_ = try SwiftDocCoverage.run(output: output, rectUrl.path)
541558
XCTAssert(output.buffer.contains("Total: 50%"))
542559
}
543560

@@ -546,14 +563,14 @@ final class SwiftDocCoverageTests: XCTestCase {
546563
let url = tempDir.appendingPathComponent("temp/report.txt")
547564
defer { try? FileManager.default.removeItem(at: tempDir) }
548565

549-
_ = try SwiftDocCoverage.run(rectFileURL.path, "--output", url.path)
566+
_ = try SwiftDocCoverage.run(rectUrl.path, "--output", url.path)
550567

551568
let text = try String(contentsOf: url)
552569
XCTAssert(text.contains("Total: 50%"))
553570
}
554571

555572
func test_output_file_cant_open() {
556-
XCTAssertThrowsError(try SwiftDocCoverage.run(rectFileURL.path, "--output", "/report.txt")) { error in
573+
XCTAssertThrowsError(try SwiftDocCoverage.run(rectUrl.path, "--output", "/report.txt")) { error in
557574
XCTAssert(error.localizedDescription == Errors.cantOpenFile.rawValue)
558575
}
559576
}
@@ -591,47 +608,14 @@ extension Process {
591608

592609
final class ToolProcessTests: XCTestCase {
593610

594-
func test_output() throws {
595-
// let process = Process()
596-
// let output = try process.run(executableURL, arguments: [fileURL.path])
597-
//
598-
// XCTAssert(process.terminationStatus == EXIT_SUCCESS)
599-
// XCTAssert(output.contains("Total: 50%"))
600-
}
601-
602-
func test_warninigs() throws {
603-
// let process = Process()
604-
// let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path, "--report", "warnings"])
605-
// XCTAssert(process.terminationStatus == EXIT_SUCCESS)
606-
// XCTAssert(output.contains("warning: No documentation for 'Rect.size'."))
607-
}
611+
lazy var executableURL: URL = { Bundle(for: Self.self).bundleURL.deletingLastPathComponent().appendingPathComponent("swift-doc-coverage") }()
608612

609-
func test_json() throws {
610-
// let process = Process()
611-
// let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path, "--report", "json"])
612-
// XCTAssert(process.terminationStatus == EXIT_SUCCESS)
613-
//
614-
// if let data = output.data(using: .utf8),
615-
// let json = try JSONSerialization.jsonObject(with: data) as? [String : Any] {
616-
// XCTAssert(json["sources"] != nil)
617-
// }
618-
// else {
619-
// XCTFail()
620-
// }
621-
}
622-
623-
func test_file_output() throws {
624-
// let tempDirectory = createTempDirectory()
625-
// let outputFileURL = tempDirectory.appendingPathComponent("report.txt")
626-
// defer { try? FileManager.default.removeItem(at: tempDirectory) }
627-
//
628-
// let process = Process()
629-
// let output = try process.run(executableURL, arguments: [fileURL.path, "--output", outputFileURL.path])
630-
// XCTAssert(process.terminationStatus == EXIT_SUCCESS)
631-
// XCTAssert(output.isEmpty)
632-
//
633-
// let text = try String(contentsOf: outputFileURL)
634-
// XCTAssert(text.contains("Total: 50%"))
613+
func test_process() throws {
614+
let process = Process()
615+
let output = try process.run(executableURL, arguments: [rectUrl.path])
616+
617+
XCTAssert(process.terminationStatus == EXIT_SUCCESS)
618+
XCTAssert(output.contains("Total: 50%"))
635619
}
636620
}
637621

0 commit comments

Comments
 (0)