Skip to content

Commit

Permalink
Add Linux support (#9)
Browse files Browse the repository at this point in the history
* Add Linux support

* Do not use NSString's 'trimmingCharacters' API

* Special-case Linux with #if check

* Upload code coverage from Linux

* Use string interpolation instead of 'description' on errors in tests

* Remove unnecessary assertion
  • Loading branch information
dfed authored Jan 12, 2024
1 parent 484ee1e commit 4c83c05
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 22 deletions.
27 changes: 23 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: macos-13
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Select Xcode Version
run: sudo xcode-select --switch /Applications/Xcode_15.0.1.app/Contents/Developer
- name: Build and Test Framework
Expand All @@ -28,7 +28,7 @@ jobs:
runs-on: macos-13
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Select Xcode Version
run: sudo xcode-select --switch /Applications/Xcode_15.0.1.app/Contents/Developer
- name: Build Package Integration
Expand All @@ -39,17 +39,36 @@ jobs:
runs-on: macos-13
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Select Xcode Version
run: sudo xcode-select --switch /Applications/Xcode_15.0.1.app/Contents/Developer
- name: Build Project Integration
run: pushd Examples/ExampleProjectIntegration; xcrun xcodebuild build -skipPackagePluginValidation -skipMacroValidation -scheme ExampleProjectIntegration; popd

linux:
name: "Build and Test on Linux"
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Setup Swift Environment
uses: swift-actions/setup-swift@v1
with:
swift-version: 5.9
- name: Build and Test Framework
run: swift test -c release --enable-code-coverage -Xswiftc -enable-testing
- name: Prepare Coverage Reports
run: |
llvm-cov export -format="lcov" .build/x86_64-unknown-linux-gnu/release/SafeDIPackageTests.xctest -instr-profile .build/x86_64-unknown-linux-gnu/release/codecov/default.profdata > coverage.lcov
- name: Upload Coverage Reports
if: success()
uses: codecov/codecov-action@v3

readme-validation:
name: Check Markdown links
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Validate Markdown
uses: gaurav-nelson/github-action-markdown-link-check@v1
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ let package = Package(
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax"),
.byNameItem(name: "ZippyJSON", condition: .when(platforms: [.iOS, .tvOS, .macOS])),
"SafeDICore",
"ZippyJSON",
]
),
.testTarget(
name: "SafeDIToolTests",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.byNameItem(name: "ZippyJSON", condition: .when(platforms: [.iOS, .tvOS, .macOS])),
"SafeDITool",
"ZippyJSON",
]
),

Expand Down
4 changes: 2 additions & 2 deletions Sources/SafeDICore/Generators/DependencyTreeGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public final class DependencyTreeGenerator {
for try await generatedRoot in taskGroup {
generatedRoots.append(generatedRoot)
}
return generatedRoots.sorted().joined(separator: "\n\n").trimmingCharacters(in: .whitespacesAndNewlines)
return generatedRoots.sorted().joined(separator: "\n\n")
}

let importsWhitespace = imports.isEmpty ? "" : "\n"
Expand All @@ -69,7 +69,7 @@ public final class DependencyTreeGenerator {

// MARK: - DependencyTreeGeneratorError

enum DependencyTreeGeneratorError: Error, CustomStringConvertible {
private enum DependencyTreeGeneratorError: Error, CustomStringConvertible {

case noInstantiableFound(TypeDescription)
case unfulfillableProperties([UnfulfillableProperty])
Expand Down
15 changes: 7 additions & 8 deletions Sources/SafeDICore/Models/TypeDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public enum TypeDescription: Codable, Hashable, Comparable, Sendable {
case let .closure(arguments, isAsync, doesThrow, returnType):
return "(\(arguments.map { $0.asSource }.joined(separator: ", ")))\([isAsync ? " async" : "", doesThrow ? " throws" : ""].filter { !$0.isEmpty }.joined()) -> \(returnType.asSource)"
case let .unknown(text):
return text.trimmingCharacters(in: .whitespacesAndNewlines)
return text
}
}

Expand Down Expand Up @@ -280,9 +280,8 @@ extension TypeSyntax {
returnType: typeIdentifier.returnClause.type.typeDescription)

} else {
assertionFailure("TypeSyntax of unknown type. Defaulting to `description`.")
// The description is a source-accurate description of this node, so it is a reasonable fallback.
return .unknown(text: description)
return .unknown(text: trimmedDescription)
}
}
}
Expand All @@ -304,7 +303,7 @@ extension ExprSyntax {
if let base = memberAccessExpr.base {
return base.typeDescription
} else {
return .unknown(text: memberAccessExpr.description)
return .unknown(text: memberAccessExpr.trimmedDescription)
}
} else {
if let base = memberAccessExpr.base {
Expand All @@ -321,7 +320,7 @@ extension ExprSyntax {
)
}
} else {
return .unknown(text: memberAccessExpr.description)
return .unknown(text: memberAccessExpr.trimmedDescription)
}
}
} else if let genericExpr = GenericSpecializationExprSyntax(self) {
Expand All @@ -339,7 +338,7 @@ extension ExprSyntax {
parentType: parentType, generics: genericTypeVisitor.genericArguments
)
case .any, .array, .attributed, .closure, .composition, .dictionary, .implicitlyUnwrappedOptional, .metatype, .optional, .some, .tuple, .unknown:
return .unknown(text: description)
return .unknown(text: trimmedDescription)
}
} else if let tupleExpr = TupleExprSyntax(self) {
let tupleTypes = tupleExpr.elements.map(\.expression.typeDescription)
Expand Down Expand Up @@ -377,7 +376,7 @@ extension ExprSyntax {
returnType: returnType.typeDescription
)
} else {
return .unknown(text: description)
return .unknown(text: trimmedDescription)
}
} else if let optionalChainingExpr = OptionalChainingExprSyntax(self) {
return .optional(optionalChainingExpr.expression.typeDescription)
Expand All @@ -398,7 +397,7 @@ extension ExprSyntax {
value: onlyElement.value.typeDescription
)
} else {
return .unknown(text: description)
return .unknown(text: trimmedDescription)
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions Sources/SafeDITool/SafeDITool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import ArgumentParser
import Foundation
import SafeDICore
import SwiftParser
#if canImport(ZippyJSON)
import ZippyJSON
#endif

@main
struct SafeDITool: AsyncParsableCommand {
Expand Down Expand Up @@ -175,7 +177,11 @@ struct SafeDITool: AsyncParsableCommand {
of: ModuleInfo.self,
returning: [ModuleInfo].self
) { taskGroup in
#if canImport(ZippyJSON)
let decoder = ZippyJSONDecoder()
#else
let decoder = JSONDecoder()
#endif
for moduleInfoURL in moduleInfoURLs {
taskGroup.addTask {
try decoder.decode(
Expand Down Expand Up @@ -234,11 +240,15 @@ struct SafeDITool: AsyncParsableCommand {

extension Data {
fileprivate func write(toPath filePath: String) throws {
#if os(Linux)
try write(to: URL(fileURLWithPath: filePath))
#else
if #available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) {
try write(to: URL(filePath: filePath))
} else {
try write(to: URL(fileURLWithPath: filePath))
}
#endif
}
}

Expand All @@ -248,10 +258,14 @@ extension String {
}

fileprivate var asFileURL: URL {
#if os(Linux)
URL(fileURLWithPath: self)
#else
if #available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) {
URL(filePath: self)
} else {
URL(fileURLWithPath: self)
}
#endif
}
}
4 changes: 2 additions & 2 deletions Tests/SafeDICoreTests/TypeDescriptionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,8 @@ final class TypeDescriptionTests: XCTestCase {
}

func test_asSource_whenDescribingAnUnknownCase_returnsTheProvidedStringWithWhitespaceStripped() {
let sut = TypeDescription.unknown(text: " SomeTypeThatIsFormattedOddly ")
XCTAssertEqual(sut.asSource, "SomeTypeThatIsFormattedOddly")
let typeDescription = TypeSyntax(stringLiteral: " SomeTypeThatIsFormattedOddly ").typeDescription
XCTAssertEqual(typeDescription.asSource, "SomeTypeThatIsFormattedOddly")
}

// MARK: - Visitors
Expand Down
6 changes: 2 additions & 4 deletions Tests/SafeDIToolTests/SafeDIToolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2732,13 +2732,11 @@ final class SafeDIToolTests: XCTestCase {
line: UInt = #line,
block: () async throws -> ReturnType
) async {
var didThrow = false
do {
_ = try await block()
XCTFail("Did not throw error!", line: line)
} catch {
didThrow = true
XCTAssertEqual((error as CustomStringConvertible).description, errorDescription, line: line)
XCTAssertEqual("\(error)", errorDescription, line: line)
}
XCTAssertTrue(didThrow, "Did not throw error!", line: line)
}
}

0 comments on commit 4c83c05

Please sign in to comment.