walkAttributeUserTypes traverses att and invokes visit for each encountered user type. The path argument records the traversal path through objects, arrays, maps, and unions and is intended for diagnostics.
(att *AttributeExpr, seen map[string]struct{}, path string, visit func(UserType, string))
| 288 | // The path argument records the traversal path through objects, arrays, maps, |
| 289 | // and unions and is intended for diagnostics. |
| 290 | func (r *RootExpr) walkAttributeUserTypes(att *AttributeExpr, seen map[string]struct{}, path string, visit func(UserType, string)) { |
| 291 | if att == nil || att.Type == Empty { |
| 292 | return |
| 293 | } |
| 294 | switch t := att.Type.(type) { |
| 295 | case UserType: |
| 296 | if _, ok := seen[t.ID()]; ok { |
| 297 | return |
| 298 | } |
| 299 | seen[t.ID()] = struct{}{} |
| 300 | visit(t, path) |
| 301 | r.walkAttributeUserTypes(t.Attribute(), seen, path, visit) |
| 302 | case *Object: |
| 303 | for _, nat := range *t { |
| 304 | next := nat.Name |
| 305 | if path != "" { |
| 306 | next = path + "." + nat.Name |
| 307 | } |
| 308 | r.walkAttributeUserTypes(nat.Attribute, seen, next, visit) |
| 309 | } |
| 310 | case *Array: |
| 311 | next := path + "[]" |
| 312 | r.walkAttributeUserTypes(t.ElemType, seen, next, visit) |
| 313 | case *Map: |
| 314 | r.walkAttributeUserTypes(t.KeyType, seen, path+"[key]", visit) |
| 315 | r.walkAttributeUserTypes(t.ElemType, seen, path+"[value]", visit) |
| 316 | case *Union: |
| 317 | for _, nat := range t.Values { |
| 318 | next := nat.Name |
| 319 | if path != "" { |
| 320 | next = path + "." + nat.Name |
| 321 | } |
| 322 | r.walkAttributeUserTypes(nat.Attribute, seen, next, visit) |
| 323 | } |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | // Finalize finalizes the server expressions. |
| 328 | func (r *RootExpr) Finalize() { |
no test coverage detected