Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Swift 3 ACLs (open & fileprivate) in existing rules #905

Merged
merged 4 commits into from
Nov 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,19 @@
* `closure_spacing` rule now accepts empty bodies with a space.
[Marcelo Fabri](https://github.com/marcelofabri)
[#875](https://github.com/realm/SwiftLint/issues/875)

* Add `TrailingCommaRule` to enforce/forbid trailing commas in arrays and
dictionaries. The default is to forbid them, but this can be changed with
the `mandatory_comma` configuration.
[Marcelo Fabri](https://github.com/marcelofabri)
[#883](https://github.com/realm/SwiftLint/issues/883)

* Add support for `fileprivate` in `PrivateOutletRule` and
`PrivateUnitTestRule`.
[Marcelo Fabri](https://github.com/marcelofabri)
[#781](https://github.com/realm/SwiftLint/issues/781)
[#831](https://github.com/realm/SwiftLint/issues/831)

##### Bug Fixes

* Fix a few edge cases where malformed `MARK:` comments wouldn't trigger a
Expand Down
5 changes: 3 additions & 2 deletions Source/SwiftLintFramework/Extensions/String+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ extension String {

internal func nameStrippingLeadingUnderscoreIfPrivate(dict: [String: SourceKitRepresentable]) ->
String {
let privateACL = "source.lang.swift.accessibility.private"
if dict["key.accessibility"] as? String == privateACL && characters.first == "_" {
if let aclString = dict["key.accessibility"] as? String,
let acl = AccessControlLevel(identifier: aclString)
where acl.isPrivate && characters.first == "_" {
return self[startIndex.successor()..<endIndex]
}
return self
Expand Down
19 changes: 18 additions & 1 deletion Source/SwiftLintFramework/Rules/MissingDocsRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,41 @@ extension File {

public enum AccessControlLevel: String, CustomStringConvertible {
case Private = "source.lang.swift.accessibility.private"
case FilePrivate = "source.lang.swift.accessibility.fileprivate"
case Internal = "source.lang.swift.accessibility.internal"
case Public = "source.lang.swift.accessibility.public"
case Open = "source.lang.swift.accessibility.open"

internal init?(description value: String) {
switch value {
case "private": self = .Private
case "fileprivate": self = .FilePrivate
case "internal": self = .Internal
case "public": self = .Public
case "open": self = .Open
default: return nil
}
}

init?(identifier value: String) {
self.init(rawValue: value)
}

public var description: String {
switch self {
case Private: return "private"
case FilePrivate: return "fileprivate"
case Internal: return "internal"
case Public: return "public"
case Open: return "open"
}
}

// Returns true if is `private` or `fileprivate`
var isPrivate: Bool {
return self == .Private || self == .FilePrivate
}

}

public struct MissingDocsRule: OptInRule {
Expand All @@ -92,7 +108,8 @@ public struct MissingDocsRule: OptInRule {
}

public init() {
parameters = [RuleParameter(severity: .Warning, value: .Public)]
parameters = [RuleParameter(severity: .Warning, value: .Public),
RuleParameter(severity: .Warning, value: .Open)]
}

public let parameters: [RuleParameter<AccessControlLevel>]
Expand Down
16 changes: 10 additions & 6 deletions Source/SwiftLintFramework/Rules/PrivateOutletRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ public struct PrivateOutletRule: ASTRule, OptInRule, ConfigurationProviderRule {
guard isOutlet else { return [] }

// Check if private
let accessibility = (dictionary["key.accessibility"] as? String) ?? ""
let setterAccessiblity = (dictionary["key.setter_accessibility"] as? String) ?? ""
let isPrivate = accessibility == "source.lang.swift.accessibility.private"
let isPrivateSet = setterAccessiblity == "source.lang.swift.accessibility.private"
let accessibility = dictionary["key.accessibility"] as? String
let setterAccessiblity = dictionary["key.setter_accessibility"] as? String

let isPrivate = isPrivateLevel(accessibility)
let isPrivateSet = isPrivateLevel(setterAccessiblity)

if isPrivate || (self.configuration.allowPrivateSet && isPrivateSet) {
return []
Expand All @@ -66,8 +67,11 @@ public struct PrivateOutletRule: ASTRule, OptInRule, ConfigurationProviderRule {
return [
StyleViolation(ruleDescription: self.dynamicType.description,
severity: configuration.severityConfiguration.severity,
location: location
)
location: location)
]
}

private func isPrivateLevel(identifier: String?) -> Bool {
return identifier.flatMap(AccessControlLevel.init(identifier:))?.isPrivate ?? false
}
}
6 changes: 3 additions & 3 deletions Source/SwiftLintFramework/Rules/PrivateUnitTestRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,15 @@ public struct PrivateUnitTestRule: ASTRule, ConfigurationProviderRule {
-> [StyleViolation] {

guard let acl = AccessControlLevel(dictionary) else { return [] }
switch acl {
case .Private:
if acl.isPrivate {
let offset = Int(dictionary["key.offset"] as? Int64 ?? 0)
return [StyleViolation(
ruleDescription: self.dynamicType.description,
severity: configuration.severityConfiguration.severity,
location: Location(file: file, byteOffset: offset),
reason: configuration.message)]
default: return []
}

return []
}
}