Skip to content

Commit 494f111

Browse files
committed
Add capability to convert stored property to computed property
1 parent fa81bf5 commit 494f111

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

Sources/SwiftRefactor/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
add_swift_syntax_library(SwiftRefactor
1010
AddSeparatorsToIntegerLiteral.swift
1111
CallToTrailingClosures.swift
12+
ConvertStoredPropertyToComputed.swift
1213
ExpandEditorPlaceholder.swift
1314
FormatRawStringLiteral.swift
1415
IntegerLiteralUtilities.swift
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#if swift(>=6)
14+
public import SwiftSyntax
15+
#else
16+
import SwiftSyntax
17+
#endif
18+
19+
public struct ConvertStoredPropertyToComputed: SyntaxRefactoringProvider {
20+
21+
public static func refactor(syntax: VariableDeclSyntax, in context: ()) -> VariableDeclSyntax? {
22+
guard syntax.bindings.count == 1, let binding = syntax.bindings.first, let initializer = binding.initializer else {
23+
return nil
24+
}
25+
26+
let body = CodeBlockItemSyntax(
27+
item: .expr(initializer.value)
28+
)
29+
30+
let newBinding = binding
31+
.with(\.initializer, nil)
32+
.with(
33+
\.accessorBlock,
34+
AccessorBlockSyntax(
35+
leftBrace: .leftBraceToken(trailingTrivia: .space),
36+
accessors: .getter(CodeBlockItemListSyntax([body])),
37+
rightBrace: .rightBraceToken(leadingTrivia: .space)
38+
)
39+
)
40+
41+
return syntax
42+
.with(\.bindingSpecifier, .keyword(.var, trailingTrivia: .space))
43+
.with(\.bindings, PatternBindingListSyntax([newBinding]))
44+
}
45+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftRefactor
14+
import SwiftSyntax
15+
import SwiftSyntaxBuilder
16+
import XCTest
17+
import _SwiftSyntaxTestSupport
18+
19+
final class ConvertStoredPropertyToComputedTest: XCTestCase {
20+
21+
func testRefactoringStoredPropertyWithInitializer1() throws {
22+
let baseline: DeclSyntax = """
23+
static let defaultColor: Color = .red
24+
"""
25+
26+
let expected: DeclSyntax = """
27+
static var defaultColor: Color { .red }
28+
"""
29+
30+
try assertRefactorConvert(baseline, expected: expected)
31+
}
32+
33+
func testRefactoringStoredPropertyWithInitializer2() throws {
34+
let baseline: DeclSyntax = """
35+
static let defaultColor: Color = Color.red
36+
"""
37+
38+
let expected: DeclSyntax = """
39+
static var defaultColor: Color { Color.red }
40+
"""
41+
42+
try assertRefactorConvert(baseline, expected: expected)
43+
}
44+
45+
func testRefactoringStoredPropertyWithInitializer3() throws {
46+
let baseline: DeclSyntax = """
47+
var defaultColor: Color = Color.red
48+
"""
49+
50+
let expected: DeclSyntax = """
51+
var defaultColor: Color { Color.red }
52+
"""
53+
54+
try assertRefactorConvert(baseline, expected: expected)
55+
}
56+
57+
func testRefactoringStoredPropertyWithInitializer4() throws {
58+
let baseline: DeclSyntax = """
59+
var defaultColor: Color = Color()
60+
"""
61+
62+
let expected: DeclSyntax = """
63+
var defaultColor: Color { Color() }
64+
"""
65+
66+
try assertRefactorConvert(baseline, expected: expected)
67+
}
68+
}
69+
70+
fileprivate func assertRefactorConvert(
71+
_ callDecl: DeclSyntax,
72+
expected: DeclSyntax?,
73+
file: StaticString = #filePath,
74+
line: UInt = #line
75+
) throws {
76+
try assertRefactor(
77+
callDecl,
78+
context: (),
79+
provider: ConvertStoredPropertyToComputed.self,
80+
expected: expected,
81+
file: file,
82+
line: line
83+
)
84+
}

0 commit comments

Comments
 (0)