mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-06-16 10:34:34 +00:00
Correctly handle init accessor
This commit is contained in:
@@ -2870,7 +2870,7 @@ extension Formatter {
|
||||
["static", "class"].contains(string)
|
||||
})
|
||||
if let name = name, classOrStatic || !staticSelf {
|
||||
processAccessors(["get", "set", "willSet", "didSet"], for: name,
|
||||
processAccessors(["get", "set", "willSet", "didSet", "init"], for: name,
|
||||
at: &index, localNames: localNames, members: members,
|
||||
typeStack: &typeStack, closureStack: &closureStack,
|
||||
membersByType: &membersByType,
|
||||
@@ -3160,8 +3160,15 @@ extension Formatter {
|
||||
assert(tokens[index] == .startOfScope("{"))
|
||||
var foundAccessors = false
|
||||
var localNames = localNames
|
||||
while let nextIndex = self.index(of: .nonSpaceOrCommentOrLinebreak, after: index, if: {
|
||||
if case let .identifier(name) = $0, names.contains(name) { return true } else { return false }
|
||||
while var nextIndex = self.index(of: .nonSpaceOrCommentOrLinebreak, after: index, if: {
|
||||
switch $0 {
|
||||
case .keyword where $0.isAttribute:
|
||||
return true
|
||||
case let .identifier(name), let .keyword(name):
|
||||
return names.contains(name)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}), let startIndex = self.index(of: .startOfScope("{"), after: nextIndex) {
|
||||
foundAccessors = true
|
||||
index = startIndex + 1
|
||||
@@ -3170,10 +3177,18 @@ extension Formatter {
|
||||
}), let varToken = next(.identifier, after: parenStart) {
|
||||
localNames.insert(varToken.unescaped())
|
||||
} else {
|
||||
switch tokens[nextIndex].string {
|
||||
var token = tokens[nextIndex]
|
||||
while token.isAttribute,
|
||||
let endIndex = endOfAttribute(at: nextIndex),
|
||||
let index = self.index(of: .nonSpaceOrCommentOrLinebreak, after: endIndex)
|
||||
{
|
||||
nextIndex = index
|
||||
token = tokens[nextIndex]
|
||||
}
|
||||
switch token.string {
|
||||
case "get":
|
||||
localNames.insert(name)
|
||||
case "set":
|
||||
case "set", "init":
|
||||
localNames.insert(name)
|
||||
localNames.insert("newValue")
|
||||
case "willSet":
|
||||
|
||||
@@ -994,7 +994,7 @@ private struct Inference {
|
||||
prevIndex -= 1
|
||||
}
|
||||
if let name = name {
|
||||
processAccessors(["get", "set", "willSet", "didSet"], for: name,
|
||||
processAccessors(["get", "set", "willSet", "didSet", "init"], for: name,
|
||||
at: &index, localNames: localNames, members: members,
|
||||
typeStack: &typeStack, membersByType: &membersByType,
|
||||
classMembersByType: &classMembersByType,
|
||||
|
||||
@@ -668,7 +668,7 @@ extension Formatter {
|
||||
|
||||
func isAccessorKeyword(at i: Int, checkKeyword: Bool = true) -> Bool {
|
||||
guard !checkKeyword ||
|
||||
["get", "set", "willSet", "didSet"].contains(token(at: i)?.string ?? ""),
|
||||
["get", "set", "willSet", "didSet", "init"].contains(token(at: i)?.string ?? ""),
|
||||
var prevIndex = index(of: .nonSpaceOrCommentOrLinebreak, before: i)
|
||||
else {
|
||||
return false
|
||||
@@ -1120,7 +1120,7 @@ extension Formatter {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case "get", "set", "willSet", "didSet":
|
||||
case "get", "set", "willSet", "didSet", "init":
|
||||
return isAccessorKeyword(at: i, checkKeyword: false)
|
||||
case "actor":
|
||||
if last(.nonSpaceOrCommentOrLinebreak, before: i)?.isOperator(ofType: .infix) == true {
|
||||
|
||||
@@ -625,6 +625,18 @@ class ParsingHelpersTests: XCTestCase {
|
||||
XCTAssert(formatter.isAccessorKeyword(at: 34))
|
||||
}
|
||||
|
||||
func testInit() {
|
||||
let formatter = Formatter(tokenize("""
|
||||
var foo: Int {
|
||||
init {}
|
||||
get {}
|
||||
set {}
|
||||
}
|
||||
"""))
|
||||
XCTAssert(formatter.isAccessorKeyword(at: 10))
|
||||
XCTAssert(formatter.isAccessorKeyword(at: 16))
|
||||
}
|
||||
|
||||
func testNotGetter() {
|
||||
let formatter = Formatter(tokenize("""
|
||||
func foo() {
|
||||
@@ -644,6 +656,15 @@ class ParsingHelpersTests: XCTestCase {
|
||||
XCTAssert(formatter.isAccessorKeyword(at: 10, checkKeyword: false))
|
||||
}
|
||||
|
||||
func testNotSetterInit() {
|
||||
let formatter = Formatter(tokenize("""
|
||||
class Foo {
|
||||
init() { print("") }
|
||||
}
|
||||
"""))
|
||||
XCTAssertFalse(formatter.isAccessorKeyword(at: 7))
|
||||
}
|
||||
|
||||
// MARK: isEnumCase
|
||||
|
||||
func testIsEnumCase() {
|
||||
|
||||
@@ -6230,6 +6230,50 @@ class RedundancyTests: RulesTests {
|
||||
testFormatting(for: input, rule: FormatRules.redundantSelf, options: options)
|
||||
}
|
||||
|
||||
func testPropertyInitNotInterpretedAsTypeInit() {
|
||||
let input = """
|
||||
struct MyStruct {
|
||||
private var __myVar: String
|
||||
var myVar: String {
|
||||
@storageRestrictions(initializes: __myVar)
|
||||
init(initialValue) {
|
||||
__myVar = initialValue
|
||||
}
|
||||
set {
|
||||
__myVar = newValue
|
||||
}
|
||||
get {
|
||||
__myVar
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(explicitSelf: .initOnly)
|
||||
testFormatting(for: input, rule: FormatRules.redundantSelf, options: options)
|
||||
}
|
||||
|
||||
func testPropertyInitNotInterpretedAsTypeInit2() {
|
||||
let input = """
|
||||
struct MyStruct {
|
||||
private var __myVar: String
|
||||
var myVar: String {
|
||||
@storageRestrictions(initializes: __myVar)
|
||||
init {
|
||||
__myVar = newValue
|
||||
}
|
||||
set {
|
||||
__myVar = newValue
|
||||
}
|
||||
get {
|
||||
__myVar
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(explicitSelf: .initOnly)
|
||||
testFormatting(for: input, rule: FormatRules.redundantSelf, options: options)
|
||||
}
|
||||
|
||||
// parsing bugs
|
||||
|
||||
func testSelfRemovalParsingBug() {
|
||||
|
||||
Reference in New Issue
Block a user