Skip to content

Commit 392167b

Browse files
committed
Add a compiler SPI for "description without comments"
Introduce a new `SyntaxProtocol.descriptionWithoutComments` that removes comments from the given syntax, replacing them with either a space (if the comment has no newlines) or a newline (if it does have newlines).
1 parent 45bf2b8 commit 392167b

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

Sources/SwiftIfConfig/ActiveSyntaxRewriter.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,38 @@ extension IfConfigDeclSyntax {
379379
}
380380
}
381381
}
382+
383+
extension SyntaxProtocol {
384+
// Produce the source code for this syntax node with all of the comments
385+
// removed. Each comment will be replaced with either a newline or a space,
386+
// depending on whether the comment involved a newline.
387+
@_spi(Compiler)
388+
public var descriptionWithoutComments: String {
389+
var result = ""
390+
for token in tokens(viewMode: .sourceAccurate) {
391+
token.leadingTrivia.writeWithoutComments(to: &result)
392+
token.text.write(to: &result)
393+
token.trailingTrivia.writeWithoutComments(to: &result)
394+
}
395+
return result
396+
}
397+
}
398+
399+
extension Trivia {
400+
fileprivate func writeWithoutComments(to stream: inout some TextOutputStream) {
401+
for piece in pieces {
402+
switch piece {
403+
case .backslashes, .carriageReturnLineFeeds, .carriageReturns, .formfeeds, .newlines, .pounds, .spaces, .tabs,
404+
.unexpectedText, .verticalTabs:
405+
piece.write(to: &stream)
406+
407+
case .blockComment(let text), .docBlockComment(let text), .docLineComment(let text), .lineComment(let text):
408+
if text.contains(where: \.isNewline) {
409+
stream.write("\n")
410+
} else {
411+
stream.write(" ")
412+
}
413+
}
414+
}
415+
}
416+
}

Tests/SwiftIfConfigTest/VisitorTests.swift

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import SwiftDiagnostics
14-
import SwiftIfConfig
14+
@_spi(Compiler) import SwiftIfConfig
1515
import SwiftParser
1616
import SwiftSyntax
1717
@_spi(XCTestFailureLocation) @_spi(Testing) import SwiftSyntaxMacrosGenericTestSupport
@@ -299,6 +299,42 @@ public class VisitorTests: XCTestCase {
299299
"""
300300
)
301301
}
302+
303+
func testRemoveComments() {
304+
let original: SourceFileSyntax = """
305+
306+
/// This is a documentation comment
307+
func f() { }
308+
309+
/** Another documentation comment
310+
that is split across
311+
multiple lines */
312+
func g() { }
313+
314+
func h() {
315+
x +/*comment*/y
316+
// foo
317+
}
318+
"""
319+
320+
assertStringsEqualWithDiff(
321+
original.descriptionWithoutComments,
322+
"""
323+
324+
325+
func f() { }
326+
327+
328+
329+
func g() { }
330+
331+
func h() {
332+
x + y
333+
334+
}
335+
"""
336+
)
337+
}
302338
}
303339

304340
/// Assert that applying the given build configuration to the source code

0 commit comments

Comments
 (0)