@@ -74,19 +74,40 @@ public enum CType {
74
74
extension CType : CustomStringConvertible {
75
75
/// Print the part of this type that comes before the declarator, appending
76
76
/// it to the provided `result` string.
77
- func printBefore( result: inout String ) {
77
+ func printBefore( hasEmptyPlaceholder: inout Bool , result: inout String ) {
78
+ // Save the value of hasEmptyPlaceholder and restore it once we're done
79
+ // here.
80
+ let previousHasEmptyPlaceholder = hasEmptyPlaceholder
81
+ defer {
82
+ hasEmptyPlaceholder = previousHasEmptyPlaceholder
83
+ }
84
+
78
85
switch self {
79
86
case . floating( let floating) :
80
87
switch floating {
81
88
case . float: result += " float "
82
89
case . double: result += " double "
83
90
}
84
91
92
+ spaceBeforePlaceHolder (
93
+ hasEmptyPlaceholder: hasEmptyPlaceholder,
94
+ result: & result
95
+ )
96
+
85
97
case . function( resultType: let resultType, parameters: _, variadic: _) :
86
- resultType. printBefore ( result: & result)
98
+ let previousHasEmptyPlaceholder = hasEmptyPlaceholder
99
+ hasEmptyPlaceholder = false
100
+ defer {
101
+ hasEmptyPlaceholder = previousHasEmptyPlaceholder
102
+ }
103
+ resultType. printBefore (
104
+ hasEmptyPlaceholder: & hasEmptyPlaceholder,
105
+ result: & result
106
+ )
87
107
88
- // FIXME: Clang inserts a parentheses in here if there's a non-empty
89
- // placeholder, which is Very Stateful. How should I model that?
108
+ if !previousHasEmptyPlaceholder {
109
+ result += " ( "
110
+ }
90
111
91
112
case . integral( let integral) :
92
113
switch integral {
@@ -97,21 +118,47 @@ extension CType: CustomStringConvertible {
97
118
case . size_t: result += " size_t "
98
119
}
99
120
121
+ spaceBeforePlaceHolder (
122
+ hasEmptyPlaceholder: hasEmptyPlaceholder,
123
+ result: & result
124
+ )
125
+
100
126
case . pointer( let pointee) :
101
- pointee. printBefore ( result: & result)
127
+ var innerHasEmptyPlaceholder = false
128
+ pointee. printBefore (
129
+ hasEmptyPlaceholder: & innerHasEmptyPlaceholder,
130
+ result: & result
131
+ )
102
132
result += " * "
103
133
104
134
case . qualified( const: let isConst, volatile: let isVolatile, type: let underlying) :
105
- underlying. printBefore ( result: & result)
135
+ if isConst || isVolatile {
136
+ hasEmptyPlaceholder = false
137
+ }
138
+
139
+ underlying. printBefore ( hasEmptyPlaceholder: & hasEmptyPlaceholder, result: & result)
106
140
107
141
// FIXME: "east const" is easier to print correctly, so do that. We could
108
142
// follow Clang and decide when it's correct to print "west const" by
109
143
// splitting the qualifiers before we get here.
110
144
if isConst {
111
- result += " const "
145
+ result += " const "
146
+ hasEmptyPlaceholder = false
147
+
148
+ spaceBeforePlaceHolder (
149
+ hasEmptyPlaceholder: hasEmptyPlaceholder,
150
+ result: & result
151
+ )
152
+
112
153
}
113
154
if isVolatile {
114
- result += " volatile "
155
+ result += " volatile "
156
+ hasEmptyPlaceholder = false
157
+
158
+ spaceBeforePlaceHolder (
159
+ hasEmptyPlaceholder: hasEmptyPlaceholder,
160
+ result: & result
161
+ )
115
162
}
116
163
117
164
case . tag( let tag) :
@@ -121,7 +168,18 @@ extension CType: CustomStringConvertible {
121
168
case . union( let cUnion) : result += " union \( cUnion. name) "
122
169
}
123
170
124
- case . void: result += " void "
171
+ spaceBeforePlaceHolder (
172
+ hasEmptyPlaceholder: hasEmptyPlaceholder,
173
+ result: & result
174
+ )
175
+
176
+ case . void:
177
+ result += " void "
178
+
179
+ spaceBeforePlaceHolder (
180
+ hasEmptyPlaceholder: hasEmptyPlaceholder,
181
+ result: & result
182
+ )
125
183
}
126
184
}
127
185
@@ -146,13 +204,14 @@ extension CType: CustomStringConvertible {
146
204
147
205
/// Print the part of the type that comes after the declarator, appending
148
206
/// it to the provided `result` string.
149
- func printAfter( result: inout String ) {
207
+ func printAfter( hasEmptyPlaceholder : inout Bool , result: inout String ) {
150
208
switch self {
151
209
case . floating, . integral, . tag, . void: break
152
210
153
211
case . function( resultType: let resultType, parameters: let parameters, variadic: let variadic) :
154
- // FIXME: Clang inserts a parentheses in here if there's a non-empty
155
- // placeholder, which is Very Stateful. How should I model that?
212
+ if !hasEmptyPlaceholder {
213
+ result += " ) "
214
+ }
156
215
157
216
result += " ( "
158
217
@@ -167,33 +226,53 @@ extension CType: CustomStringConvertible {
167
226
168
227
result += " ) "
169
228
170
- resultType. printAfter ( result: & result)
229
+ var innerHasEmptyPlaceholder = false
230
+ resultType. printAfter (
231
+ hasEmptyPlaceholder: & innerHasEmptyPlaceholder,
232
+ result: & result
233
+ )
171
234
172
235
case . pointer( let pointee) :
173
- pointee. printAfter ( result: & result)
236
+ var innerHasEmptyPlaceholder = false
237
+ pointee. printAfter (
238
+ hasEmptyPlaceholder: & innerHasEmptyPlaceholder,
239
+ result: & result
240
+ )
174
241
175
242
case . qualified( const: _, volatile: _, type: let underlying) :
176
- underlying. printAfter ( result: & result)
243
+ underlying. printAfter (
244
+ hasEmptyPlaceholder: & hasEmptyPlaceholder,
245
+ result: & result
246
+ )
177
247
}
178
248
}
179
249
180
250
/// Print this type into a string, with the given placeholder as the name
181
251
/// of the entity being declared.
182
252
public func print( placeholder: String ? ) -> String {
253
+ var hasEmptyPlaceholder = ( placeholder == nil )
183
254
var result = " "
184
- printBefore ( result: & result)
255
+ printBefore ( hasEmptyPlaceholder : & hasEmptyPlaceholder , result: & result)
185
256
if let placeholder {
186
- result += " "
187
257
result += placeholder
188
258
}
189
- printAfter ( result: & result)
259
+ printAfter ( hasEmptyPlaceholder : & hasEmptyPlaceholder , result: & result)
190
260
return result
191
261
}
192
262
193
263
/// Render the C type into a string that represents the type in C.
194
264
public var description : String {
195
265
print ( placeholder: nil )
196
266
}
267
+
268
+ private func spaceBeforePlaceHolder(
269
+ hasEmptyPlaceholder: Bool ,
270
+ result: inout String
271
+ ) {
272
+ if !hasEmptyPlaceholder {
273
+ result += " "
274
+ }
275
+ }
197
276
}
198
277
199
278
extension CType {
0 commit comments