Skip to content

Commit d668cfb

Browse files
committed
add util properties for TypeSyntaxProtocol
1 parent b7ad775 commit d668cfb

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

lib/Macros/Sources/SwiftMacros/PointerBoundsMacro.swift

+47-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ struct CountedOrSizedPointerThunkBuilder: PointerBoundsThunkBuilder {
315315
}
316316

317317
func castIntToTargetType(expr: ExprSyntax, type: TypeSyntax) -> ExprSyntax {
318-
if type.isSwiftInt {
318+
if type.canRepresentBasicType(type: Int.self) {
319319
return expr
320320
}
321321
return ExprSyntax("\(type)(exactly: \(expr))!")
@@ -717,3 +717,49 @@ public struct PointerBoundsMacro: PeerMacro {
717717
}
718718
}
719719
}
720+
721+
// MARK: syntax utils
722+
extension TypeSyntaxProtocol {
723+
public var isSwiftCoreModule: Bool {
724+
guard let identifierType = self.as(IdentifierTypeSyntax.self) else {
725+
return false
726+
}
727+
return identifierType.name.text == "Swift"
728+
}
729+
730+
/// Check if this syntax could resolve to the type passed. Only supports types where the canonical type
731+
/// can be named using only IdentifierTypeSyntax and MemberTypeSyntax. A non-exhaustive list of unsupported
732+
/// types includes:
733+
/// * array types
734+
/// * function types
735+
/// * optional types
736+
/// * tuple types (including Void!)
737+
/// The type syntax is allowed to use any level of qualified name for the type, e.g. Swift.Int.self
738+
/// will match against both "Swift.Int" and "Int".
739+
///
740+
/// - Parameter type: Type to check against. NB: if passing a type alias, the canonical type will be used.
741+
/// - Returns: true if `self` spells out some suffix of the fully qualified name of `type`, otherwise false
742+
public func canRepresentBasicType(type: Any.Type) -> Bool {
743+
let qualifiedTypeName = String(reflecting: type)
744+
var typeNames = qualifiedTypeName.split(separator: ".")
745+
var currType: TypeSyntaxProtocol = self
746+
747+
while !typeNames.isEmpty {
748+
let typeName = typeNames.popLast()!
749+
if let identifierType = currType.as(IdentifierTypeSyntax.self) {
750+
// It doesn't matter whether this is the final element of typeNames, because we don't know
751+
// surrounding context - the Foo.Bar.Baz type can be referred to as `Baz` inside Foo.Bar
752+
return identifierType.name.text == typeName
753+
} else if let memberType = currType.as(MemberTypeSyntax.self) {
754+
if memberType.name.text != typeName {
755+
return false
756+
}
757+
currType = memberType.baseType
758+
} else {
759+
return false
760+
}
761+
}
762+
763+
return false
764+
}
765+
}

0 commit comments

Comments
 (0)