ibex10
October 12, 2023, 12:40am
1
I have hard-coded the protocol names in the print statements below.
protocol Foo {
}
extension Foo {
func go () {
print (type (of:self), "Foo", #function)
}
}
protocol Bar: Foo {
}
extension Bar {
func go() {
print (type (of:self), "Bar", #function)
func _super (self:some Foo) {
print (type (of:self), "Bar", #function)
self.go()
}
_super(self: self)
}
}
struct Clever: Bar {
}
Is there a way to get the name of a protocol, analogous to #function
or type (of:self)
, so that I don't have to hard-code them?
1 Like
Kyle-Ye
(Kyle)
October 12, 2023, 7:46am
2
You can use Swift Runtime to do so
// Module A
protocol P {
func hello()
}
@_silgen_name("swift_getTypeName")
@inline(__always)
private func _getTypeName(_ type: Any.Type, qualified: Bool)
-> (UnsafePointer<UInt8>, Int)
print(String(cString: _getTypeName(P.self, qualified: true).0))
// Print A.P
print(String(cString: _getTypeName(P.self, qualified: false).0))
// Print P
Here is my Library's usage https://github.com/Kyle-Ye/OpenSwiftUI/blob/f02d16bef286f8698371d4bd71f308f6e67a6a73/Sources/OpenSwiftUI/Other/ProtocolDescriptor.swift#L1-L8
Update:
Swift Standard Library actually already shipped it as an underscore API.
You can also just use it directly
import Swift // Implicitly added for all Swift file
print(_typeName(P.self)) // A.P
print(_typeName(P.self, qualified: false)) // P
Relative Code is here
@_silgen_name("swift_getTypeName")
public func _getTypeName(_ type: Any.Type, qualified: Bool)
-> (UnsafePointer<UInt8>, Int)
/// Returns the demangled qualified name of a metatype.
@_semantics("typeName")
@_unavailableInEmbedded
public // @testable
func _typeName(_ type: Any.Type, qualified: Bool = true) -> String {
let (stringPtr, count) = _getTypeName(type, qualified: qualified)
return String._fromUTF8Repairing(
UnsafeBufferPointer(start: stringPtr, count: count)).0
}
1 Like
ibex10
October 12, 2023, 10:52am
3
Thank you, @Kyle-Ye , but the protocol name is still hard-coded in the examples.
I am beginning to think that this, getting the name of a protocol in its extensions, is currently not possible. It would be really nice if we had something like #protocol
analogous to #function
.
1 Like
xwu
(Xiaodi Wu)
October 12, 2023, 2:51pm
4
Seems like a perfect fit for a user-defined expression macro!
ibex10
October 13, 2023, 5:16am
5
The standard library contains the following set of macros:
macro function<T>() -> T
Produces the name of the declaration in which it appears.
macro file<T>() -> T
Produces the path to the file in which it appears.
macro fileID<T>() -> T
Produces a unique identifier for the source file in which the macro appears.
macro filePath<T>() -> T
Produces the complete path to the file in which the macro appears.
macro line<T>() -> T
Produces the line number on which it appears.
macro column<T>() -> T
Produces the column number in which the macro begins.
I wish it had one more:
macro type<T>() -> T
Produces the name of the type in which the macro appears or the name of the protocol in an extension of which the macro appears.
I wonder why this particular one is missing.
1 Like