typeToTableHeaders converts a type to a slice of column names. If the given type is invalid (not a struct or a pointer to a struct, has invalid table tags, etc.), an error is returned. requireDefault is only needed for the root call. This is recursive, so nested structs do not need the default sort
(t reflect.Type, requireDefault bool)
| 355 | // structs do not need the default sort name. |
| 356 | // nolint:revive |
| 357 | func typeToTableHeaders(t reflect.Type, requireDefault bool) ([]string, string, error) { |
| 358 | if !isStructOrStructPointer(t) { |
| 359 | return nil, "", xerrors.Errorf("typeToTableHeaders called with a non-struct or a non-pointer-to-a-struct type") |
| 360 | } |
| 361 | if t.Kind() == reflect.Pointer { |
| 362 | t = t.Elem() |
| 363 | } |
| 364 | |
| 365 | headers := []string{} |
| 366 | defaultSortName := "" |
| 367 | noSortOpt := false |
| 368 | for i := 0; i < t.NumField(); i++ { |
| 369 | field := t.Field(i) |
| 370 | name, defaultSort, noSort, recursive, skip, _, err := parseTableStructTag(field) |
| 371 | if err != nil { |
| 372 | return nil, "", xerrors.Errorf("parse struct tags for field %q in type %q: %w", field.Name, t.String(), err) |
| 373 | } |
| 374 | if requireDefault && noSort { |
| 375 | noSortOpt = true |
| 376 | } |
| 377 | |
| 378 | if name == "" && (recursive && skip) { |
| 379 | return nil, "", xerrors.Errorf("a name is required for the field %q. "+ |
| 380 | "recursive_line will ensure this is never shown to the user, but is still needed", field.Name) |
| 381 | } |
| 382 | // If recurse and skip is set, the name is intentionally empty. |
| 383 | if name == "" { |
| 384 | continue |
| 385 | } |
| 386 | if defaultSort { |
| 387 | if defaultSortName != "" { |
| 388 | return nil, "", xerrors.Errorf("multiple fields marked as default sort in type %q", t.String()) |
| 389 | } |
| 390 | defaultSortName = name |
| 391 | } |
| 392 | |
| 393 | fieldType := field.Type |
| 394 | if recursive { |
| 395 | if !isStructOrStructPointer(fieldType) { |
| 396 | return nil, "", xerrors.Errorf("field %q in type %q is marked as recursive but does not contain a struct or a pointer to a struct", field.Name, t.String()) |
| 397 | } |
| 398 | |
| 399 | childNames, defaultSort, err := typeToTableHeaders(fieldType, false) |
| 400 | if err != nil { |
| 401 | return nil, "", xerrors.Errorf("get child field header names for field %q in type %q: %w", field.Name, fieldType.String(), err) |
| 402 | } |
| 403 | for _, childName := range childNames { |
| 404 | fullName := fmt.Sprintf("%s %s", name, childName) |
| 405 | if skip { |
| 406 | fullName = childName |
| 407 | } |
| 408 | headers = append(headers, fullName) |
| 409 | } |
| 410 | if defaultSortName == "" { |
| 411 | defaultSortName = defaultSort |
| 412 | } |
| 413 | continue |
| 414 | } |
no test coverage detected