Skip to content

Commit

Permalink
Fix false positives on explicit_acl and explicit_top_level_acl
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelofabri committed Apr 9, 2019
1 parent a97487f commit 537dec1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@
[Keith Smiley](https://github.com/keith)
[#2703](https://github.com/realm/SwiftLint/issues/2703)

* Fix false positives on `explicit_acl` and `explicit_top_level_acl` rules when
declaring extensions that add protocol conformances with Swift 5.
[Marcelo Fabri](https://github.com/marcelofabri)
[#2705](https://github.com/realm/SwiftLint/issues/2705)

## 0.31.0: Busy Laundromat

#### Breaking
Expand Down
8 changes: 8 additions & 0 deletions Rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -5728,6 +5728,10 @@ internal protocol A {
internal class A { deinit {} }
```

```swift
extension A: Equatable {}
```

</details>
<details>
<summary>Triggering Examples</summary>
Expand Down Expand Up @@ -6034,6 +6038,10 @@ internal func a() {}

```

```swift
extension A: Equatable {}
```

</details>
<details>
<summary>Triggering Examples</summary>
Expand Down
12 changes: 11 additions & 1 deletion Source/SwiftLintFramework/Rules/Idiomatic/ExplicitACLRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public struct ExplicitACLRule: OptInRule, ConfigurationProviderRule, AutomaticTe
var b: Int
}
""",
"internal class A { deinit {} }"
"internal class A { deinit {} }",
"extension A: Equatable {}"
],
triggeringExamples: [
"enum A {}\n",
Expand All @@ -60,11 +61,20 @@ public struct ExplicitACLRule: OptInRule, ConfigurationProviderRule, AutomaticTe

private func offsetOfElements(from elements: [SourceKittenElement], in file: File,
thatAreNotInRanges ranges: [NSRange]) -> [Int] {
let extensionKinds: Set<SwiftDeclarationKind> = [.extension, .extensionClass, .extensionEnum,
.extensionProtocol, .extensionStruct]

return elements.compactMap { element in
guard let typeOffset = element.offset else {
return nil
}

guard let kind = element.kind.flatMap(SwiftDeclarationKind.init(rawValue:)),
case let isConformanceExtension = extensionKinds.contains(kind) && !element.inheritedTypes.isEmpty,
!isConformanceExtension else {
return nil
}

// find the last "internal" token before the type
guard let previousInternalByteRange = lastInternalByteRange(before: typeOffset, in: ranges) else {
return typeOffset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public struct ExplicitTopLevelACLRule: OptInRule, ConfigurationProviderRule, Aut
"internal enum A {\n enum B {}\n}",
"internal final class Foo {}",
"internal\nclass Foo {}",
"internal func a() {}\n"
"internal func a() {}\n",
"extension A: Equatable {}"
],
triggeringExamples: [
"enum A {}\n",
Expand All @@ -30,8 +31,18 @@ public struct ExplicitTopLevelACLRule: OptInRule, ConfigurationProviderRule, Aut
)

public func validate(file: File) -> [StyleViolation] {
let extensionKinds: Set<SwiftDeclarationKind> = [.extension, .extensionClass, .extensionEnum,
.extensionProtocol, .extensionStruct]

// find all top-level types marked as internal (either explictly or implictly)
let internalTypesOffsets = file.structure.dictionary.substructure.compactMap { element -> Int? in
// ignore extensions that declare protocol conformance
guard let kind = element.kind.flatMap(SwiftDeclarationKind.init(rawValue:)),
case let isConformanceExtension = extensionKinds.contains(kind) && !element.inheritedTypes.isEmpty,
!isConformanceExtension else {
return nil
}

if element.accessibility.flatMap(AccessControlLevel.init(identifier:)) == .internal {
return element.offset
}
Expand Down

0 comments on commit 537dec1

Please sign in to comment.