Skip to content

Commit 9fa6b2b

Browse files
committed
macros now require trailing parentheses to resolve
1 parent 24f415b commit 9fa6b2b

7 files changed

+82
-12
lines changed

Sources/LinkResolution/UCF.Predicate.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ extension UCF
55
struct Predicate
66
{
77
let suffix:Selector.Suffix?
8-
let hasEmptyTrailingParentheses:Bool
8+
let seal:Selector.Seal?
99

10-
init(suffix:Selector.Suffix?, hasEmptyTrailingParentheses:Bool)
10+
init(suffix:Selector.Suffix?, seal:Selector.Seal?)
1111
{
1212
self.suffix = suffix
13-
self.hasEmptyTrailingParentheses = hasEmptyTrailingParentheses
13+
self.seal = seal
1414
}
1515
}
1616
}

Sources/LinkResolution/UCF.ResolvableOverload.swift

+24-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,30 @@ extension UCF.ResolvableOverload
1717
{
1818
static func ~= (predicate:UCF.Predicate, self:Self) -> Bool
1919
{
20-
if predicate.hasEmptyTrailingParentheses
20+
if case nil = predicate.seal
21+
{
22+
// Macros are currently the only kind of declaration that *must* be spelled with
23+
// trailing parentheses.
24+
switch self.phylum
25+
{
26+
case .actor: break
27+
case .associatedtype: break
28+
case .case: break
29+
case .class: break
30+
case .deinitializer: break
31+
case .enum: break
32+
case .func: break
33+
case .initializer: break
34+
case .macro: return false
35+
case .operator: break
36+
case .protocol: break
37+
case .struct: break
38+
case .subscript: break
39+
case .typealias: break
40+
case .var: break
41+
}
42+
}
43+
else
2144
{
2245
switch self.phylum
2346
{

Sources/LinkResolution/UCF.Selector (ext).swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ extension UCF.Selector
55
{
66
var predicate:UCF.Predicate
77
{
8-
.init(suffix: self.suffix,
9-
hasEmptyTrailingParentheses: self.path.hasEmptyTrailingParentheses)
8+
.init(suffix: self.suffix, seal: self.path.seal)
109
}
1110
}
1211
// TODO: this does not belong in this module

Sources/UCF/Codelinks/UCF.Selector.Path.swift

+11-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,25 @@ extension UCF.Selector
1010
public
1111
var fold:Int
1212
public
13-
var hasEmptyTrailingParentheses:Bool
13+
var seal:Seal?
1414

1515
@inlinable public
16-
init(components:[String] = [], fold:Int = 0, hasEmptyTrailingParentheses:Bool = false)
16+
init(components:[String] = [], fold:Int = 0, seal:Seal? = nil)
1717
{
1818
self.components = components
1919
self.fold = fold
20-
self.hasEmptyTrailingParentheses = hasEmptyTrailingParentheses
20+
self.seal = seal
2121
}
2222
}
2323
}
2424
extension UCF.Selector.Path
2525
{
26+
@inlinable public
27+
var hasTrailingParentheses:Bool
28+
{
29+
self.seal != nil
30+
}
31+
2632
@inlinable public
2733
var visible:ArraySlice<String>
2834
{
@@ -117,10 +123,11 @@ extension UCF.Selector.Path
117123
case k?:
118124
// Special case: ignore empty trailing parentheses
119125
self.components.append(String.init(string[i ..< j]))
120-
self.hasEmptyTrailingParentheses = true
126+
self.seal = .trailingParentheses
121127
return string.index(after: k)
122128

123129
case let k?:
130+
self.seal = .trailingArguments
124131
j = string.index(after: k)
125132
}
126133
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extension UCF.Selector
2+
{
3+
@frozen public
4+
enum Seal:Equatable, Hashable, Sendable
5+
{
6+
case trailingParentheses
7+
case trailingArguments
8+
}
9+
}

Sources/UCF/Codelinks/UCF.Selector.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extension UCF.Selector:CustomStringConvertible
4545
string += component
4646
}
4747

48-
if self.path.hasEmptyTrailingParentheses
48+
if case .trailingParentheses? = self.path.seal
4949
{
5050
string += "()"
5151
}

Sources/UCFTests/Main.ParseCodelink.swift

+33-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extension Main.ParseCodelink:TestBattery
2121
tests.expect(link.base ==? .relative)
2222
tests.expect(link.path.components ..? ["Unicode", "Scalar", "value"])
2323
tests.expect(link.path.visible ..? ["Unicode", "Scalar", "value"])
24+
tests.expect(false: link.path.hasTrailingParentheses)
2425
tests.expect(nil: link.suffix)
2526
}
2627
if let tests:TestGroup = tests / "SlashDot",
@@ -29,6 +30,7 @@ extension Main.ParseCodelink:TestBattery
2930
tests.expect(link.base ==? .relative)
3031
tests.expect(link.path.components ..? ["Unicode", "Scalar", "value"])
3132
tests.expect(link.path.visible ..? ["Scalar", "value"])
33+
tests.expect(false: link.path.hasTrailingParentheses)
3234
tests.expect(nil: link.suffix)
3335
}
3436
if let tests:TestGroup = tests / "DotSlash",
@@ -37,6 +39,7 @@ extension Main.ParseCodelink:TestBattery
3739
tests.expect(link.base ==? .relative)
3840
tests.expect(link.path.components ..? ["Unicode", "Scalar", "value"])
3941
tests.expect(link.path.visible ..? ["value"])
42+
tests.expect(false: link.path.hasTrailingParentheses)
4043
tests.expect(nil: link.suffix)
4144
}
4245
if let tests:TestGroup = tests / "SlashSlash",
@@ -45,6 +48,7 @@ extension Main.ParseCodelink:TestBattery
4548
tests.expect(link.base ==? .relative)
4649
tests.expect(link.path.components ..? ["Unicode", "Scalar", "value"])
4750
tests.expect(link.path.visible ..? ["value"])
51+
tests.expect(false: link.path.hasTrailingParentheses)
4852
tests.expect(nil: link.suffix)
4953
}
5054
if let tests:TestGroup = tests / "SingleCharacter",
@@ -53,6 +57,7 @@ extension Main.ParseCodelink:TestBattery
5357
tests.expect(link.base ==? .relative)
5458
tests.expect(link.path.components ..? ["x"])
5559
tests.expect(link.path.visible ..? ["x"])
60+
tests.expect(false: link.path.hasTrailingParentheses)
5661
tests.expect(nil: link.suffix)
5762
}
5863

@@ -62,6 +67,7 @@ extension Main.ParseCodelink:TestBattery
6267
tests.expect(link.base ==? .relative)
6368
tests.expect(link.path.components ..? ["Real", "..(_:_:)"])
6469
tests.expect(link.path.visible ..? ["Real", "..(_:_:)"])
70+
tests.expect(true: link.path.hasTrailingParentheses)
6571
tests.expect(nil: link.suffix)
6672
}
6773
if let tests:TestGroup = tests / "Real" / "2",
@@ -70,6 +76,7 @@ extension Main.ParseCodelink:TestBattery
7076
tests.expect(link.base ==? .relative)
7177
tests.expect(link.path.components ..? ["Real", "..(_:_:)"])
7278
tests.expect(link.path.visible ..? ["..(_:_:)"])
79+
tests.expect(true: link.path.hasTrailingParentheses)
7380
tests.expect(nil: link.suffix)
7481
}
7582
if let tests:TestGroup = tests / "Real" / "3",
@@ -78,6 +85,7 @@ extension Main.ParseCodelink:TestBattery
7885
tests.expect(link.base ==? .relative)
7986
tests.expect(link.path.components ..? ["Real", "...(_:_:)"])
8087
tests.expect(link.path.visible ..? ["Real", "...(_:_:)"])
88+
tests.expect(true: link.path.hasTrailingParentheses)
8189
tests.expect(nil: link.suffix)
8290
}
8391
if let tests:TestGroup = tests / "Real" / "4",
@@ -86,6 +94,7 @@ extension Main.ParseCodelink:TestBattery
8694
tests.expect(link.base ==? .relative)
8795
tests.expect(link.path.components ..? ["Real", "...(_:_:)"])
8896
tests.expect(link.path.visible ..? ["...(_:_:)"])
97+
tests.expect(true: link.path.hasTrailingParentheses)
8998
tests.expect(nil: link.suffix)
9099
}
91100
if let tests:TestGroup = tests / "Real" / "5",
@@ -94,6 +103,7 @@ extension Main.ParseCodelink:TestBattery
94103
tests.expect(link.base ==? .relative)
95104
tests.expect(link.path.components ..? ["Real", "/(_:_:)"])
96105
tests.expect(link.path.visible ..? ["Real", "/(_:_:)"])
106+
tests.expect(true: link.path.hasTrailingParentheses)
97107
tests.expect(nil: link.suffix)
98108
}
99109
if let tests:TestGroup = tests / "Real" / "6",
@@ -102,6 +112,7 @@ extension Main.ParseCodelink:TestBattery
102112
tests.expect(link.base ==? .relative)
103113
tests.expect(link.path.components ..? ["Real", "/(_:_:)"])
104114
tests.expect(link.path.visible ..? ["/(_:_:)"])
115+
tests.expect(true: link.path.hasTrailingParentheses)
105116
tests.expect(nil: link.suffix)
106117
}
107118
if let tests:TestGroup = tests / "Real" / "7",
@@ -110,6 +121,7 @@ extension Main.ParseCodelink:TestBattery
110121
tests.expect(link.base ==? .relative)
111122
tests.expect(link.path.components ..? ["Real", "./.(_:_:)"])
112123
tests.expect(link.path.visible ..? ["Real", "./.(_:_:)"])
124+
tests.expect(true: link.path.hasTrailingParentheses)
113125
tests.expect(nil: link.suffix)
114126
}
115127
if let tests:TestGroup = tests / "Real" / "8",
@@ -118,6 +130,7 @@ extension Main.ParseCodelink:TestBattery
118130
tests.expect(link.base ==? .relative)
119131
tests.expect(link.path.components ..? ["Real", "./.(_:_:)"])
120132
tests.expect(link.path.visible ..? ["./.(_:_:)"])
133+
tests.expect(true: link.path.hasTrailingParentheses)
121134
tests.expect(nil: link.suffix)
122135
}
123136
if let tests:TestGroup = tests / "EmptyTrailingParentheses",
@@ -126,7 +139,7 @@ extension Main.ParseCodelink:TestBattery
126139
tests.expect(link.base ==? .relative)
127140
tests.expect(link.path.components ..? ["Real", "init"])
128141
tests.expect(link.path.visible ..? ["Real", "init"])
129-
tests.expect(true: link.path.hasEmptyTrailingParentheses)
142+
tests.expect(true: link.path.hasTrailingParentheses)
130143
tests.expect(nil: link.suffix)
131144
}
132145
if let tests:TestGroup = tests / "EmptyTrailingComponent",
@@ -135,6 +148,7 @@ extension Main.ParseCodelink:TestBattery
135148
tests.expect(link.base ==? .relative)
136149
tests.expect(link.path.components ..? ["Real", "init"])
137150
tests.expect(link.path.visible ..? ["Real", "init"])
151+
tests.expect(false: link.path.hasTrailingParentheses)
138152
tests.expect(nil: link.suffix)
139153
}
140154
if let tests:TestGroup = tests / "DivisionOperator",
@@ -143,6 +157,7 @@ extension Main.ParseCodelink:TestBattery
143157
tests.expect(link.base ==? .relative)
144158
tests.expect(link.path.components ..? ["/(_:_:)"])
145159
tests.expect(link.path.visible ..? ["/(_:_:)"])
160+
tests.expect(true: link.path.hasTrailingParentheses)
146161
tests.expect(nil: link.suffix)
147162
}
148163
if let tests:TestGroup = tests / "CustomOperator",
@@ -151,6 +166,7 @@ extension Main.ParseCodelink:TestBattery
151166
tests.expect(link.base ==? .relative)
152167
tests.expect(link.path.components ..? ["/-/(_:_:)"])
153168
tests.expect(link.path.visible ..? ["/-/(_:_:)"])
169+
tests.expect(true: link.path.hasTrailingParentheses)
154170
tests.expect(nil: link.suffix)
155171
}
156172
if let tests:TestGroup = tests / "ClosedRangeOperator",
@@ -159,6 +175,7 @@ extension Main.ParseCodelink:TestBattery
159175
tests.expect(link.base ==? .relative)
160176
tests.expect(link.path.components ..? ["...(_:_:)"])
161177
tests.expect(link.path.visible ..? ["...(_:_:)"])
178+
tests.expect(true: link.path.hasTrailingParentheses)
162179
tests.expect(nil: link.suffix)
163180
}
164181
}
@@ -169,6 +186,7 @@ extension Main.ParseCodelink:TestBattery
169186
{
170187
tests.expect(link.base ==? .relative)
171188
tests.expect(link.path.components ..? ["Fake"])
189+
tests.expect(false: link.path.hasTrailingParentheses)
172190
tests.expect(link.suffix ==? .filter(.enum))
173191
}
174192
if let tests:TestGroup = tests / "Fake" / "UncannyHash",
@@ -178,13 +196,15 @@ extension Main.ParseCodelink:TestBattery
178196

179197
tests.expect(link.base ==? .relative)
180198
tests.expect(link.path.components ..? ["Fake"])
199+
tests.expect(false: link.path.hasTrailingParentheses)
181200
tests.expect(link.suffix ==? .hash(hash))
182201
}
183202
if let tests:TestGroup = tests / "Fake" / "ClassVar",
184203
let link:UCF.Selector = tests.roundtrip("Fake.max [class var]")
185204
{
186205
tests.expect(link.base ==? .relative)
187206
tests.expect(link.path.components ..? ["Fake", "max"])
207+
tests.expect(false: link.path.hasTrailingParentheses)
188208
tests.expect(link.suffix ==? .filter(.class_var))
189209
}
190210
}
@@ -196,6 +216,7 @@ extension Main.ParseCodelink:TestBattery
196216
tests.expect(link.base ==? .relative)
197217
tests.expect(link.path.components ..? ["Sloth", "Color"])
198218
tests.expect(link.path.visible ..? ["Color"])
219+
tests.expect(false: link.path.hasTrailingParentheses)
199220
tests.expect(nil: link.suffix)
200221
}
201222
if let tests:TestGroup = tests / "Filter",
@@ -204,6 +225,7 @@ extension Main.ParseCodelink:TestBattery
204225
tests.expect(link.base ==? .relative)
205226
tests.expect(link.path.components ..? ["Sloth", "Color"])
206227
tests.expect(link.path.visible ..? ["Color"])
228+
tests.expect(false: link.path.hasTrailingParentheses)
207229
tests.expect(link.suffix ==? .filter(.enum))
208230
}
209231
if let tests:TestGroup = tests / "FilterInterior",
@@ -212,6 +234,7 @@ extension Main.ParseCodelink:TestBattery
212234
tests.expect(link.base ==? .relative)
213235
tests.expect(link.path.components ..? ["Sloth", "Color"])
214236
tests.expect(link.path.visible ..? ["Color"])
237+
tests.expect(false: link.path.hasTrailingParentheses)
215238
tests.expect(nil: link.suffix)
216239
}
217240
if let tests:TestGroup = tests / "FilterLegacy",
@@ -220,6 +243,7 @@ extension Main.ParseCodelink:TestBattery
220243
tests.expect(link.base ==? .relative)
221244
tests.expect(link.path.components ..? ["Sloth", "Color"])
222245
tests.expect(link.path.visible ..? ["Color"])
246+
tests.expect(false: link.path.hasTrailingParentheses)
223247
tests.expect(link.suffix ==? .legacy(.class, nil))
224248
}
225249
if let tests:TestGroup = tests / "FilterAndHash",
@@ -230,6 +254,7 @@ extension Main.ParseCodelink:TestBattery
230254
tests.expect(link.base ==? .relative)
231255
tests.expect(link.path.components ..? ["Sloth", "Color"])
232256
tests.expect(link.path.visible ..? ["Color"])
257+
tests.expect(false: link.path.hasTrailingParentheses)
233258
tests.expect(link.suffix ==? .legacy(.struct, hash))
234259
}
235260
if let tests:TestGroup = tests / "Hash",
@@ -240,6 +265,7 @@ extension Main.ParseCodelink:TestBattery
240265
tests.expect(link.base ==? .relative)
241266
tests.expect(link.path.components ..? ["Sloth", "update(_:)"])
242267
tests.expect(link.path.visible ..? ["update(_:)"])
268+
tests.expect(true: link.path.hasTrailingParentheses)
243269
tests.expect(link.suffix ==? .hash(hash))
244270
}
245271
if let tests:TestGroup = tests / "Hash" / "Minus",
@@ -250,6 +276,7 @@ extension Main.ParseCodelink:TestBattery
250276
tests.expect(link.base ==? .relative)
251277
tests.expect(link.path.components ..? ["Sloth", "-(_:)"])
252278
tests.expect(link.path.visible ..? ["-(_:)"])
279+
tests.expect(true: link.path.hasTrailingParentheses)
253280
tests.expect(link.suffix ==? .hash(hash))
254281
}
255282
if let tests:TestGroup = tests / "Hash" / "Slinging" / "Slasher",
@@ -260,6 +287,7 @@ extension Main.ParseCodelink:TestBattery
260287
tests.expect(link.base ==? .relative)
261288
tests.expect(link.path.components ..? ["Sloth", "/(_:)"])
262289
tests.expect(link.path.visible ..? ["/(_:)"])
290+
tests.expect(true: link.path.hasTrailingParentheses)
263291
tests.expect(link.suffix ==? .hash(hash))
264292
}
265293
}
@@ -271,6 +299,7 @@ extension Main.ParseCodelink:TestBattery
271299
tests.expect(link.base ==? .qualified)
272300
tests.expect(link.path.components ..? ["Swift"])
273301
tests.expect(link.path.visible ..? ["Swift"])
302+
tests.expect(false: link.path.hasTrailingParentheses)
274303
tests.expect(nil: link.suffix)
275304
}
276305
if let tests:TestGroup = tests / "Hidden",
@@ -279,6 +308,7 @@ extension Main.ParseCodelink:TestBattery
279308
tests.expect(link.base ==? .qualified)
280309
tests.expect(link.path.components ..? ["Swift", "Int"])
281310
tests.expect(link.path.visible ..? ["Int"])
311+
tests.expect(false: link.path.hasTrailingParentheses)
282312
tests.expect(nil: link.suffix)
283313
}
284314
if let tests:TestGroup = tests / "Visible",
@@ -287,6 +317,7 @@ extension Main.ParseCodelink:TestBattery
287317
tests.expect(link.base ==? .qualified)
288318
tests.expect(link.path.components ..? ["Swift", "Int"])
289319
tests.expect(link.path.visible ..? ["Swift", "Int"])
320+
tests.expect(false: link.path.hasTrailingParentheses)
290321
tests.expect(nil: link.suffix)
291322
}
292323
if let tests:TestGroup = tests / "EmptyTrailingComponent",
@@ -295,6 +326,7 @@ extension Main.ParseCodelink:TestBattery
295326
tests.expect(link.base ==? .qualified)
296327
tests.expect(link.path.components ..? ["Swift", "Int"])
297328
tests.expect(link.path.visible ..? ["Swift", "Int"])
329+
tests.expect(false: link.path.hasTrailingParentheses)
298330
tests.expect(nil: link.suffix)
299331
}
300332
}

0 commit comments

Comments
 (0)