Skip to content

Commit b55c31c

Browse files
committed
add logic to compute the function signature ‘autograph’
1 parent c4c4498 commit b55c31c

13 files changed

+323
-35
lines changed

Sources/MarkdownPluginSwift/Signatures/Signature.Expanded (ext).swift

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ extension Signature.Expanded
55
{
66
@inlinable public
77
init(_ fragments:__shared some Collection<Signature<Scalar>.Fragment>,
8-
landmarks:inout Signature.Landmarks)
8+
sugarArray:Scalar,
9+
sugarDictionary:Scalar,
10+
sugarOptional:Scalar,
11+
landmarks:inout SignatureLandmarks)
912
{
1013
var utf8:[UInt8] = []
1114
utf8.reserveCapacity(fragments.reduce(0) { $0 + $1.spelling.utf8.count })
@@ -26,7 +29,19 @@ extension Signature.Expanded
2629
}
2730
}
2831

32+
let sugarMap:SignatureSyntax.SugarMap = linkTargets.reduce(into: .init())
33+
{
34+
switch $1.value
35+
{
36+
case sugarArray: $0.arrays.insert($1.key)
37+
case sugarDictionary: $0.dictionaries.insert($1.key)
38+
case sugarOptional: $0.optionals.insert($1.key)
39+
default: break
40+
}
41+
}
42+
2943
self.init(utf8: utf8,
44+
sugarMap: sugarMap,
3045
linkBoundaries: linkBoundaries,
3146
linkTargets: &linkTargets,
3247
landmarks: &landmarks)
@@ -51,14 +66,14 @@ extension Signature.Expanded
5166
init(_ string:String,
5267
linkBoundaries:borrowing [Int] = [])
5368
{
54-
var ignored:Signature.Landmarks = .init()
69+
var ignored:SignatureLandmarks = .init()
5570
self.init(string, linkBoundaries: linkBoundaries, landmarks: &ignored)
5671
}
5772

5873
@inlinable @_spi(testable) public
5974
init(_ string:String,
6075
linkBoundaries:borrowing [Int] = [],
61-
landmarks:inout Signature.Landmarks)
76+
landmarks:inout SignatureLandmarks)
6277
{
6378
var empty:[Int: Scalar] = [:]
6479
self.init(utf8: [UInt8].init(string.utf8),
@@ -69,11 +84,15 @@ extension Signature.Expanded
6984

7085
@inlinable
7186
init(utf8:[UInt8],
87+
sugarMap:SignatureSyntax.SugarMap = .init(),
7288
linkBoundaries:borrowing [Int],
7389
linkTargets:inout [Int: Scalar],
74-
landmarks:inout Signature.Landmarks)
90+
landmarks:inout SignatureLandmarks)
7591
{
76-
let signature:SignatureSyntax = utf8.withUnsafeBufferPointer { .expanded($0) }
92+
let signature:SignatureSyntax = utf8.withUnsafeBufferPointer
93+
{
94+
.expanded($0, sugaring: sugarMap, landmarks: &landmarks)
95+
}
7796
var references:[Scalar: Int] = [:]
7897
var referents:[Scalar] = []
7998

Sources/MarkdownPluginSwift/Signatures/Signature.Landmarks.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

Sources/MarkdownPluginSwift/Signatures/Signature.Landmarks.InterestingKeywords.swift renamed to Sources/MarkdownPluginSwift/Signatures/SignatureLandmarks.InterestingKeywords.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Signatures
22

3-
extension Signature.Landmarks
3+
extension SignatureLandmarks
44
{
55
@frozen public
66
struct InterestingKeywords
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Signatures
2+
3+
@frozen public
4+
struct SignatureLandmarks
5+
{
6+
public
7+
var keywords:InterestingKeywords
8+
public
9+
var inputs:[String]
10+
public
11+
var output:[String]
12+
13+
@inlinable public
14+
init()
15+
{
16+
self.keywords = .init()
17+
self.inputs = []
18+
self.output = []
19+
}
20+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import SwiftSyntax
2+
3+
extension SignatureSyntax
4+
{
5+
/// `Autographer`’s job is to produce the “autograph” of a type, which is an even more
6+
/// abridged form of the type’s signature. It is used for function signature disambiguation.
7+
struct Autographer
8+
{
9+
private
10+
let sugarMap:SugarMap
11+
private(set)
12+
var autograph:String
13+
14+
init(sugaring sugarMap:SugarMap)
15+
{
16+
self.sugarMap = sugarMap
17+
self.autograph = ""
18+
}
19+
}
20+
}
21+
extension SignatureSyntax.Autographer
22+
{
23+
mutating
24+
func encode(type:TypeSyntax)
25+
{
26+
if let type:AttributedTypeSyntax = type.as(AttributedTypeSyntax.self)
27+
{
28+
self.encode(type: type.baseType)
29+
}
30+
else if
31+
let type:IdentifierTypeSyntax = type.as(IdentifierTypeSyntax.self)
32+
{
33+
self.encode(type: type.name, generics: type.genericArgumentClause?.arguments)
34+
}
35+
else if
36+
let type:MemberTypeSyntax = type.as(MemberTypeSyntax.self)
37+
{
38+
self.encode(type: type.baseType)
39+
self.autograph.append(".")
40+
self.encode(type: type.name, generics: type.genericArgumentClause?.arguments)
41+
}
42+
else if
43+
let type:ArrayTypeSyntax = type.as(ArrayTypeSyntax.self)
44+
{
45+
self.autograph.append("[")
46+
self.encode(type: type.element)
47+
self.autograph.append("]")
48+
}
49+
else if
50+
let type:DictionaryTypeSyntax = type.as(DictionaryTypeSyntax.self)
51+
{
52+
self.autograph.append("[")
53+
self.encode(type: type.key)
54+
self.autograph.append(":")
55+
self.encode(type: type.value)
56+
self.autograph.append("]")
57+
}
58+
else if
59+
let type:ImplicitlyUnwrappedOptionalTypeSyntax = type.as(
60+
ImplicitlyUnwrappedOptionalTypeSyntax.self)
61+
{
62+
self.encode(type: type.wrappedType)
63+
self.autograph.append("!")
64+
}
65+
else if
66+
let type:OptionalTypeSyntax = type.as(OptionalTypeSyntax.self)
67+
{
68+
self.encode(type: type.wrappedType)
69+
self.autograph.append("?")
70+
}
71+
else if
72+
let type:MetatypeTypeSyntax = type.as(MetatypeTypeSyntax.self)
73+
{
74+
self.encode(type: type.baseType)
75+
self.autograph.append(".Type")
76+
}
77+
else if
78+
let type:TupleTypeSyntax = type.as(TupleTypeSyntax.self)
79+
{
80+
self.autograph.append("(")
81+
82+
var first:Bool = true
83+
for element:TupleTypeElementSyntax in type.elements
84+
{
85+
if first
86+
{
87+
first = false
88+
}
89+
else
90+
{
91+
self.autograph.append(",")
92+
}
93+
self.encode(type: element.type)
94+
}
95+
96+
self.autograph.append(")")
97+
}
98+
else if
99+
let function:FunctionTypeSyntax = type.as(FunctionTypeSyntax.self)
100+
{
101+
self.autograph.append("(")
102+
103+
var first:Bool = true
104+
for parameter:TupleTypeElementSyntax in function.parameters
105+
{
106+
if first
107+
{
108+
first = false
109+
}
110+
else
111+
{
112+
self.autograph.append(",")
113+
}
114+
115+
self.encode(type: parameter.type)
116+
}
117+
118+
self.autograph.append(")->")
119+
self.encode(type: function.returnClause.type)
120+
}
121+
else
122+
{
123+
self.autograph.append("_")
124+
}
125+
}
126+
127+
private mutating
128+
func encode(type name:TokenSyntax, generics:GenericArgumentListSyntax?)
129+
{
130+
if let generics:GenericArgumentListSyntax
131+
{
132+
let generics:[TypeSyntax] = generics.map(\.argument)
133+
let position:Int = name.positionAfterSkippingLeadingTrivia.utf8Offset
134+
135+
if self.sugarMap.arrays.contains(position), generics.count == 1
136+
{
137+
self.autograph.append("[")
138+
self.encode(type: generics[0])
139+
self.autograph.append("]")
140+
return
141+
}
142+
if self.sugarMap.dictionaries.contains(position), generics.count == 2
143+
{
144+
self.autograph.append("[")
145+
self.encode(type: generics[0])
146+
self.autograph.append(":")
147+
self.encode(type: generics[1])
148+
self.autograph.append("]")
149+
return
150+
}
151+
if self.sugarMap.optionals.contains(position), generics.count == 1
152+
{
153+
self.encode(type: generics[0])
154+
self.autograph.append("?")
155+
return
156+
}
157+
}
158+
else if name.text == "`Self`"
159+
{
160+
self.autograph.append("Self")
161+
return
162+
}
163+
164+
self.autograph.append(name.text)
165+
}
166+
}

Sources/MarkdownPluginSwift/Signatures/SignatureSyntax.Builder.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,17 @@ extension SignatureSyntax.Builder<SignatureSyntax.ExpandedVisitor>
103103
}
104104
}
105105
}
106+
// Subscript inputs and outputs are “shallow”
106107
else if
107108
let clause:FunctionParameterClauseSyntax =
108109
region.as(FunctionParameterClauseSyntax.self)
109110
{
110-
self.register(parameters: clause, type: .func)
111+
self.register(parameters: clause, type: .subscript)
112+
}
113+
else if
114+
let clause:ReturnClauseSyntax = region.as(ReturnClauseSyntax.self)
115+
{
116+
self.register(returns: clause)
111117
}
112118
else
113119
{

Sources/MarkdownPluginSwift/Signatures/SignatureSyntax.ExpandedVisitor.swift

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,23 @@ import SwiftSyntax
22

33
extension SignatureSyntax
44
{
5+
@frozen @usableFromInline
56
struct ExpandedVisitor
67
{
8+
let sugarMap:SugarMap
9+
10+
private(set)
11+
var inputs:[String]
12+
private(set)
13+
var output:[String]
14+
15+
@usableFromInline
16+
init(sugaring sugarMap:SugarMap)
17+
{
18+
self.sugarMap = sugarMap
19+
self.inputs = []
20+
self.output = []
21+
}
722
}
823
}
924
extension SignatureSyntax.ExpandedVisitor:SignatureVisitor
@@ -13,11 +28,36 @@ extension SignatureSyntax.ExpandedVisitor:SignatureVisitor
1328
parameter:FunctionParameterSyntax,
1429
type _:SignatureParameterType) -> SignatureSyntax.ExpandedParameter
1530
{
16-
.init(syntax: parameter)
31+
var autographer:SignatureSyntax.Autographer = .init(sugaring: self.sugarMap)
32+
autographer.encode(type: parameter.type)
33+
inputs.append(autographer.autograph)
34+
return .init(syntax: parameter)
1735
}
1836

1937
mutating
2038
func register(returns:TypeSyntax)
2139
{
40+
guard
41+
let tuple:TupleTypeSyntax = returns.as(TupleTypeSyntax.self)
42+
else
43+
{
44+
self.register(output: returns)
45+
return
46+
}
47+
48+
for element:TupleTypeElementSyntax in tuple.elements
49+
{
50+
self.register(output: element.type)
51+
}
52+
}
53+
}
54+
extension SignatureSyntax.ExpandedVisitor
55+
{
56+
private mutating
57+
func register(output:TypeSyntax)
58+
{
59+
var autographer:SignatureSyntax.Autographer = .init(sugaring: self.sugarMap)
60+
autographer.encode(type: output)
61+
self.output.append(autographer.autograph)
2262
}
2363
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extension SignatureSyntax
2+
{
3+
@frozen @usableFromInline
4+
struct SugarMap
5+
{
6+
@usableFromInline
7+
var arrays:Set<Int>
8+
@usableFromInline
9+
var dictionaries:Set<Int>
10+
@usableFromInline
11+
var optionals:Set<Int>
12+
13+
@inlinable
14+
init()
15+
{
16+
self.arrays = []
17+
self.dictionaries = []
18+
self.optionals = []
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)