Skip to content

Commit

Permalink
Code coverage: SwiftSource 100%
Browse files Browse the repository at this point in the history
  • Loading branch information
ikhvorost committed Feb 26, 2024
1 parent 5b1a9fc commit 02776d0
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 127 deletions.
4 changes: 3 additions & 1 deletion Sources/SwiftSource/DeclProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ extension SubscriptDeclSyntax: DeclProtocol {
}

extension VariableDeclSyntax: DeclProtocol {
var keyword: SwiftKeyword { SwiftKeyword(token: bindingSpecifier)! }
var keyword: SwiftKeyword {
bindingSpecifier.trimmedDescription == "let" ? .let : .var
}

var name: TokenSyntax {
let name = bindings.map { $0.pattern.trimmedDescription }.joined(separator: ",")
Expand Down
43 changes: 22 additions & 21 deletions Sources/SwiftSource/SwiftAccessLevel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,32 @@ public enum SwiftAccessLevel: Int {
case `fileprivate`
case `private`

init?(token: TokenSyntax) {
guard case .keyword(let keyword) = token.tokenKind else {
return nil
}

switch keyword {
case .open: self = .open
case .public: self = .public
case .internal: self = .internal
case .fileprivate: self = .fileprivate
case .private: self = .private
default: return nil
}
}

init(modifiers: DeclModifierListSyntax) {
init(modifiers: DeclModifierListSyntax) {
for modifier in modifiers {
// Skip private(set) etc.
guard modifier.detail == nil else {
guard modifier.detail == nil, // Skip private(set) etc.
case .keyword(let keyword) = modifier.name.tokenKind
else {
continue
}

if let accessLevel = SwiftAccessLevel(token: modifier.name) {
self = accessLevel
return
switch keyword {
case .open:
self = .open
return
case .public:
self = .public
return
case .internal:
self = .internal
return
case .fileprivate:
self = .fileprivate
return
case .private:
self = .private
return
default:
break
}
}
self = .internal
Expand Down
27 changes: 0 additions & 27 deletions Sources/SwiftSource/SwiftKeyword.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,4 @@ public enum SwiftKeyword: String {
case `subscript`
case `typealias`
case `var`

init?(token: TokenSyntax) {
guard case .keyword(let keyword) = token.tokenKind else {
return nil
}

switch keyword {
case .actor: self = .actor
case .associatedtype: self = .associatedtype
case .case: self = .case
case .class: self = .class
case .enum: self = .enum
case .extension: self = .extension
case .func: self = .func
//case .import:
case .`init`: self = .`init`
case .let: self = .let
case .macro: self = .macro
case .precedencegroup: self = .precedencegroup
case .protocol: self = .protocol
case .struct: self = .struct
case .subscript: self = .subscript
case .typealias: self = .typealias
case .var: self = .var
default: return nil
}
}
}
6 changes: 3 additions & 3 deletions Sources/SwiftSource/SwiftSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public struct SwiftSource {
self.init(url: nil, source: source)
}

public init(url: URL) throws {
let source = try String(contentsOf: url)
self.init(url: url, source: source)
public init(fileURL: URL) throws {
let source = try String(contentsOf: fileURL)
self.init(url: fileURL, source: source)
}
}
2 changes: 1 addition & 1 deletion Sources/swift-doc-coverage/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ struct SwiftDocCoverage: ParsableCommand {
let sources: [SwiftSource] = try urls.map { url in
let sourceTime = Date()

let source = try SwiftSource(url: url)
let source = try SwiftSource(fileURL: url)

if report != .json {
let declarations = source.declarations.filter { $0.accessLevel.rawValue <= minAccessLevel }
Expand Down
186 changes: 112 additions & 74 deletions Tests/SwiftDocCoverageTests/SwiftDocCoverageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,18 @@ final class DeclarationTests: XCTestCase {
XCTAssert(source.declarations[5].name == "enum Planet<Item>")
}

func test_macro() {
let code =
"""
@attached(member, names: named(_registerModule), named(moduleName), named(requiresMainQueueSetup), named(methodQueue))
public macro ReactView(jsName: String? = nil) = #externalMacro(module: "ReactBridgeMacros", type: "ReactView")
"""
let source = SwiftSource(source: code)
XCTAssert(source.declarations.count == 1)
XCTAssert(source.declarations[0].name == "macro ReactView(jsName: String? = nil)")
XCTAssert(source.declarations[0].accessLevel == .public)
}

func test_precedencegroup_operator() {
let code =
"""
Expand Down Expand Up @@ -358,13 +370,30 @@ final class DeclarationTests: XCTestCase {
XCTAssert(source.declarations[10].accessLevel == .internal)
XCTAssert(source.declarations[11].accessLevel == .internal)
}

func test_multilines() {
let code =
"""
func greet(
id: Number,
person: String,
text: String) -> String
{
person + text
}
"""
let source = SwiftSource(source: code)
XCTAssert(source.declarations.count == 1)
XCTAssert(source.declarations[0].name == "func greet( id: Number, person: String, text: String) -> String")
}
}

final class DocumentationTests: XCTestCase {
final class DocTests: XCTestCase {

func test_no_comments() {
let code =
"""
public func eat(_ food: Food, quantity: Int) throws -> Int { return 0 }
"""
let source = SwiftSource(source: code)
Expand All @@ -378,7 +407,9 @@ final class DocumentationTests: XCTestCase {
// A developer line comment
/* A developer block comment */
/// A documentation line comment
/** A documentation block comment */
/** A documentation
block comment */
mutating public func eat(_ food: Food, quantity: Int) throws -> Int { return 0 }
"""
let source = SwiftSource(source: code)
Expand All @@ -387,73 +418,27 @@ final class DocumentationTests: XCTestCase {
XCTAssert(source.declarations[0].comments[0].text == "// A developer line comment")
XCTAssert(source.declarations[0].comments[1].text == "/* A developer block comment */")
XCTAssert(source.declarations[0].comments[2].text == "/// A documentation line comment")
XCTAssert(source.declarations[0].comments[3].text == "/** A documentation block comment */")
XCTAssert(source.declarations[0].comments[3].text == "/** A documentation \nblock comment */")
}
}

final class FileTests: XCTestCase {

static let directoryURL = Bundle.module.url(forResource: "Resources", withExtension: nil, subdirectory: nil)!
static let fileURL = directoryURL.appendingPathComponent("Rect/Rect.swift")
static let readmeURL = directoryURL.appendingPathComponent("README.md")
static let emptyDirURL = directoryURL.appendingPathComponent("Empty")

func test_file() throws {
let source = try SwiftSource(url: Self.fileURL)
XCTAssert(source.declarations.count == 4)
}

func test_not_found() throws {
// XCTAssertThrowsError(try Coverage(paths: [Self.directoryURL.appendingPathComponent("NotFound").path])) { error in
// XCTAssert(error.localizedDescription == "Path not found.")
// }
}

func test_not_swift_file() throws {
// XCTAssertThrowsError(try Coverage(paths: [Self.readmeURL.path])) { error in
// XCTAssert(error.localizedDescription == "Not swift file.")
// }
}
//static let readmeURL = directoryURL.appendingPathComponent("README.md")
//static let emptyDirURL = directoryURL.appendingPathComponent("Empty")

func test_no_declarations() throws {
// let coverage = try Coverage(paths: [Self.fileURL.path], minAccessLevel: .open)
// XCTAssertThrowsError(try coverage.report()) { error in
// XCTAssert(error.localizedDescription == "Declarations not found.")
// }
}

func test_report() throws {
// let coverage = try Coverage(paths: [Self.fileURL.path])
// let report = try coverage.report()
//
// XCTAssert(report.totalCount == 4)
// XCTAssert(report.totalUndocumentedCount == 2)
// XCTAssert(report.sources.count == 1)
//
// try coverage.reportStatistics()
}

func test_empty_directory() throws {
// let tempDirectory = tempDirectory()
// defer { try? FileManager.default.removeItem(at: tempDirectory) }
//
// XCTAssertThrowsError(try Coverage(paths: [tempDirectory.path])) { error in
// XCTAssert(error.localizedDescription == "Swift files not found.")
// }
}

func test_directory() throws {
// let coverage = try Coverage(paths: [Self.directoryURL.path])
// let report = try coverage.report()
//
// XCTAssert(report.totalCount == 4)
// XCTAssert(report.totalUndocumentedCount == 2)
// print(report.sources.count == 1)
func test_no_file() throws {
let fileURL = URL(filePath: Self.directoryURL.appendingPathComponent("File.swift").path)
XCTAssertThrowsError(try SwiftSource(fileURL: fileURL)) { error in
XCTAssert(error.localizedDescription == "The file “File.swift” couldn’t be opened because there is no such file.")
}
}

func test_warnings() throws {
// let coverage = try Coverage(paths: [Self.fileURL.path])
// try coverage.reportWarnings()
func test_file() throws {
let source = try SwiftSource(fileURL: Self.fileURL)
XCTAssert(source.declarations.count == 4)
}
}

Expand Down Expand Up @@ -502,6 +487,54 @@ final class ToolTests: XCTestCase {
XCTAssert(process.terminationStatus == EXIT_FAILURE)
}

// func test_directory() throws {
// let coverage = try Coverage(paths: [Self.directoryURL.path])
// let report = try coverage.report()
//
// XCTAssert(report.totalCount == 4)
// XCTAssert(report.totalUndocumentedCount == 2)
// print(report.sources.count == 1)
// }

// func test_empty_directory() throws {
// let tempDirectory = tempDirectory()
// defer { try? FileManager.default.removeItem(at: tempDirectory) }
//
// XCTAssertThrowsError(try Coverage(paths: [tempDirectory.path])) { error in
// XCTAssert(error.localizedDescription == "Swift files not found.")
// }
// }

//func test_not_found() throws {
// XCTAssertThrowsError(try Coverage(paths: [Self.directoryURL.appendingPathComponent("NotFound").path])) { error in
// XCTAssert(error.localizedDescription == "Path not found.")
// }
//}

//func test_not_swift_file() throws {
// XCTAssertThrowsError(try Coverage(paths: [Self.readmeURL.path])) { error in
// XCTAssert(error.localizedDescription == "Not swift file.")
// }
//}

// func test_no_declarations() throws {
// let coverage = try Coverage(paths: [Self.fileURL.path], minAccessLevel: .open)
// XCTAssertThrowsError(try coverage.report()) { error in
// XCTAssert(error.localizedDescription == "Declarations not found.")
// }
// }

// func test_report() throws {
// let coverage = try Coverage(paths: [Self.fileURL.path])
// let report = try coverage.report()
//
// XCTAssert(report.totalCount == 4)
// XCTAssert(report.totalUndocumentedCount == 2)
// XCTAssert(report.sources.count == 1)
//
// try coverage.reportStatistics()
// }

func test_output() throws {
let process = Process()
let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path])
Expand All @@ -510,25 +543,30 @@ final class ToolTests: XCTestCase {
XCTAssert(output.contains("Total: 50%"))
}

// func test_warnings() throws {
// let coverage = try Coverage(paths: [Self.fileURL.path])
// try coverage.reportWarnings()
// }

func test_warninigs() throws {
let process = Process()
let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path, "--report", "warnings"])
XCTAssert(process.terminationStatus == EXIT_SUCCESS)
XCTAssert(output.contains("warning: No documentation for 'Rect.size'."))
// let process = Process()
// let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path, "--report", "warnings"])
// XCTAssert(process.terminationStatus == EXIT_SUCCESS)
// XCTAssert(output.contains("warning: No documentation for 'Rect.size'."))
}

func test_json() throws {
let process = Process()
let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path, "--report", "json"])
XCTAssert(process.terminationStatus == EXIT_SUCCESS)

if let data = output.data(using: .utf8),
let json = try JSONSerialization.jsonObject(with: data) as? [String : Any] {
XCTAssert(json["sources"] != nil)
}
else {
XCTFail()
}
// let process = Process()
// let output = try process.run(swiftDocCoverageURL, arguments: [fileURL.path, "--report", "json"])
// XCTAssert(process.terminationStatus == EXIT_SUCCESS)
//
// if let data = output.data(using: .utf8),
// let json = try JSONSerialization.jsonObject(with: data) as? [String : Any] {
// XCTAssert(json["sources"] != nil)
// }
// else {
// XCTFail()
// }
}

func test_file_output() throws {
Expand Down

0 comments on commit 02776d0

Please sign in to comment.