@@ -177,17 +177,19 @@ extension DeclSyntaxProtocol {
177177 var signatureString : String {
178178 return switch DeclSyntax ( self . detached) . as ( DeclSyntaxEnum . self) {
179179 case . functionDecl( let node) :
180- node. with ( \. body, nil ) . trimmedDescription
180+ node. with ( \. body, nil ) . triviaSanitizedDescription
181181 case . initializerDecl( let node) :
182- node. with ( \. body, nil ) . trimmedDescription
182+ node. with ( \. body, nil ) . triviaSanitizedDescription
183183 case . classDecl( let node) :
184- node. with ( \. memberBlock, " " ) . trimmedDescription
184+ node. with ( \. memberBlock, " " ) . triviaSanitizedDescription
185185 case . structDecl( let node) :
186- node. with ( \. memberBlock, " " ) . trimmedDescription
186+ node. with ( \. memberBlock, " " ) . triviaSanitizedDescription
187187 case . protocolDecl( let node) :
188- node. with ( \. memberBlock, " " ) . trimmedDescription
188+ node. with ( \. memberBlock, " " ) . triviaSanitizedDescription
189189 case . accessorDecl( let node) :
190- node. with ( \. body, nil ) . trimmedDescription
190+ node. with ( \. body, nil ) . triviaSanitizedDescription
191+ case . subscriptDecl( let node) :
192+ node. with ( \. accessorBlock, nil ) . triviaSanitizedDescription
191193 case . variableDecl( let node) :
192194 node
193195 . with ( \. bindings, PatternBindingListSyntax (
@@ -197,9 +199,47 @@ extension DeclSyntaxProtocol {
197199 . with ( \. initializer, nil )
198200 }
199201 ) )
200- . trimmedDescription
202+ . triviaSanitizedDescription
201203 default :
202204 fatalError ( " unimplemented \( self . kind) " )
203205 }
204206 }
207+
208+ /// Syntax text but without unnecessary trivia.
209+ ///
210+ /// Connective trivia are condensed into a single whitespace, but no space
211+ /// after opening or before closing parentheses
212+ var triviaSanitizedDescription : String {
213+ let visitor = TriviaSanitizingDescriptionVisitor ( viewMode: . sourceAccurate)
214+ visitor. walk ( self . trimmed)
215+ return visitor. result
216+ }
217+ }
218+
219+ class TriviaSanitizingDescriptionVisitor : SyntaxVisitor {
220+ var result : String = " "
221+
222+ var prevTokenKind : TokenKind = . endOfFile
223+ var prevHadTrailingSpace : Bool = false
224+
225+ override func visit( _ node: TokenSyntax ) -> SyntaxVisitorContinueKind {
226+ let tokenKind = node. tokenKind
227+ switch ( prevTokenKind, tokenKind) {
228+ case
229+ // No whitespace after open parentheses.
230+ ( . leftAngle, _) , ( . leftParen, _) , ( . leftSquare, _) , ( . endOfFile, _) ,
231+ // No whitespace before close parentheses.
232+ ( _, . rightAngle) , ( _, . rightParen) , ( _, . rightSquare) :
233+ break
234+ default :
235+ if prevHadTrailingSpace || !node. leadingTrivia. isEmpty {
236+ result += " "
237+ }
238+ }
239+ result += node. text
240+ prevTokenKind = tokenKind
241+ prevHadTrailingSpace = !node. trailingTrivia. isEmpty
242+
243+ return . skipChildren
244+ }
205245}
0 commit comments