@@ -52,13 +52,39 @@ extension FixIt {
52
52
53
53
// MARK: - Make missing
54
54
55
+ private extension FixIt . Change {
56
+ /// Transfers the leading and trailing trivia of `nodes` to the previous token
57
+ /// While doing this, it tries to be smart, merging trivia where it makes sense
58
+ /// and refusing to add e.g. a space after punctuation, where it usually
59
+ /// doesn't make sense.
60
+ static func transferTriviaAtSides( from nodes: [ some SyntaxProtocol ] ) -> Self ? {
61
+ guard let first = nodes. first, let last = nodes. last else {
62
+ preconditionFailure ( " nodes must not be empty " )
63
+ }
64
+ let removedTriviaAtSides = first. leadingTrivia. mergingCommonSuffix ( last. trailingTrivia)
65
+ guard !removedTriviaAtSides. isEmpty, let previousToken = first. previousToken ( viewMode: . sourceAccurate) else {
66
+ return nil
67
+ }
68
+ let mergedTrivia = previousToken. trailingTrivia. mergingCommonPrefix ( removedTriviaAtSides)
69
+ // We merge with the common prefix instead of the common suffix to preserve the original shape of the previous
70
+ // token's trailing trivia after merging.
71
+ guard !previousToken. tokenKind. isPunctuation || !mergedTrivia. allSatisfy ( \. isSpaceOrTab) else {
72
+ // Punctuation is generally not followed by spaces in Swift.
73
+ // If this action would only add spaces to the punctuation, drop it.
74
+ // This generally yields better results.
75
+ return nil
76
+ }
77
+ return . replaceTrailingTrivia( token: previousToken, newTrivia: mergedTrivia)
78
+ }
79
+ }
80
+
55
81
extension FixIt . MultiNodeChange {
56
- /// Replaced a present token with a missing node .
82
+ /// Replaced a present token with a missing token .
57
83
///
58
84
/// If `transferTrivia` is `true`, the leading and trailing trivia of the
59
- /// removed node will be transferred to the trailing trivia of the previous token.
85
+ /// removed token will be transferred to the trailing trivia of the previous token.
60
86
static func makeMissing( _ token: TokenSyntax , transferTrivia: Bool = true ) -> Self {
61
- return makeMissing ( [ token] , transferTrivia: transferTrivia)
87
+ self . makeMissing ( [ token] , transferTrivia: transferTrivia)
62
88
}
63
89
64
90
/// Replace present tokens with missing tokens.
@@ -68,57 +94,33 @@ extension FixIt.MultiNodeChange {
68
94
/// tokens.
69
95
static func makeMissing( _ tokens: [ TokenSyntax ] , transferTrivia: Bool = true ) -> Self {
70
96
precondition ( tokens. allSatisfy ( \. isPresent) )
71
- return . makeMissing( tokens. map ( Syntax . init) , transferTrivia: transferTrivia)
97
+ return self . makeMissing ( tokens. map ( Syntax . init) , transferTrivia: transferTrivia)
72
98
}
73
99
74
100
/// If `transferTrivia` is `true`, the leading and trailing trivia of the
75
101
/// removed node will be transferred to the trailing trivia of the previous token.
76
102
static func makeMissing( _ node: ( some SyntaxProtocol ) ? , transferTrivia: Bool = true ) -> Self {
77
- guard let node = node else {
103
+ guard let node else {
78
104
return FixIt . MultiNodeChange ( primitiveChanges: [ ] )
79
105
}
80
- var changes = [ FixIt . Change. replace ( oldNode: Syntax ( node) , newNode: MissingMaker ( ) . rewrite ( node, detach: true ) ) ]
81
- if transferTrivia {
82
- changes += FixIt . MultiNodeChange. transferTriviaAtSides ( from: [ node] ) . primitiveChanges
83
- }
84
- return FixIt . MultiNodeChange ( primitiveChanges: changes)
85
- }
86
-
87
- /// Transfers the leading and trailing trivia of `nodes` to the previous token
88
- /// While doing this, it tries to be smart, merging trivia where it makes sense
89
- /// and refusing to add e.g. a space after punctuation, where it usually
90
- /// doesn't make sense.
91
- private static func transferTriviaAtSides( from nodes: [ some SyntaxProtocol ] ) -> Self {
92
- let removedTriviaAtSides = ( nodes. first? . leadingTrivia ?? [ ] ) . merging ( nodes. last? . trailingTrivia ?? [ ] )
93
- if !removedTriviaAtSides. isEmpty, let previousToken = nodes. first? . previousToken ( viewMode: . sourceAccurate) {
94
- let mergedTrivia = previousToken. trailingTrivia. merging ( removedTriviaAtSides)
95
- if previousToken. tokenKind. isPunctuation, mergedTrivia. allSatisfy ( { $0. isSpaceOrTab } ) {
96
- // Punctuation is generally not followed by spaces in Swift.
97
- // If this action would only add spaces to the punctuation, drop it.
98
- // This generally yields better results.
99
- return FixIt . MultiNodeChange ( )
100
- }
101
- return FixIt . MultiNodeChange ( . replaceTrailingTrivia( token: previousToken, newTrivia: mergedTrivia) )
102
- } else {
103
- return FixIt . MultiNodeChange ( )
104
- }
106
+ return self . makeMissing ( [ node] , transferTrivia: transferTrivia)
105
107
}
106
108
107
- /// Replace present nodes with their missing equivalents .
109
+ /// Replace present nodes with missing nodes .
108
110
///
109
111
/// If `transferTrivia` is `true`, the leading trivia of the first node and
110
112
/// the trailing trivia of the last node will be transferred to their adjecent
111
113
/// tokens.
112
- static func makeMissing( _ nodes: [ Syntax ] , transferTrivia: Bool = true ) -> Self {
114
+ static func makeMissing( _ nodes: [ some SyntaxProtocol ] , transferTrivia: Bool = true ) -> Self {
113
115
precondition ( !nodes. isEmpty)
114
116
var changes = nodes. map {
115
117
FixIt . Change. replace (
116
- oldNode: $0 ,
118
+ oldNode: Syntax ( $0 ) ,
117
119
newNode: MissingMaker ( ) . rewrite ( $0, detach: true )
118
120
)
119
121
}
120
- if transferTrivia {
121
- changes += FixIt . MultiNodeChange . transferTriviaAtSides ( from : nodes ) . primitiveChanges
122
+ if transferTrivia, let transferredTrivia = FixIt . Change . transferTriviaAtSides ( from : nodes ) {
123
+ changes. append ( transferredTrivia )
122
124
}
123
125
return FixIt . MultiNodeChange ( primitiveChanges: changes)
124
126
}
0 commit comments