Skip to content

Commit

Permalink
Support Strict Concurrency (#83)
Browse files Browse the repository at this point in the history
# Support Strict Concurrency

## ♻️ Current situation & Problem
This PR enables strict concurrency and resolve some issues. Swift 6 is
now fully supported.


## ⚙️ Release Notes 
* Swift 6 compatibility.


## 📚 Documentation
--


## ✅ Testing
--

### Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
Supereg authored Aug 13, 2024
1 parent dcd5f95 commit 23dda93
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 152 deletions.
58 changes: 52 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@
// SPDX-License-Identifier: MIT
//

import class Foundation.ProcessInfo
import PackageDescription


#if swift(<6)
let swiftConcurrency: SwiftSetting = .enableExperimentalFeature("StrictConcurrency")
#else
let swiftConcurrency: SwiftSetting = .enableUpcomingFeature("StrictConcurrency")
#endif


let package = Package(
name: "ResearchKitOnFHIR",
platforms: [
Expand All @@ -27,7 +35,7 @@ let package = Package(
.package(url: "https://github.com/StanfordBDHG/ResearchKit", .upToNextMinor(from: "3.0.1")),
.package(url: "https://github.com/apple/FHIRModels.git", .upToNextMinor(from: "0.5.0")),
.package(url: "https://github.com/antlr/antlr4", from: "4.13.1")
],
] + swiftLintPackage(),
targets: [
.target(
name: "ResearchKitOnFHIR",
Expand All @@ -36,7 +44,11 @@ let package = Package(
.product(name: "ResearchKitSwiftUI", package: "ResearchKit"),
.product(name: "ModelsR4", package: "FHIRModels"),
.target(name: "FHIRPathParser")
]
],
swiftSettings: [
swiftConcurrency
],
plugins: [] + swiftLintPlugin()
),
.target(
name: "FHIRQuestionnaires",
Expand All @@ -57,7 +69,11 @@ let package = Package(
.copy("Resources/MultipleEnableWhen.json"),
.copy("Resources/ImageCapture.json"),
.copy("Resources/SliderExample.json")
]
],
swiftSettings: [
swiftConcurrency
],
plugins: [] + swiftLintPlugin()
),
.target(
name: "FHIRPathParser",
Expand All @@ -66,20 +82,50 @@ let package = Package(
],
exclude: [
"ANTLUtils"
]
],
swiftSettings: [
swiftConcurrency
],
plugins: [] + swiftLintPlugin()
),
.testTarget(
name: "ResearchKitOnFHIRTests",
dependencies: [
.target(name: "ResearchKitOnFHIR"),
.target(name: "FHIRQuestionnaires")
]
],
swiftSettings: [
swiftConcurrency
],
plugins: [] + swiftLintPlugin()
),
.testTarget(
name: "FHIRPathParserTests",
dependencies: [
.target(name: "FHIRPathParser")
]
],
swiftSettings: [
swiftConcurrency
],
plugins: [] + swiftLintPlugin()
)
]
)


func swiftLintPlugin() -> [Target.PluginUsage] {
// Fully quit Xcode and open again with `open --env SPEZI_DEVELOPMENT_SWIFTLINT /Applications/Xcode.app`
if ProcessInfo.processInfo.environment["SPEZI_DEVELOPMENT_SWIFTLINT"] != nil {
[.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint")]
} else {
[]
}
}

func swiftLintPackage() -> [PackageDescription.Package.Dependency] {
if ProcessInfo.processInfo.environment["SPEZI_DEVELOPMENT_SWIFTLINT"] != nil {
[.package(url: "https://github.com/realm/SwiftLint.git", .upToNextMinor(from: "0.55.1"))]
} else {
[]
}
}
3 changes: 3 additions & 0 deletions Sources/FHIRPathParser/DateExpressionError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ extension DateExpressionError {
}


extension DateExpressionError.FailedDateOperationReason: Sendable {}


extension Result where Failure == Error {
static func failure(_ token: Token?, _ error: DateExpressionError) -> Result<Success, Failure> {
.failure(ExpressionError(token: token, underlyingError: error))
Expand Down
2 changes: 1 addition & 1 deletion Sources/FHIRPathParser/ExpressionError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// SPDX-License-Identifier: MIT
//

import Antlr4
@preconcurrency import Antlr4


public struct ExpressionError: Error {
Expand Down
6 changes: 3 additions & 3 deletions Sources/FHIRPathParser/Generated/FHIRPathLexer.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Generated from FHIRPath.g4 by ANTLR 4.13.1
import Antlr4
@preconcurrency import Antlr4

open class FHIRPathLexer: Lexer {

internal static var _decisionToDFA: [DFA] = {
internal static let _decisionToDFA: [DFA] = {

Check warning on line 6 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

static property '_decisionToDFA' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 6 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

static property '_decisionToDFA' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 6 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package / Test using xcodebuild or run fastlane

static property '_decisionToDFA' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 6 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package / Test using xcodebuild or run fastlane

static property '_decisionToDFA' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
var decisionToDFA = [DFA]()
let length = FHIRPathLexer._ATN.getNumberOfDecisions()
for i in 0..<length {
Expand Down Expand Up @@ -276,4 +276,4 @@ open class FHIRPathLexer: Lexer {

public
static let _ATN: ATN = try! ATNDeserializer().deserialize(_serializedATN)

Check warning on line 278 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

static property '_ATN' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 278 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

static property '_ATN' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 278 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package / Test using xcodebuild or run fastlane

static property '_ATN' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 278 in Sources/FHIRPathParser/Generated/FHIRPathLexer.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package / Test using xcodebuild or run fastlane

static property '_ATN' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
}
}
4 changes: 2 additions & 2 deletions Sources/FHIRPathParser/Generated/FHIRPathParser.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Generated from FHIRPath.g4 by ANTLR 4.13.1
import Antlr4
@preconcurrency import Antlr4

open class FHIRPathParser: Parser {

internal static var _decisionToDFA: [DFA] = {
internal static let _decisionToDFA: [DFA] = {

Check warning on line 6 in Sources/FHIRPathParser/Generated/FHIRPathParser.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

static property '_decisionToDFA' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 6 in Sources/FHIRPathParser/Generated/FHIRPathParser.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package / Test using xcodebuild or run fastlane

static property '_decisionToDFA' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
var decisionToDFA = [DFA]()
let length = FHIRPathParser._ATN.getNumberOfDecisions()
for i in 0..<length {
Expand Down
120 changes: 75 additions & 45 deletions Sources/FHIRQuestionnaires/Questionnaire+Resources.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,78 +14,108 @@ extension Questionnaire {
// MARK: Example FHIR Questionnaires to demonstrate library functionality

/// A FHIR questionnaire demonstrating enableWhen conditions that are converted to ResearchKit skip logic
public static var skipLogicExample: Questionnaire = loadQuestionnaire(withName: "SkipLogicExample")

public static var skipLogicExample: Questionnaire {
loadQuestionnaire(withName: "SkipLogicExample")
}

/// A FHIR questionnaire demonstrating multiple enableWhen conditions in an AND / OR configuration
public static var multipleEnableWhen: Questionnaire = loadQuestionnaire(withName: "MultipleEnableWhen")

public static var multipleEnableWhen: Questionnaire {
loadQuestionnaire(withName: "MultipleEnableWhen")
}

/// A FHIR questionnaire demonstrating the use of a regular expression to validate an email address
public static var textValidationExample: Questionnaire = loadQuestionnaire(withName: "TextValidationExample")

public static var textValidationExample: Questionnaire {
loadQuestionnaire(withName: "TextValidationExample")
}

/// A FHIR questionnaire demonstrating the use of a contained ValueSet
public static var containedValueSetExample: Questionnaire = loadQuestionnaire(withName: "ContainedValueSetExample")

public static var containedValueSetExample: Questionnaire {
loadQuestionnaire(withName: "ContainedValueSetExample")
}

/// A FHIR questionnaire demonstrating integer and decimal inputs
public static var numberExample: Questionnaire = loadQuestionnaire(withName: "NumberExample")

public static var numberExample: Questionnaire {
loadQuestionnaire(withName: "NumberExample")
}

/// A FHIR questionnaire demonstrating date, dateTime, and time inputs
public static var dateTimeExample: Questionnaire = loadQuestionnaire(withName: "DateTimeExample")

public static var dateTimeExample: Questionnaire {
loadQuestionnaire(withName: "DateTimeExample")
}

/// A FHIR questionnaire demonstrating a form with nested questions
public static var formExample: Questionnaire = loadQuestionnaire(withName: "FormExample")
public static var formExample: Questionnaire {
loadQuestionnaire(withName: "FormExample")
}

/// A FHIR questionnaire demonstrating an image capture step
public static var imageCaptureExample: Questionnaire = loadQuestionnaire(withName: "ImageCapture")
public static var imageCaptureExample: Questionnaire {
loadQuestionnaire(withName: "ImageCapture")
}

/// A FHIR questionnaire demonstrating a slider
public static var sliderExample: Questionnaire = loadQuestionnaire(withName: "SliderExample")

public static var sliderExample: Questionnaire {
loadQuestionnaire(withName: "SliderExample")
}

/// A collection of example `Questionnaire`s provided by the FHIRQuestionnaires target to demonstrate functionality
public static var exampleQuestionnaires: [Questionnaire] = [
.skipLogicExample,
.textValidationExample,
.containedValueSetExample,
.numberExample,
.dateTimeExample,
.formExample,
.multipleEnableWhen,
.imageCaptureExample,
.sliderExample
]

public static var exampleQuestionnaires: [Questionnaire] {
[
.skipLogicExample,
.textValidationExample,
.containedValueSetExample,
.numberExample,
.dateTimeExample,
.formExample,
.multipleEnableWhen,
.imageCaptureExample,
.sliderExample
]
}

// MARK: Examples of clinical research FHIR Questionnaires

/// The PHQ-9 validated clinical questionnaire
public static var phq9: Questionnaire = loadQuestionnaire(withName: "PHQ-9")

public static var phq9: Questionnaire {
loadQuestionnaire(withName: "PHQ-9")
}

/// Generalized Anxiety Disorder-7
public static var gad7: Questionnaire = loadQuestionnaire(withName: "GAD-7")

public static var gad7: Questionnaire {
loadQuestionnaire(withName: "GAD-7")
}

/// International Prostatism Symptom Score (IPSS)
public static var ipss: Questionnaire = loadQuestionnaire(withName: "IPSS")

public static var ipss: Questionnaire {
loadQuestionnaire(withName: "IPSS")
}

/// The Glasgow Coma Scale
public static var gcs: Questionnaire = loadQuestionnaire(withName: "GCS")

public static var gcs: Questionnaire {
loadQuestionnaire(withName: "GCS")
}

/// A collection of clinical research `Questionnaire`s provided by the FHIRQuestionnaires target
public static var researchQuestionnaires: [Questionnaire] = [
.phq9,
.gad7,
.ipss,
.gcs
]

public static var researchQuestionnaires: [Questionnaire] {
[
.phq9,
.gad7,
.ipss,
.gcs
]
}


private static func loadQuestionnaire(withName name: String) -> Questionnaire {
guard let resourceURL = Bundle.module.url(forResource: name, withExtension: "json") else {
fatalError("Could not find the resource \"\(name)\".json in the FHIRQuestionnaires Resources folder.")
preconditionFailure("Could not find the resource \"\(name)\".json in the FHIRQuestionnaires Resources folder.")
}

do {
let resourceData = try Data(contentsOf: resourceURL)
return try JSONDecoder().decode(Questionnaire.self, from: resourceData)
} catch {
fatalError("Could not decode the FHIR questionnaire named \"\(name).json\": \(error)")
preconditionFailure("Could not decode the FHIR questionnaire named \"\(name).json\": \(error)")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// SPDX-License-Identifier: MIT
//

import ModelsR4
@preconcurrency import ModelsR4


/// An error that is thrown when translating a FHIR `Questionnaire` to an `ORKNavigableOrderedTask`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// SPDX-License-Identifier: MIT
//

// swiftlint:disable duplicate_imports function_default_parameter_at_end
// swiftlint:disable function_default_parameter_at_end
import ModelsR4
import ResearchKit
@_exported import class ResearchKit.ORKNavigableOrderedTask
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
// SPDX-License-Identifier: MIT
//

// swiftlint:disable duplicate_imports
import Foundation
import ModelsR4
import ResearchKit
Expand Down
Loading

0 comments on commit 23dda93

Please sign in to comment.