-
Notifications
You must be signed in to change notification settings - Fork 434
/
Copy pathConvertComputedPropertyToStored.swift
84 lines (74 loc) · 2.7 KB
/
ConvertComputedPropertyToStored.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#if swift(>=6)
public import SwiftSyntax
#else
import SwiftSyntax
#endif
public struct ConvertComputedPropertyToStored: SyntaxRefactoringProvider {
public static func refactor(syntax: VariableDeclSyntax, in context: ()) -> VariableDeclSyntax? {
guard syntax.bindings.count == 1, let binding = syntax.bindings.first,
let accessorBlock = binding.accessorBlock, case .getter(let body) = accessorBlock.accessors, !body.isEmpty
else {
return nil
}
let refactored = { (initializer: InitializerClauseSyntax) -> VariableDeclSyntax in
let newBinding =
binding
.with(\.initializer, initializer)
.with(\.accessorBlock, nil)
let bindingSpecifier = syntax.bindingSpecifier
.with(\.tokenKind, .keyword(.let))
return
syntax
.with(\.bindingSpecifier, bindingSpecifier)
.with(\.bindings, PatternBindingListSyntax([newBinding]))
}
guard body.count == 1 else {
let closure = ClosureExprSyntax(
leftBrace: accessorBlock.leftBrace,
statements: body,
rightBrace: accessorBlock.rightBrace
)
return refactored(
InitializerClauseSyntax(
equal: .equalToken(trailingTrivia: .space),
value: FunctionCallExprSyntax(callee: closure)
)
)
}
guard body.count == 1, let item = body.first?.item else {
return nil
}
if let item = item.as(ReturnStmtSyntax.self), let expression = item.expression {
let trailingTrivia: Trivia = expression.leadingTrivia.isEmpty ? .space : []
return refactored(
InitializerClauseSyntax(
leadingTrivia: accessorBlock.leftBrace.trivia,
equal: .equalToken(trailingTrivia: trailingTrivia),
value: expression,
trailingTrivia: accessorBlock.rightBrace.trivia.droppingTrailingWhitespace
)
)
} else if var item = item.as(ExprSyntax.self) {
item.trailingTrivia = item.trailingTrivia.droppingTrailingWhitespace
return refactored(
InitializerClauseSyntax(
equal: .equalToken(trailingTrivia: .space),
value: item,
trailingTrivia: accessorBlock.trailingTrivia
)
)
}
return nil
}
}