@@ -43,65 +43,109 @@ public struct Trivia: Sendable {
43
43
}
44
44
45
45
/// 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 {
49
47
var comments = [ String] ( )
50
- var partialComments = [ String] ( )
51
48
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
+ }
55
71
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
+ }
60
90
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)
63
94
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 ( )
70
96
71
- appendPartialCommentIfPossible ( sanitized)
97
+ let minIndentation =
98
+ lines
99
+ . filter { !$0. isEmpty }
100
+ . map { $0. prefix { $0 == " " } . count }
101
+ . min ( ) ?? 0
72
102
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 ( )
76
106
} else {
77
- comments. append ( String ( text. trimmingPrefix ( " / " ) ) )
107
+ lines [ lines. count - 1 ] . removeLast ( 2 )
108
+ lines [ lines. count - 1 ] = trimWhitespace ( lines [ lines. count - 1 ] )
78
109
}
79
-
80
- default :
81
- break
82
110
}
83
111
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 ) )
87
115
}
88
- }
89
116
90
- if !partialComments. isEmpty {
91
- appendSubstringsToLines ( )
117
+ return unindentedLines. joined ( separator: " \n " )
92
118
}
93
119
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) ) )
99
143
100
- func appendSubstringsToLines( ) {
101
- comments. append ( partialComments. joined ( separator: " " ) )
144
+ default :
145
+ break
146
+ }
102
147
}
103
-
104
- return comments
148
+ return comments. joined ( separator: " \n " )
105
149
}
106
150
107
151
/// The length of all the pieces in this ``Trivia``.
0 commit comments