Require macOS 12 & Swift 5.6 (#4037)
This will unblock using Swift Concurrency features and updating to the latest versions of Swift Argument Parser. This won't drop support for linting projects with an older toolchain / Xcode selected, as long as SwiftLint was _built_ with 5.6+ and is _running_ on macOS 12+. So the main breaking change for end users here is requiring macOS 12 to run. However, the upside to using Swift Concurrency features is worth the breaking change in my opinion. Also being able to stay on recent Swift Argument Parser releases.
This commit is contained in:
parent
09837b7bab
commit
05ac3c9d75
|
@ -27,6 +27,14 @@ macOS < 12.
|
|||
positional paths that can be added last to both commands.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
|
||||
* SwiftLint now requires Swift 5.6 or higher to build, and macOS 12
|
||||
or higher to run.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
|
||||
* Code Climate reports now use SHA256 strings as the issue fingerprint
|
||||
values.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
|
||||
#### Experimental
|
||||
|
||||
* None.
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
"repositoryURL": "https://github.com/apple/swift-argument-parser.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "e394bf350e38cb100b6bc4172834770ede1b7232",
|
||||
"version": "1.0.3"
|
||||
"revision": "df9ee6676cd5b3bf5b330ec7568a5644f547201b",
|
||||
"version": "1.1.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -9,36 +9,29 @@ private let addCryptoSwift = true
|
|||
private let staticSwiftSyntax = false
|
||||
#endif
|
||||
|
||||
#if os(Linux) && compiler(<5.6)
|
||||
private let swiftSyntaxFiveDotSix = false
|
||||
#else
|
||||
private let swiftSyntaxFiveDotSix = true
|
||||
#endif
|
||||
|
||||
let frameworkDependencies: [Target.Dependency] = [
|
||||
.product(name: "SourceKittenFramework", package: "SourceKitten"),
|
||||
.product(name: "SwiftSyntax", package: "SwiftSyntax"),
|
||||
.product(name: "SwiftSyntaxParser", package: "SwiftSyntax"),
|
||||
"Yams",
|
||||
]
|
||||
+ (addCryptoSwift ? ["CryptoSwift"] : [])
|
||||
+ (staticSwiftSyntax ? ["lib_InternalSwiftSyntaxParser"] : [])
|
||||
+ (swiftSyntaxFiveDotSix ? [.product(name: "SwiftSyntaxParser", package: "SwiftSyntax")] : [])
|
||||
|
||||
let package = Package(
|
||||
name: "SwiftLint",
|
||||
platforms: [.macOS(.v10_12)],
|
||||
platforms: [.macOS(.v12)],
|
||||
products: [
|
||||
.executable(name: "swiftlint", targets: ["swiftlint"]),
|
||||
.library(name: "SwiftLintFramework", targets: ["SwiftLintFramework"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(name: "swift-argument-parser", url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.0.3")),
|
||||
.package(name: "SwiftSyntax", url: "https://github.com/apple/swift-syntax.git",
|
||||
.exact(swiftSyntaxFiveDotSix ? "0.50600.1" : "0.50500.0")),
|
||||
.package(name: "swift-argument-parser", url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.1.3")),
|
||||
.package(name: "SwiftSyntax", url: "https://github.com/apple/swift-syntax.git", .exact("0.50600.1")),
|
||||
.package(url: "https://github.com/jpsim/SourceKitten.git", from: "0.32.0"),
|
||||
.package(url: "https://github.com/jpsim/Yams.git", from: "4.0.2"),
|
||||
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.9.0"),
|
||||
] + (addCryptoSwift ? [.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.4.3"))] : []),
|
||||
] + (addCryptoSwift ? [.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.5.1"))] : []),
|
||||
targets: [
|
||||
.executableTarget(
|
||||
name: "swiftlint",
|
||||
|
@ -51,7 +44,6 @@ let package = Package(
|
|||
.target(
|
||||
name: "SwiftLintFramework",
|
||||
dependencies: frameworkDependencies,
|
||||
swiftSettings: swiftSyntaxFiveDotSix ? [.define("SWIFT_SYNTAX_FIVE_DOT_SIX")] : [],
|
||||
// Pass `-dead_strip_dylibs` to ignore the dynamic version of `lib_InternalSwiftSyntaxParser`
|
||||
// that ships with SwiftSyntax because we want the static version from
|
||||
// `StaticInternalSwiftSyntaxParser`.
|
||||
|
|
|
@ -60,7 +60,7 @@ running it.
|
|||
### Installing from source:
|
||||
|
||||
You can also build and install from source by cloning this project and running
|
||||
`make install` (Xcode 13 or later).
|
||||
`make install` (Xcode 13.3 or later).
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ extension Configuration {
|
|||
let jsonObject: [Any] = [rootDirectory, cacheRulesDescriptions]
|
||||
if let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject),
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||
return jsonString.md5()
|
||||
return jsonString.sha256()
|
||||
}
|
||||
queuedFatalError("Could not serialize configuration for cache")
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#if canImport(CommonCrypto)
|
||||
import CommonCrypto
|
||||
|
||||
extension String {
|
||||
internal func md5() -> String {
|
||||
let context = UnsafeMutablePointer<CC_MD5_CTX>.allocate(capacity: 1)
|
||||
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
|
||||
CC_MD5_Init(context)
|
||||
CC_MD5_Update(context, self, CC_LONG(lengthOfBytes(using: .utf8)))
|
||||
CC_MD5_Final(&digest, context)
|
||||
context.deallocate()
|
||||
return digest.reduce(into: "") { $0.append(String(format: "%02x", $1)) }
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
#if canImport(CommonCrypto)
|
||||
import CommonCrypto
|
||||
|
||||
extension String {
|
||||
internal func sha256() -> String {
|
||||
let theData = data(using: .utf8)!
|
||||
return theData.withUnsafeBytes { bytes in
|
||||
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
|
||||
_ = CC_SHA256(bytes.baseAddress, CC_LONG(theData.count), &hash)
|
||||
return hash.reduce(into: "") { $0.append(String(format: "%02x", $1)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,33 +1,4 @@
|
|||
import Foundation
|
||||
import SourceKittenFramework
|
||||
|
||||
#if os(Linux)
|
||||
private extension Scanner {
|
||||
func scanString(string: String) -> String? {
|
||||
return scanString(string)
|
||||
}
|
||||
}
|
||||
#else
|
||||
private extension Scanner {
|
||||
func scanUpToString(_ string: String) -> String? {
|
||||
var result: NSString?
|
||||
let success = scanUpTo(string, into: &result)
|
||||
if success {
|
||||
return result?.bridge()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scanString(string: String) -> String? {
|
||||
var result: NSString?
|
||||
let success = scanString(string, into: &result)
|
||||
if success {
|
||||
return result?.bridge()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// A SwiftLint-interpretable command to modify SwiftLint's behavior embedded as comments in source code.
|
||||
public struct Command: Equatable {
|
||||
|
@ -100,7 +71,7 @@ public struct Command: Equatable {
|
|||
/// defined.
|
||||
public init?(actionString: String, line: Int, character: Int) {
|
||||
let scanner = Scanner(string: actionString)
|
||||
_ = scanner.scanString(string: "swiftlint:")
|
||||
_ = scanner.scanString("swiftlint:")
|
||||
// (enable|disable)(:previous|:this|:next)
|
||||
guard let actionAndModifierString = scanner.scanUpToString(" ") else {
|
||||
return nil
|
||||
|
@ -120,9 +91,12 @@ public struct Command: Equatable {
|
|||
trailingComment = nil
|
||||
} else {
|
||||
// Store any text after the comment delimiter as the trailingComment.
|
||||
// The addition to scanLocation is to move past the delimiter
|
||||
let startOfCommentPastDelimiter = scanner.scanLocation + Self.commentDelimiter.count
|
||||
trailingComment = scanner.string.bridge().substring(from: startOfCommentPastDelimiter)
|
||||
// The addition to currentIndex is to move past the delimiter
|
||||
trailingComment = String(
|
||||
scanner
|
||||
.string[scanner.currentIndex...]
|
||||
.dropFirst(Self.commentDelimiter.count)
|
||||
)
|
||||
}
|
||||
let ruleTexts = rawRuleTexts.components(separatedBy: .whitespacesAndNewlines).filter {
|
||||
let component = $0.trimmingCharacters(in: .whitespaces)
|
||||
|
@ -132,11 +106,13 @@ public struct Command: Equatable {
|
|||
ruleIdentifiers = Set(ruleTexts.map(RuleIdentifier.init(_:)))
|
||||
|
||||
// Modifier
|
||||
let hasModifier = actionAndModifierScanner.scanString(string: ":") != nil
|
||||
let hasModifier = actionAndModifierScanner.scanString(":") != nil
|
||||
if hasModifier {
|
||||
let modifierString = actionAndModifierScanner.string.bridge()
|
||||
.substring(from: actionAndModifierScanner.scanLocation)
|
||||
modifier = Modifier(rawValue: modifierString)
|
||||
modifier = Modifier(
|
||||
rawValue: String(
|
||||
actionAndModifierScanner.string[actionAndModifierScanner.currentIndex...]
|
||||
)
|
||||
)
|
||||
} else {
|
||||
modifier = nil
|
||||
}
|
||||
|
|
|
@ -50,6 +50,6 @@ public struct CodeClimateReporter: Reporter {
|
|||
return [
|
||||
"\(fingerprintLocation)",
|
||||
"\(violation.ruleIdentifier)"
|
||||
].joined().md5()
|
||||
].joined().sha256()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,10 +90,8 @@ public struct UnavailableConditionRule: ConfigurationProviderRule, AutomaticTest
|
|||
switch check {
|
||||
case is AvailabilityConditionSyntax:
|
||||
return "Use #unavailable instead of #available with an empty body."
|
||||
#if SWIFT_SYNTAX_FIVE_DOT_SIX
|
||||
case is UnavailabilityConditionSyntax:
|
||||
return "Use #available instead of #unavailable with an empty body."
|
||||
#endif
|
||||
default:
|
||||
queuedFatalError("Unknown availability check type.")
|
||||
}
|
||||
|
@ -123,12 +121,8 @@ private final class UnavailableConditionRuleVisitor: SyntaxVisitor {
|
|||
}
|
||||
|
||||
private func asAvailabilityCondition(_ condition: Syntax) -> SyntaxProtocol? {
|
||||
let availability = condition.as(AvailabilityConditionSyntax.self)
|
||||
#if SWIFT_SYNTAX_FIVE_DOT_SIX
|
||||
return availability ?? condition.as(UnavailabilityConditionSyntax.self)
|
||||
#else
|
||||
return availability
|
||||
#endif
|
||||
condition.as(AvailabilityConditionSyntax.self) ??
|
||||
condition.as(UnavailabilityConditionSyntax.self)
|
||||
}
|
||||
|
||||
private func otherAvailabilityCheckInvolved(ifStmt: IfStmtSyntax) -> Bool {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Foundation
|
||||
import SourceKittenFramework
|
||||
|
||||
struct CompilerArgumentsExtractor {
|
||||
static func allCompilerInvocations(compilerLogs: String) -> [[String]] {
|
||||
|
@ -18,28 +17,6 @@ struct CompilerArgumentsExtractor {
|
|||
|
||||
// MARK: - Private
|
||||
|
||||
#if !os(Linux)
|
||||
private extension Scanner {
|
||||
func scanUpToString(_ string: String) -> String? {
|
||||
var result: NSString?
|
||||
let success = scanUpTo(string, into: &result)
|
||||
if success {
|
||||
return result?.bridge()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scanString(_ string: String) -> String? {
|
||||
var result: NSString?
|
||||
let success = scanString(string, into: &result)
|
||||
if success {
|
||||
return result?.bridge()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private func parseCLIArguments(_ string: String) -> [String] {
|
||||
let escapedSpacePlaceholder = "\u{0}"
|
||||
let scanner = Scanner(string: string)
|
||||
|
|
|
@ -47,7 +47,7 @@ struct LintOrAnalyzeArguments: ParsableArguments {
|
|||
// `LintOrAnalyzeArguments`.
|
||||
|
||||
func pathOptionDescription(for mode: LintOrAnalyzeMode) -> ArgumentHelp {
|
||||
ArgumentHelp(shouldDisplay: false)
|
||||
ArgumentHelp(visibility: .hidden)
|
||||
}
|
||||
|
||||
func pathsArgumentDescription(for mode: LintOrAnalyzeMode) -> ArgumentHelp {
|
||||
|
|
|
@ -42,7 +42,7 @@ class ReporterTests: XCTestCase {
|
|||
severity: .error,
|
||||
location: location,
|
||||
reason: "Shorthand syntactic sugar should be used" +
|
||||
", i.e. [Int] instead of Array<Int>."),
|
||||
", i.e. [Int] instead of Array<Int>."),
|
||||
StyleViolation(ruleDescription: ColonRule.description,
|
||||
severity: .error,
|
||||
location: Location(file: nil),
|
||||
|
@ -118,9 +118,9 @@ class ReporterTests: XCTestCase {
|
|||
func testHTMLReporter() {
|
||||
let expectedOutput = stringFromFile("CannedHTMLReporterOutput.html")
|
||||
let result = HTMLReporter.generateReport(
|
||||
generateViolations(),
|
||||
swiftlintVersion: "1.2.3",
|
||||
dateString: "13/12/2016"
|
||||
generateViolations(),
|
||||
swiftlintVersion: "1.2.3",
|
||||
dateString: "13/12/2016"
|
||||
)
|
||||
XCTAssertEqual(result, expectedOutput)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"check_name" : "Line Length",
|
||||
"description" : "Violation Reason.",
|
||||
"engine_name" : "SwiftLint",
|
||||
"fingerprint" : "091a80392f7aebde05dab908162c3629",
|
||||
"fingerprint" : "917a85854a9500cfd28520fa4875a3ecbba171e522f13452c7adec71fc14497a",
|
||||
"location" : {
|
||||
"lines" : {
|
||||
"begin" : 1,
|
||||
|
@ -18,7 +18,7 @@
|
|||
"check_name" : "Line Length",
|
||||
"description" : "Violation Reason.",
|
||||
"engine_name" : "SwiftLint",
|
||||
"fingerprint" : "091a80392f7aebde05dab908162c3629",
|
||||
"fingerprint" : "917a85854a9500cfd28520fa4875a3ecbba171e522f13452c7adec71fc14497a",
|
||||
"location" : {
|
||||
"lines" : {
|
||||
"begin" : 1,
|
||||
|
@ -33,7 +33,7 @@
|
|||
"check_name" : "Syntactic Sugar",
|
||||
"description" : "Shorthand syntactic sugar should be used, i.e. [Int] instead of Array<Int>.",
|
||||
"engine_name" : "SwiftLint",
|
||||
"fingerprint" : "624a4e77e797c9e6a42c82b6428e9c45",
|
||||
"fingerprint" : "6477f518963149b01807a31e7067be97dc39a30b93673e1e246f812e9ea5ef21",
|
||||
"location" : {
|
||||
"lines" : {
|
||||
"begin" : 1,
|
||||
|
@ -48,7 +48,7 @@
|
|||
"check_name" : "Colon Spacing",
|
||||
"description" : "Colons should be next to the identifier when specifying a type and next to the key in dictionary literals.",
|
||||
"engine_name" : "SwiftLint",
|
||||
"fingerprint" : "1f9389145aa6d7e89a582fce5ae54659",
|
||||
"fingerprint" : "9b1ddedc847d23a54124cb02a56452fc01c23df8f3babc07a6a68cf2449b14a6",
|
||||
"location" : {
|
||||
"lines" : {
|
||||
"begin" : null,
|
||||
|
|
|
@ -8,8 +8,6 @@ jobs:
|
|||
strategy:
|
||||
maxParallel: 10
|
||||
matrix:
|
||||
swift55:
|
||||
containerImage: swift:5.5
|
||||
swift56:
|
||||
containerImage: swift:5.6
|
||||
container: $[ variables['containerImage'] ]
|
||||
|
@ -23,8 +21,6 @@ jobs:
|
|||
strategy:
|
||||
maxParallel: 10
|
||||
matrix:
|
||||
xcode1321:
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
|
||||
xcode1331:
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.3.1.app
|
||||
steps:
|
||||
|
@ -41,8 +37,6 @@ jobs:
|
|||
strategy:
|
||||
maxParallel: 10
|
||||
matrix:
|
||||
xcode1321:
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
|
||||
xcode1331:
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.3.1.app
|
||||
steps:
|
||||
|
|
Loading…
Reference in New Issue