@@ -55,7 +55,7 @@ type Symbol struct {
55
55
New bool
56
56
}
57
57
58
- func (s * Symbol ) addBuilds (builds [] internal.BuildContext ) {
58
+ func (s * Symbol ) addBuilds (builds ... internal.BuildContext ) {
59
59
if s .builds == nil {
60
60
s .builds = map [internal.BuildContext ]bool {}
61
61
}
@@ -94,18 +94,23 @@ func symbolsForVersion(pkgURLPath string, symbolsAtVersion map[string]map[intern
94
94
}
95
95
nameToMetaToSymbol [us.Name ][sm ] = s
96
96
}
97
- s .addBuilds (us .BuildContexts ())
97
+ s .addBuilds (us .BuildContexts ()... )
98
98
}
99
99
}
100
100
101
101
for cm , cus := range children {
102
- // Option 1: no parent exists
103
- // - make one, add to map
104
- // - append to parent
105
- // Option 2: parent exists and supports child bc
106
- // - append to parent
107
- // Option 3 parent exists and does not support child bc
108
- // - append to parent
102
+ // For each child symbol, 1 of 3 things can occur:
103
+ //
104
+ // Option 1: If no parent exists for this child symbol, make one
105
+ // and add the parent to the map.
106
+ //
107
+ // Option 2: A parent exists and does not support the build context
108
+ // of the child. This occurs when the parent type is introduced for
109
+ // another build context, but was introduced at the previous version
110
+ // for the current child. Create a new parent for this child.
111
+ //
112
+ // Option 3: A parent exists and does support the build context of
113
+ // the child. Add the child to the parent.
109
114
cs := & Symbol {
110
115
Name : cm .Name ,
111
116
Synopsis : cm .Synopsis ,
@@ -115,37 +120,43 @@ func symbolsForVersion(pkgURLPath string, symbolsAtVersion map[string]map[intern
115
120
New : true ,
116
121
}
117
122
118
- parents , ok := nameToMetaToSymbol [cm .ParentName ]
119
- var found bool
120
- if ok {
121
- for _ , ps := range parents {
122
- for build := range ps .builds {
123
- if cus .SupportsBuild (build ) {
124
- ps .Children = append (ps .Children , cs )
125
- found = true
126
- break
127
- }
128
- }
129
- }
130
- }
131
- if found {
123
+ ps := findParent (cm .ParentName , cus , nameToMetaToSymbol )
124
+ if ps != nil {
125
+ // Option 3: found a relevant parent.
126
+ ps .Children = append (ps .Children , cs )
132
127
continue
133
128
}
134
129
135
- // We did not find a parent, so create one.
136
- ps := createParent (cus , pkgURLPath )
137
- ps .Children = append (ps .Children , cs )
130
+ // Option 1 and 2: We did not find a relevant parent, so create
131
+ // one.
132
+ //
133
+ // Since this parent is not introduced at this version, create
134
+ // a distinct type for each group of symbols.
135
+ // To do so, we make up a synopsis for the SymbolMeta below, since it
136
+ // is only used as a key in nameToMetaToSymbol.
137
+ //
138
+ // Example case:
139
+ // http://pkg.go.dev/internal/poll?tab=versions for go1.10 should show:
140
+ //
141
+ // type FD -- windows/amd64
142
+ // FD.ReadMsg
143
+ // FD.WriteMsg
144
+ // type FD -- darwin/amd64, linux/amd64
145
+ // FD.SetBlocking
146
+ // FD.WriteOnce
147
+ ps = createParent (cm .ParentName , pkgURLPath , cus .BuildContexts ()... )
138
148
pm := internal.SymbolMeta {
139
149
Name : ps .Name ,
140
150
ParentName : ps .Name ,
141
- Synopsis : ps .Synopsis ,
151
+ Synopsis : fmt . Sprintf ( "type %s (%v)" , ps .Name , cus . BuildContexts ()) ,
142
152
Section : ps .Section ,
143
153
Kind : ps .Kind ,
144
154
}
145
- ps .addBuilds ( cus . BuildContexts () )
146
- nameToMetaToSymbol [pm .Name ] = map [internal. SymbolMeta ] * Symbol {
147
- pm : ps ,
155
+ ps .Children = append ( ps . Children , cs )
156
+ if _ , ok := nameToMetaToSymbol [pm .Name ]; ! ok {
157
+ nameToMetaToSymbol [ pm . Name ] = map [internal. SymbolMeta ] * Symbol {}
148
158
}
159
+ nameToMetaToSymbol [pm.Name ][pm ] = ps
149
160
}
150
161
151
162
var symbols []* Symbol
@@ -163,6 +174,22 @@ func symbolsForVersion(pkgURLPath string, symbolsAtVersion map[string]map[intern
163
174
return sortSymbols (symbols )
164
175
}
165
176
177
+ func findParent (parentName string , cus * internal.UnitSymbol ,
178
+ nameToMetaToSymbol map [string ]map [internal.SymbolMeta ]* Symbol ) * Symbol {
179
+ parents , ok := nameToMetaToSymbol [parentName ]
180
+ if ! ok {
181
+ return nil
182
+ }
183
+ for _ , ps := range parents {
184
+ for build := range ps .builds {
185
+ if cus .SupportsBuild (build ) {
186
+ return ps
187
+ }
188
+ }
189
+ }
190
+ return nil
191
+ }
192
+
166
193
func symbolLink (pkgURLPath , name string , builds []internal.BuildContext ) string {
167
194
if len (builds ) == len (internal .BuildContexts ) {
168
195
return fmt .Sprintf ("%s#%s" , pkgURLPath , name )
@@ -179,15 +206,15 @@ func symbolLink(pkgURLPath, name string, builds []internal.BuildContext) string
179
206
// different version. The symbol created will have New set to false, since this
180
207
// function is only used when a parent symbol is not found for the unit symbol,
181
208
// which means it was not introduced at the same version.
182
- func createParent (us * internal. UnitSymbol , pkgURLPath string ) * Symbol {
209
+ func createParent (parentName , pkgURLPath string , builds ... internal. BuildContext ) * Symbol {
183
210
s := & Symbol {
184
- Name : us . ParentName ,
185
- Synopsis : fmt .Sprintf ("type %s" , us . ParentName ),
211
+ Name : parentName ,
212
+ Synopsis : fmt .Sprintf ("type %s" , parentName ),
186
213
Section : internal .SymbolSectionTypes ,
187
214
Kind : internal .SymbolKindType ,
188
- Link : symbolLink (pkgURLPath , us . ParentName , us . BuildContexts () ),
215
+ Link : symbolLink (pkgURLPath , parentName , builds ),
189
216
}
190
- s .addBuilds (us . BuildContexts () )
217
+ s .addBuilds (builds ... )
191
218
return s
192
219
}
193
220
@@ -240,10 +267,31 @@ func sortSymbols(symbols []*Symbol) [][]*Symbol {
240
267
241
268
func sortSymbolsGroup (syms []* Symbol ) {
242
269
sort .Slice (syms , func (i , j int ) bool {
243
- return syms [i ].Synopsis < syms [j ].Synopsis
270
+ s1 := syms [i ]
271
+ s2 := syms [j ]
272
+ if s1 .Synopsis != s2 .Synopsis {
273
+ return s1 .Synopsis < s2 .Synopsis
274
+ }
275
+ return compareStringSlices (s1 .Builds , s2 .Builds ) < 0
244
276
})
245
277
}
246
278
279
+ func compareStringSlices (ss1 , ss2 []string ) int {
280
+ for i , s1 := range ss1 {
281
+ if i >= len (ss2 ) { // first slice is longer, so greater
282
+ return 1
283
+ }
284
+ if c := strings .Compare (s1 , ss2 [i ]); c != 0 {
285
+ return c
286
+ }
287
+ }
288
+ if len (ss1 ) == len (ss2 ) {
289
+ return 0
290
+ }
291
+ // first slice is shorter
292
+ return - 1
293
+ }
294
+
247
295
// ParseVersionsDetails returns a map of versionToNameToUnitSymbol based on
248
296
// data from the proovided VersionDetails.
249
297
func ParseVersionsDetails (vd VersionsDetails ) (_ * internal.SymbolHistory , err error ) {
0 commit comments