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
Fixes #2705
  • Loading branch information
marcelofabri committed Apr 9, 2019
1 parent a97487f commit 076fade
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 @@ -5763,6 +5763,10 @@ func b() {}

```

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

</details>


Expand Down Expand Up @@ -6064,6 +6068,10 @@ func b() {}

```

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

</details>


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 @@ -47,7 +47,8 @@ public struct ExplicitACLRule: OptInRule, ConfigurationProviderRule, AutomaticTe
"internal struct C { let d = 5 }\n",
"public struct C { let d = 5 }\n",
"func a() {}\n",
"internal let a = 0\nfunc b() {}\n"
"internal let a = 0\nfunc b() {}\n",
"extension A: Equatable {}"
]
)

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 @@ -25,13 +25,24 @@ public struct ExplicitTopLevelACLRule: OptInRule, ConfigurationProviderRule, Aut
"final class B {}\n",
"struct C {}\n",
"func a() {}\n",
"internal let a = 0\nfunc b() {}\n"
"internal let a = 0\nfunc b() {}\n",
"extension A: Equatable {}"
]
)

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 076fade

Please sign in to comment.