@@ -43,65 +43,109 @@ public struct Trivia: Sendable {
4343 }
4444
4545 /// The string contents of all the comment pieces with any comments tokens trimmed.
46- ///
47- /// Each element in the array is the trimmed contents of a line comment, or, in the case of a multi-line comment a trimmed, concatenated single string.
48- public var commentValues : [ String ] {
46+ public var commentValue : String {
4947 var comments = [ String] ( )
50- var partialComments = [ String] ( )
5148
52- var foundStartOfCodeBlock = false
53- var foundEndOfCodeBlock = false
54- var isInCodeBlock : Bool { foundStartOfCodeBlock && !foundEndOfCodeBlock }
49+ // Determine if all line comments have a single space
50+ lazy var allLineCommentsHaveSpace : Bool = {
51+ return pieces. allSatisfy { piece in
52+ switch piece {
53+ case . lineComment( let text) :
54+ return text. hasPrefix ( " // " )
55+ case . docLineComment( let text) :
56+ return text. hasPrefix ( " /// " )
57+ default :
58+ return true
59+ }
60+ }
61+ } ( )
62+
63+ // Helper function to trim leading and trailing whitespace
64+ func trimWhitespace( _ text: String ) -> String {
65+ let trimmed = text. drop ( while: { $0 == " " } )
66+ . reversed ( )
67+ . drop ( while: { $0 == " " } )
68+ . reversed ( )
69+ return String ( trimmed)
70+ }
5571
56- for piece in pieces {
57- switch piece {
58- case . blockComment( let text) , . docBlockComment( let text) :
59- let text = text. trimmingCharacters ( in: " \n " )
72+ // Helper function to trim leading and trailing newlines
73+ func trimNewlines( _ text: String ) -> String {
74+ let trimmed = text. drop ( while: { $0 == " \n " } )
75+ . reversed ( )
76+ . drop ( while: { $0 == " \n " } )
77+ . reversed ( )
78+ return String ( trimmed)
79+ }
80+
81+ // Helper function to process block comments
82+ func processBlockComment( _ text: String , prefix: String , suffix: String ) -> String {
83+ var text = text
84+ text. removeFirst ( prefix. count)
85+ text. removeLast ( suffix. count)
86+ text = trimWhitespace ( text)
87+ text = trimNewlines ( text)
88+ return text
89+ }
6090
61- foundStartOfCodeBlock = text. hasPrefix ( " /*")
62- foundEndOfCodeBlock = text.hasSuffix("*/" )
91+ // Helper function to process multiline block comments
92+ func processMultilineBlockComment( _ text: String ) -> String {
93+ var lines = text. split ( separator: " \n " , omittingEmptySubsequences: false ) . map ( String . init)
6394
64- let sanitized =
65- text
66- . split ( separator: " \n " )
67- . map { $0. trimmingAnyCharacters ( in: " /* " ) . trimmingAnyCharacters ( in: " " ) }
68- . filter { !$0. isEmpty }
69- . joined ( separator: " " )
95+ lines. removeFirst ( )
7096
71- appendPartialCommentIfPossible ( sanitized)
97+ let minIndentation =
98+ lines
99+ . filter { !$0. isEmpty }
100+ . map { $0. prefix { $0 == " " } . count }
101+ . min ( ) ?? 0
72102
73- case . lineComment ( let text ) , . docLineComment ( let text ) :
74- if isInCodeBlock {
75- appendPartialCommentIfPossible ( text )
103+ if let lastLine = lines . last {
104+ if trimWhitespace ( lastLine ) == " */ " {
105+ lines . removeLast ( )
76106 } else {
77- comments. append ( String ( text. trimmingPrefix ( " / " ) ) )
107+ lines [ lines. count - 1 ] . removeLast ( 2 )
108+ lines [ lines. count - 1 ] = trimWhitespace ( lines [ lines. count - 1 ] )
78109 }
79-
80- default :
81- break
82110 }
83111
84- if foundEndOfCodeBlock , !partialComments . isEmpty {
85- appendSubstringsToLines ( )
86- partialComments . removeAll ( )
112+ let unindentedLines = lines . map { line in
113+ guard line . count >= minIndentation else { return line }
114+ return String ( line . dropFirst ( minIndentation ) )
87115 }
88- }
89116
90- if !partialComments. isEmpty {
91- appendSubstringsToLines ( )
117+ return unindentedLines. joined ( separator: " \n " )
92118 }
93119
94- func appendPartialCommentIfPossible( _ text: String ) {
95- guard partialComments. isEmpty || !text. isEmpty else { return }
96-
97- partialComments. append ( text)
98- }
120+ for piece in pieces {
121+ switch piece {
122+ case . blockComment( let text) :
123+ let processedText =
124+ text. hasPrefix ( " /* \n " )
125+ ? processMultilineBlockComment ( text)
126+ : processBlockComment ( text, prefix: " /*", suffix: "*/" )
127+ comments. append ( processedText)
128+
129+ case . docBlockComment( let text) :
130+ let processedText =
131+ text. hasPrefix ( " /** \n " )
132+ ? processMultilineBlockComment ( text)
133+ : processBlockComment ( text, prefix: " /**", suffix: "*/" )
134+ comments. append ( processedText)
135+
136+ case . lineComment( let text) :
137+ let prefix = allLineCommentsHaveSpace ? " // " : " // "
138+ comments. append ( String ( text. dropFirst ( prefix. count) ) )
139+
140+ case . docLineComment( let text) :
141+ let prefix = allLineCommentsHaveSpace ? " /// " : " /// "
142+ comments. append ( String ( text. dropFirst ( prefix. count) ) )
99143
100- func appendSubstringsToLines( ) {
101- comments. append ( partialComments. joined ( separator: " " ) )
144+ default :
145+ break
146+ }
102147 }
103-
104- return comments
148+ return comments. joined ( separator: " \n " )
105149 }
106150
107151 /// The length of all the pieces in this ``Trivia``.
0 commit comments