Skip to content

Commit

Permalink
Fix some false positives in rule explicit_self (realm#3368)
Browse files Browse the repository at this point in the history
  • Loading branch information
svenmuennich authored Sep 25, 2020
1 parent 15c25ab commit da408b5
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
[JP Simard](https://github.com/jpsim)
[#3365](https://github.com/realm/SwiftLint/issues/3365)

* Fix some false positives in rule `explicit_self`.
[Sven Münnich](https://github.com/svenmuennich)

## 0.40.3: Greased Up Drum Bearings

#### Breaking
Expand Down
96 changes: 94 additions & 2 deletions Source/SwiftLintFramework/Rules/Style/ExplicitSelfRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ public struct ExplicitSelfRule: CorrectableRule, ConfigurationProviderRule, Anal
_ = self.p1
}
}
"""),
Example("""
@propertyWrapper
struct Wrapper<Value> {
let wrappedValue: Value
var projectedValue: [Value] {
[self.wrappedValue]
}
}
struct A {
@Wrapper var p1: Int
func f1() {
self.$p1
self._p1
}
}
func f1() {
A(p1: 10).$p1
}
""")
],
triggeringExamples: [
Expand All @@ -45,6 +64,25 @@ public struct ExplicitSelfRule: CorrectableRule, ConfigurationProviderRule, Anal
_ = ↓p1
}
}
"""),
Example("""
@propertyWrapper
struct Wrapper<Value> {
let wrappedValue: Value
var projectedValue: [Value] {
[self.wrappedValue]
}
}
struct A {
@Wrapper var p1: Int
func f1() {
↓$p1
↓_p1
}
}
func f1() {
A(p1: 10).$p1
}
""")
],
corrections: [
Expand Down Expand Up @@ -79,6 +117,43 @@ public struct ExplicitSelfRule: CorrectableRule, ConfigurationProviderRule, Anal
_ = self.p1
}
}
"""),
Example("""
@propertyWrapper
struct Wrapper<Value> {
let wrappedValue: Value
var projectedValue: [Value] {
[self.wrappedValue]
}
}
struct A {
@Wrapper var p1: Int
func f1() {
↓$p1
↓_p1
}
}
func f1() {
A(p1: 10).$p1
}
"""): Example("""
@propertyWrapper
struct Wrapper<Value> {
let wrappedValue: Value
var projectedValue: [Value] {
[self.wrappedValue]
}
}
struct A {
@Wrapper var p1: Int
func f1() {
self.$p1
self._p1
}
}
func f1() {
A(p1: 10).$p1
}
""")
],
requiresFileOnDisk: true
Expand Down Expand Up @@ -159,13 +234,30 @@ private extension SwiftLintFile {
func allCursorInfo(compilerArguments: [String], atByteOffsets byteOffsets: [ByteCount]) throws
-> [[String: SourceKitRepresentable]] {
return try byteOffsets.compactMap { offset in
if stringView.substringWithByteRange(ByteRange(location: offset - 1, length: 1))! == "." { return nil }
if isExplicitAccess(at: offset) { return nil }
var cursorInfo = try Request.cursorInfo(file: self.path!, offset: offset,
arguments: compilerArguments).sendIfNotDisabled()
cursorInfo["swiftlint.offset"] = Int64(offset.value)

// Accessing a `projectedValue` of a property wrapper (e.g. `self.$foo`) or the property wrapper itself
// (e.g. `self._foo`) results in an incorrect `key.length` (it does not account for the identifier
// prefixes `$` and `_`), while `key.name` contains the prefix. Hence we need to check for explicit access
// at a corrected offset as well.
var prefixLength: Int64 = 0
if let name = cursorInfo["key.name"] as? String, let length = cursorInfo["key.length"] as? Int64 {
prefixLength = Int64(name.count) - length
if prefixLength > 0, isExplicitAccess(at: offset - ByteCount(prefixLength)) {
return nil
}
}

cursorInfo["swiftlint.offset"] = Int64(offset.value) - prefixLength
return cursorInfo
}
}

private func isExplicitAccess(at location: ByteCount) -> Bool {
stringView.substringWithByteRange(ByteRange(location: location - 1, length: 1))! == "."
}
}

private extension StringView {
Expand Down

0 comments on commit da408b5

Please sign in to comment.