Skip to content

Commit 6906d27

Browse files
committed
Account for qualifiers in SwiftifyImport macro
1 parent 23ca6b9 commit 6906d27

File tree

1 file changed

+36
-7
lines changed

1 file changed

+36
-7
lines changed

lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,13 +204,42 @@ func replaceBaseType(_ type: TypeSyntax, _ base: TypeSyntax) -> TypeSyntax {
204204
return base
205205
}
206206

207+
// C++ type qualifiers, `const T` and `volatile T`, are encoded as fake generic
208+
// types, `__cxxConst<T>` and `__cxxVolatile<T>` respectively. Remove those.
209+
func dropQualifierGenerics(_ type: TypeSyntax) -> TypeSyntax {
210+
guard let identifier = type.as(IdentifierTypeSyntax.self) else { return type }
211+
guard let generic = identifier.genericArgumentClause else { return type }
212+
guard let genericArg = generic.arguments.first else { return type }
213+
guard case .type(let argType) = genericArg.argument else { return type }
214+
switch identifier.name.text {
215+
case "__cxxConst", "__cxxVolatile":
216+
return dropQualifierGenerics(argType)
217+
default:
218+
return type
219+
}
220+
}
221+
222+
// The `const` type qualifier used to be encoded as a `_const` suffix on type
223+
// names (though this causes issues for more complex types). We still drop the
224+
// suffix here for backwards compatibility with older textual interfaces.
225+
func dropQualifierSuffix(_ type: TypeSyntax) -> TypeSyntax {
226+
guard let identifier = type.as(IdentifierTypeSyntax.self) else { return type }
227+
let typename = identifier.name.text
228+
if typename.hasSuffix("_const") {
229+
return TypeSyntax(identifier.with(\.name, TokenSyntax.identifier(
230+
String(typename.dropLast("_const".count))
231+
)))
232+
}
233+
return type
234+
}
235+
207236
// The generated type names for template instantiations sometimes contain
208-
// a `_const` suffix for diambiguation purposes. We need to remove that.
209-
func dropConstSuffix(_ typeName: String) -> String {
210-
if typeName.hasSuffix("_const") {
211-
return String(typeName.dropLast("_const".count))
237+
// encoded qualifiers for disambiguation purposes. We need to remove those.
238+
func dropCxxQualifiers(_ type: TypeSyntax) -> TypeSyntax {
239+
if let attributed = type.as(AttributedTypeSyntax.self) {
240+
return dropCxxQualifiers(attributed.baseType)
212241
}
213-
return typeName
242+
return dropQualifierSuffix(dropQualifierGenerics(type))
214243
}
215244

216245
func getPointerMutability(text: String) -> Mutability? {
@@ -405,7 +434,7 @@ struct CxxSpanThunkBuilder: ParamPointerBoundsThunkBuilder {
405434
let genericArg = TypeSyntax(parsedDesugaredType.as(IdentifierTypeSyntax.self)!
406435
.genericArgumentClause!.arguments.first!.argument)!
407436
types[index] = replaceBaseType(param.type,
408-
TypeSyntax("Span<\(raw: dropConstSuffix(try getTypeName(genericArg).text))>"))
437+
TypeSyntax("Span<\(raw: dropCxxQualifiers(genericArg)))>"))
409438
return try base.buildFunctionSignature(types, returnType)
410439
}
411440

@@ -440,7 +469,7 @@ struct CxxSpanReturnThunkBuilder: BoundsCheckedThunkBuilder {
440469
let genericArg = TypeSyntax(parsedDesugaredType.as(IdentifierTypeSyntax.self)!
441470
.genericArgumentClause!.arguments.first!.argument)!
442471
let newType = replaceBaseType(signature.returnClause!.type,
443-
TypeSyntax("Span<\(raw: dropConstSuffix(try getTypeName(genericArg).text))>"))
472+
TypeSyntax("Span<\(raw: dropCxxQualifiers(genericArg)))>"))
444473
return try base.buildFunctionSignature(argTypes, newType)
445474
}
446475

0 commit comments

Comments
 (0)