@@ -112,12 +112,11 @@ extension PathHierarchy {
112
112
// When descending through placeholder nodes, we trust that the known disambiguation
113
113
// that they were created with is necessary.
114
114
var knownDisambiguation = " "
115
- let ( kind , subtree ) = tree. storage. first!
116
- if kind != " _ " {
115
+ let element = tree. storage. first!
116
+ if let kind = element . kind {
117
117
knownDisambiguation += " - \( kind) "
118
118
}
119
- let hash = subtree. keys. first!
120
- if hash != " _ " {
119
+ if let hash = element. hash {
121
120
knownDisambiguation += " - \( hash) "
122
121
}
123
122
path = accumulatedPath + " / " + nameTransform( node. name) + knownDisambiguation
@@ -170,33 +169,45 @@ extension PathHierarchy {
170
169
}
171
170
172
171
extension PathHierarchy . DisambiguationContainer {
172
+
173
+ static func disambiguatedValues< E: Sequence > (
174
+ for elements: E ,
175
+ includeLanguage: Bool = false
176
+ ) -> [ ( value: PathHierarchy . Node , disambiguation: Disambiguation ) ] where E. Element == Element {
177
+ var collisions : [ ( value: PathHierarchy . Node , disambiguation: Disambiguation ) ] = [ ]
178
+
179
+ var remainingIDs = Set ( elements. map ( \. node. identifier) )
180
+
181
+ // Kind disambiguation is the most readable, so we start by checking if any element has a unique kind.
182
+ let groupedByKind = [ String? : [ Element] ] ( grouping: elements, by: \. kind)
183
+ for (kind, elements) in groupedByKind where elements. count == 1 && kind != nil {
184
+ let element = elements. first!
185
+ if includeLanguage, let symbol = element. node. symbol {
186
+ collisions. append ( ( value: element. node, disambiguation: . kind( " \( SourceLanguage ( id: symbol. identifier. interfaceLanguage) . linkDisambiguationID) . \( kind!) " ) ) )
187
+ } else {
188
+ collisions. append ( ( value: element. node, disambiguation: . kind( kind!) ) )
189
+ }
190
+ remainingIDs. remove ( element. node. identifier)
191
+ }
192
+ if remainingIDs. isEmpty {
193
+ return collisions
194
+ }
195
+
196
+ for element in elements where remainingIDs. contains ( element. node. identifier) {
197
+ collisions. append ( ( value: element. node, disambiguation: element. hash. map { . hash( $0) } ?? . none) )
198
+ }
199
+ return collisions
200
+ }
201
+
173
202
/// Returns all values paired with their disambiguation suffixes.
174
203
///
175
204
/// - Parameter includeLanguage: Whether or not the kind disambiguation information should include the language, for example: "swift".
176
205
func disambiguatedValues( includeLanguage: Bool = false ) -> [ ( value: PathHierarchy . Node , disambiguation: Disambiguation ) ] {
177
206
if storage. count == 1 {
178
- let tree = storage. values. first!
179
- if tree. count == 1 {
180
- return [ ( tree. values. first!, . none) ]
181
- }
207
+ return [ ( storage. first!. node, . none) ]
182
208
}
183
209
184
- var collisions : [ ( value: PathHierarchy . Node , disambiguation: Disambiguation ) ] = [ ]
185
- for (kind, kindTree) in storage {
186
- if kindTree. count == 1 {
187
- // No other match has this kind
188
- if includeLanguage, let symbol = kindTree. first!. value. symbol {
189
- collisions. append ( ( value: kindTree. first!. value, disambiguation: . kind( " \( SourceLanguage ( id: symbol. identifier. interfaceLanguage) . linkDisambiguationID) . \( kind) " ) ) )
190
- } else {
191
- collisions. append ( ( value: kindTree. first!. value, disambiguation: . kind( kind) ) )
192
- }
193
- continue
194
- }
195
- for (usr, value) in kindTree {
196
- collisions. append ( ( value: value, disambiguation: . hash( usr) ) )
197
- }
198
- }
199
- return collisions
210
+ return Self . disambiguatedValues ( for: storage, includeLanguage: includeLanguage)
200
211
}
201
212
202
213
/// Returns all values paired with their disambiguation suffixes without needing to disambiguate between two different versions of the same symbol.
@@ -205,31 +216,29 @@ extension PathHierarchy.DisambiguationContainer {
205
216
func disambiguatedValuesWithCollapsedUniqueSymbols( includeLanguage: Bool ) -> [ ( value: PathHierarchy . Node , disambiguation: Disambiguation ) ] {
206
217
typealias DisambiguationPair = ( String , String )
207
218
208
- var uniqueSymbolIDs = [ String: [ DisambiguationPair] ] ( )
209
- var nonSymbols = [ DisambiguationPair] ( )
210
- for (kind, kindTree) in storage {
211
- for (hash, value) in kindTree {
212
- guard let symbol = value. symbol else {
213
- nonSymbols. append ( ( kind, hash) )
214
- continue
215
- }
216
- if symbol. identifier. interfaceLanguage == " swift " {
217
- uniqueSymbolIDs [ symbol. identifier. precise, default: [ ] ] . insert ( ( kind, hash) , at: 0 )
218
- } else {
219
- uniqueSymbolIDs [ symbol. identifier. precise, default: [ ] ] . append ( ( kind, hash) )
220
- }
219
+ var uniqueSymbolIDs = [ String: [ Element] ] ( )
220
+ var nonSymbols = [ Element] ( )
221
+ for element in storage {
222
+ guard let symbol = element. node. symbol else {
223
+ nonSymbols. append ( element)
224
+ continue
225
+ }
226
+ if symbol. identifier. interfaceLanguage == " swift " {
227
+ uniqueSymbolIDs [ symbol. identifier. precise, default: [ ] ] . insert ( element, at: 0 )
228
+ } else {
229
+ uniqueSymbolIDs [ symbol. identifier. precise, default: [ ] ] . append ( element)
221
230
}
222
231
}
223
232
224
- var duplicateSymbols = [ String : ArraySlice < DisambiguationPair > ] ( )
233
+ var duplicateSymbols = [ String : ArraySlice < Element > ] ( )
225
234
226
- var new = Self ( )
227
- for (kind , hash ) in nonSymbols {
228
- new. add ( kind, hash, storage [ kind ] ! [ hash] ! )
235
+ var new = PathHierarchy . DisambiguationContainer ( )
236
+ for element in nonSymbols {
237
+ new. add ( element . node , kind: element . kind , hash: element . hash)
229
238
}
230
239
for (id, symbolDisambiguations) in uniqueSymbolIDs {
231
- let ( kind , hash ) = symbolDisambiguations [ 0 ]
232
- new. add ( kind, hash, storage [ kind ] ! [ hash] ! )
240
+ let element = symbolDisambiguations. first!
241
+ new. add ( element . node , kind: element . kind , hash: element . hash)
233
242
234
243
if symbolDisambiguations. count > 1 {
235
244
duplicateSymbols [ id] = symbolDisambiguations. dropFirst ( )
@@ -243,8 +252,8 @@ extension PathHierarchy.DisambiguationContainer {
243
252
244
253
for (id, disambiguations) in duplicateSymbols {
245
254
let primaryDisambiguation = disambiguated. first ( where: { $0. value. symbol? . identifier. precise == id } ) !. disambiguation
246
- for (kind , hash ) in disambiguations {
247
- disambiguated. append ( ( storage [ kind ] ! [ hash ] ! , primaryDisambiguation. updated ( kind: kind, hash: hash) ) )
255
+ for element in disambiguations {
256
+ disambiguated. append ( ( element . node , primaryDisambiguation. updated ( kind: element . kind, hash: element . hash) ) )
248
257
}
249
258
}
250
259
@@ -280,14 +289,14 @@ extension PathHierarchy.DisambiguationContainer {
280
289
}
281
290
282
291
/// Creates a new disambiguation with a new kind or hash value.
283
- func updated( kind: String , hash: String ) -> Self {
292
+ func updated( kind: String ? , hash: String ? ) -> Self {
284
293
switch self {
285
294
case . none:
286
295
return . none
287
296
case . kind:
288
- return . kind( kind )
297
+ return kind . map { . kind( $0 ) } ?? self
289
298
case . hash:
290
- return . hash( hash )
299
+ return hash . map { . hash( $0 ) } ?? self
291
300
}
292
301
}
293
302
}
0 commit comments