Compare commits

...

13 Commits

Author SHA1 Message Date
JP Simard af93485bbe
Set up QEMU 2022-03-13 12:24:50 -04:00
JP Simard 925ff8738f
arm64 only 2022-03-13 12:11:25 -04:00
JP Simard e176a9648f
fixup! Build multi-platform docker image 2022-03-13 12:04:06 -04:00
JP Simard b0afb75714
Build multi-platform docker image 2022-03-13 12:01:16 -04:00
JP Simard 8ecb7c435e
Update Dockerfile to build for both arm64 & amd64 2022-03-13 11:59:32 -04:00
JP Simard e8ef21fef6
release 0.46.5 2022-03-08 16:18:50 -05:00
JP Simard 169542a3e2
push to HEAD in `make push_version` 2022-03-08 16:17:00 -05:00
Danny Moesch 2eca7783b3
Exclude examples with complex language constructs from the rule documentation (#3880) 2022-03-08 16:15:14 -05:00
Marcelo Fabri e8dc313d8b
Fix regression in `trailing_closure` rule with Swift 5.6 (#3879)
Fixes #3848
2022-03-08 16:15:14 -05:00
JP Simard 9445e676d2
Fix regression in `unused_import` rule when using Swift 5.6 (#3878)
Fixes https://github.com/realm/SwiftLint/issues/3849
2022-03-08 16:15:14 -05:00
Marcelo Fabri 8023f36485
Fix regression in `last_where` rule with Swift 5.6 (#3874)
Fixes #3847
2022-03-08 16:15:14 -05:00
Marcelo Fabri 052708b82c
Fix `closure_parameter_position` rule with Swift 5.6 (#3871)
Fixes #3845
2022-03-08 16:15:14 -05:00
Marcelo Fabri 17026c12b1
Fix `empty_parentheses_with_trailing_closure` with Swift 5.6 (#3870)
Fixes #3846
2022-03-08 16:15:14 -05:00
11 changed files with 129 additions and 91 deletions

View File

@ -3,44 +3,38 @@ name: docker
on: on:
push: push:
branches: branches:
- master - '*'
tags: tags:
- '*' - '*'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Extract DOCKER_TAG using tag name
if: startsWith(github.ref, 'refs/tags/')
run: |
echo "DOCKER_TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
- name: Use default DOCKER_TAG
if: startsWith(github.ref, 'refs/tags/') != true
run: |
echo "DOCKER_TAG=latest" >> $GITHUB_ENV
- name: Set lowercase repository name - name: Set lowercase repository name
run: | run: |
echo "REPOSITORY_LC=${REPOSITORY,,}" >>${GITHUB_ENV} echo "REPOSITORY_LC=${REPOSITORY,,}" >>${GITHUB_ENV}
env: env:
REPOSITORY: '${{ github.repository }}' REPOSITORY: '${{ github.repository }}'
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Github registry - name: Log in to Github registry
uses: docker/login-action@v1 uses: docker/login-action@v1
with: with:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
registry: ghcr.io registry: ghcr.io
- uses: docker/build-push-action@v2 - uses: docker/build-push-action@v2
with: with:
platforms: linux/arm64
push: true push: true
tags: ghcr.io/${{ env.REPOSITORY_LC }}:${{ env.DOCKER_TAG }} tags: ghcr.io/${{ env.REPOSITORY_LC }}:multiarch

View File

@ -1,4 +1,4 @@
## Master ## 0.46.5: Laundry Studio
#### Breaking #### Breaking
@ -14,7 +14,25 @@
#### Bug Fixes #### Bug Fixes
* None. * Fix `empty_parentheses_with_trailing_closure` rule when using Swift 5.6.
[Marcelo Fabri](https://github.com/marcelofabri)
[#3846](https://github.com/realm/SwiftLint/issues/3846)
* Fix false negatives in `closure_parameter_position` rule with Swift 5.6.
[Marcelo Fabri](https://github.com/marcelofabri)
[#3845](https://github.com/realm/SwiftLint/issues/3845)
* Fix regression in `last_where` rule when using Swift 5.6.
[Marcelo Fabri](https://github.com/marcelofabri)
[#3847](https://github.com/realm/SwiftLint/issues/3847)
* Fix regression in `unused_import` rule when using Swift 5.6.
[JP Simard](https://github.com/jpsim)
[#3849](https://github.com/realm/SwiftLint/issues/3849)
* Fix regression in `trailing_closure` rule when using Swift 5.6.
[Marcelo Fabri](https://github.com/marcelofabri)
[#3848](https://github.com/realm/SwiftLint/issues/3848)
## 0.46.4: Detergent Tray ## 0.46.4: Detergent Tray

View File

@ -1,5 +1,5 @@
# Explicitly specify `focal` because `swift:latest` does not use `ubuntu:latest`. # Explicitly specify `focal` because `swift:latest` does not use `ubuntu:latest`.
ARG BUILDER_IMAGE=swift:focal ARG BUILDER_IMAGE=swiftlang/swift:nightly-5.6-focal
ARG RUNTIME_IMAGE=ubuntu:focal ARG RUNTIME_IMAGE=ubuntu:focal
# builder image # builder image
@ -13,12 +13,10 @@ COPY Source Source/
COPY Tests Tests/ COPY Tests Tests/
COPY Package.* ./ COPY Package.* ./
ARG SWIFT_FLAGS="-c release -Xswiftc -static-stdlib -Xlinker -lCFURLSessionInterface -Xlinker -lCFXMLInterface -Xlinker -lcurl -Xlinker -lxml2" ARG SWIFT_FLAGS="-c release"
RUN swift build $SWIFT_FLAGS RUN swift build $SWIFT_FLAGS
RUN mkdir -p /executables RUN mkdir -p /executables
RUN for executable in $(swift package completion-tool list-executables); do \ RUN mv $(swift build $SWIFT_FLAGS --show-bin-path)/swiftlint /executables
install -v `swift build $SWIFT_FLAGS --show-bin-path`/$executable /executables; \
done
# runtime image # runtime image
FROM ${RUNTIME_IMAGE} FROM ${RUNTIME_IMAGE}
@ -28,8 +26,7 @@ RUN apt-get update && apt-get install -y \
libxml2 \ libxml2 \
&& rm -r /var/lib/apt/lists/* && rm -r /var/lib/apt/lists/*
COPY --from=builder /usr/lib/libsourcekitdInProc.so /usr/lib COPY --from=builder /usr/lib/libsourcekitdInProc.so /usr/lib
COPY --from=builder /usr/lib/swift/linux/libBlocksRuntime.so /usr/lib COPY --from=builder /usr/lib/swift/linux/* /usr/lib
COPY --from=builder /usr/lib/swift/linux/libdispatch.so /usr/lib
COPY --from=builder /executables/* /usr/bin COPY --from=builder /executables/* /usr/bin
RUN swiftlint version RUN swiftlint version

View File

@ -158,7 +158,7 @@ endif
@sed 's/__VERSION__/$(NEW_VERSION)/g' script/Version.swift.template > Source/SwiftLintFramework/Models/Version.swift @sed 's/__VERSION__/$(NEW_VERSION)/g' script/Version.swift.template > Source/SwiftLintFramework/Models/Version.swift
git commit -a -m "release $(NEW_VERSION)" git commit -a -m "release $(NEW_VERSION)"
git tag -a $(NEW_VERSION) -m "$(NEW_VERSION_AND_NAME)" git tag -a $(NEW_VERSION) -m "$(NEW_VERSION_AND_NAME)"
git push origin master git push origin HEAD
git push origin $(NEW_VERSION) git push origin $(NEW_VERSION)
%: %:

View File

@ -4,5 +4,5 @@ public struct Version {
public let value: String public let value: String
/// The current SwiftLint version. /// The current SwiftLint version.
public static let current = Version(value: "0.46.4") public static let current = Version(value: "0.46.5")
} }

View File

@ -105,6 +105,10 @@ private extension SwiftLintFile {
// Always disallow 'Swift' and 'SwiftShims' because they're always available without importing. // Always disallow 'Swift' and 'SwiftShims' because they're always available without importing.
usrFragments.remove("Swift") usrFragments.remove("Swift")
usrFragments.remove("SwiftShims") usrFragments.remove("SwiftShims")
if SwiftVersion.current >= .fiveDotSix {
usrFragments.remove("main")
}
var unusedImports = imports.subtracting(usrFragments).subtracting(configuration.alwaysKeepImports) var unusedImports = imports.subtracting(usrFragments).subtracting(configuration.alwaysKeepImports)
// Certain Swift attributes requires importing Foundation. // Certain Swift attributes requires importing Foundation.
if unusedImports.contains("Foundation") && containsAttributesRequiringFoundation() { if unusedImports.contains("Foundation") && containsAttributesRequiringFoundation() {

View File

@ -35,7 +35,19 @@ public struct LastWhereRule: CallPairRule, OptInRule, ConfigurationProviderRule,
patternSyntaxKinds: [.identifier], patternSyntaxKinds: [.identifier],
callNameSuffix: ".filter", callNameSuffix: ".filter",
severity: configuration.severity) { dictionary in severity: configuration.severity) { dictionary in
if dictionary.substructure.isNotEmpty { let substructure: [SourceKittenDictionary] = {
if SwiftVersion.current >= .fiveDotSix {
return dictionary.substructure.flatMap { dict -> [SourceKittenDictionary] in
if dict.expressionKind == .argument {
return dict.substructure
}
return [dict]
}
}
return dictionary.substructure
}()
if substructure.isNotEmpty {
return true // has a substructure, like a closure return true // has a substructure, like a closure
} }

View File

@ -112,16 +112,23 @@ public struct ClosureParameterPositionRule: ASTRule, ConfigurationProviderRule,
return [] return []
} }
guard let nameOffset = dictionary.nameOffset, guard let bodyLength = dictionary.bodyLength,
let nameLength = dictionary.nameLength,
let bodyLength = dictionary.bodyLength,
bodyLength > 0 bodyLength > 0
else { else {
return [] return []
} }
let parameters = dictionary.enclosedVarParameters + let nameOffset = dictionary.nameOffset ?? 0
dictionary.substructure.filter { $0.declarationKind == .varLocal } // capture lists let nameLength = dictionary.nameLength ?? 0
let captureLists = dictionary.substructure.flatMap { dict -> [SourceKittenDictionary] in
if SwiftVersion.current >= .fiveDotSix, dict.expressionKind == .argument {
return dict.substructure.filter { $0.declarationKind == .varLocal }
}
return dict.declarationKind == .varLocal ? [dict] : []
}
let parameters = dictionary.enclosedVarParameters + captureLists
let rangeStart = nameOffset + nameLength let rangeStart = nameOffset + nameLength
let regex = Self.openBraceRegex let regex = Self.openBraceRegex

View File

@ -80,7 +80,7 @@ public struct EmptyParenthesesWithTrailingClosureRule: SubstitutionCorrectableAS
// avoid the more expensive regex match if there's no trailing closure in the substructure // avoid the more expensive regex match if there's no trailing closure in the substructure
if SwiftVersion.current >= .fourDotTwo, if SwiftVersion.current >= .fourDotTwo,
dictionary.substructure.last?.expressionKind != .closure { !dictionary.hasTrailingClosure {
return [] return []
} }
@ -99,3 +99,17 @@ public struct EmptyParenthesesWithTrailingClosureRule: SubstitutionCorrectableAS
return [match] return [match]
} }
} }
private extension SourceKittenDictionary {
var hasTrailingClosure: Bool {
guard let lastStructure = substructure.last else {
return false
}
if SwiftVersion.current >= .fiveDotSix, lastStructure.expressionKind == .argument {
return lastStructure.substructure.last?.expressionKind == .closure
} else {
return lastStructure.expressionKind == .closure
}
}
}

View File

@ -10,16 +10,8 @@ public struct PreferSelfInStaticReferencesRule: SubstitutionCorrectableASTRule,
nonTriggeringExamples: [ nonTriggeringExamples: [
Example(""" Example("""
class C { class C {
static private(set) var i = 0, j = C.i static let primes = [2, 3, 5, 7]
let h = C.i func isPrime(i: Int) -> Bool { Self.primes.contains(i) }
@GreaterThan(C.j) var k: Int
}
"""),
Example("""
class `Self` {
static let i = 0
func f() -> Int { Self.i }
}
"""), """),
Example(""" Example("""
struct T { struct T {
@ -29,9 +21,24 @@ public struct PreferSelfInStaticReferencesRule: SubstitutionCorrectableASTRule,
static let i = 0 static let i = 0
} }
extension T { extension T {
static let j = S.i + Self.i static let j = S.i + T.i
static let k = { T.j }()
} }
"""), """),
Example("""
class `Self` {
static let i = 0
func f() -> Int { Self.i }
}
"""),
Example("""
class C {
static private(set) var i = 0, j = C.i
static let k = { C.i }()
let h = C.i
@GreaterThan(C.j) var k: Int
}
""", excludeFromDocumentation: true),
Example(""" Example("""
struct S { struct S {
struct T { struct T {
@ -45,7 +52,7 @@ public struct PreferSelfInStaticReferencesRule: SubstitutionCorrectableASTRule,
static let j = Self.T.R.i + Self.R.j static let j = Self.T.R.i + Self.R.j
let h = Self.T.R.i + Self.R.j let h = Self.T.R.i + Self.R.j
} }
"""), """, excludeFromDocumentation: true),
Example(""" Example("""
class C { class C {
static let s = 2 static let s = 2
@ -55,31 +62,9 @@ public struct PreferSelfInStaticReferencesRule: SubstitutionCorrectableASTRule,
} }
func g() -> Any { C.self } func g() -> Any { C.self }
} }
"""), """, excludeFromDocumentation: true)
Example("""
struct S {
static let i = 1
static let j = { Self.i }()
}
extension S {
static let k = { S.j }()
}
""")
], ],
triggeringExamples: [ triggeringExamples: [
Example("""
struct C {
static let i = 0
static let j = C.i
}
"""),
Example("""
struct S {
static let i = 0
func f() -> Int { S.i }
func g() -> Any { S.self }
}
"""),
Example(""" Example("""
class C { class C {
struct S { struct S {
@ -88,8 +73,16 @@ public struct PreferSelfInStaticReferencesRule: SubstitutionCorrectableASTRule,
} }
static let i = 1 static let i = 1
let h = C.i let h = C.i
func f() -> Int { C.i + h }
} }
"""), """),
Example("""
struct S {
static let i = 1
static func f() -> Int { S.i }
func g() -> Any { S.self }
}
"""),
Example(""" Example("""
struct S { struct S {
struct T { struct T {
@ -105,28 +98,19 @@ public struct PreferSelfInStaticReferencesRule: SubstitutionCorrectableASTRule,
corrections: [ corrections: [
Example(""" Example("""
struct S { struct S {
struct T { static let i = 1
static let i = 3 static let j = S.i
} let k = S.j
static let h = S.T.i static func f(_ l: Int = S.i) -> Int { l*S.j }
func g() { S.i + S.f() + k }
} }
"""): Example(""" """): Example("""
struct S { struct S {
struct T { static let i = 1
static let i = 3 static let j = Self.i
} let k = Self.j
static let h = Self.T.i static func f(_ l: Int = Self.i) -> Int { l*Self.j }
} func g() { Self.i + Self.f() + k }
"""),
Example("""
class S {
static func f() { S.g(S.f) }
static func g(f: () -> Void) { f() }
}
"""): Example("""
class S {
static func f() { Self.g(Self.f) }
static func g(f: () -> Void) { f() }
} }
""") """)
] ]

View File

@ -82,8 +82,16 @@ public struct TrailingClosureRule: OptInRule, ConfigurationProviderRule {
return shouldTrigger() return shouldTrigger()
} }
let argumentsCountIsExpected: Bool = {
if SwiftVersion.current >= .fiveDotSix, arguments.count == 1,
arguments[0].expressionKind == .argument {
return true
}
return arguments.isEmpty
}()
// check if there's only one unnamed parameter that is a closure // check if there's only one unnamed parameter that is a closure
if arguments.isEmpty, if argumentsCountIsExpected,
let offset = dictionary.offset, let offset = dictionary.offset,
let totalLength = dictionary.length, let totalLength = dictionary.length,
let nameOffset = dictionary.nameOffset, let nameOffset = dictionary.nameOffset,