comments.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. Copyright 2025 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package util
  14. import (
  15. "fmt"
  16. "k8s.io/gengo/v2"
  17. )
  18. // ExtractCommentTagsWithoutArguments parses comments for special metadata tags. The
  19. // marker argument should be unique enough to identify the tags needed, and
  20. // should not be a marker for tags you don't want, or else the caller takes
  21. // responsibility for making that distinction.
  22. //
  23. // The tagNames argument is a list of specific tags being extracted. If this is
  24. // nil or empty, all lines which match the marker are considered. If this is
  25. // specified, only lines with begin with marker + one of the tags will be
  26. // considered. This is useful when a common marker is used which may match
  27. // lines which fail this syntax (e.g. which predate this definition).
  28. //
  29. // This function looks for input lines of the following forms:
  30. // - 'marker' + "key=value"
  31. // - 'marker' + "key()=value"
  32. // - 'marker' + "key(arg)=value"
  33. //
  34. // The arg is forbidden. This function only consider tags with no arguments specified
  35. // (either as "key=value" or as // "key()=value"). Finding tags with an argument will
  36. // result in an error.
  37. //
  38. // The value is optional. If not specified, the resulting Tag will have "" as
  39. // the value.
  40. //
  41. // Tag comment-lines may have a trailing end-of-line comment.
  42. //
  43. // The map returned here is keyed by the Tag's name without args.
  44. //
  45. // A tag can be specified more than one time and all values are returned. If
  46. // the resulting map has an entry for a key, the value (a slice) is guaranteed
  47. // to have at least 1 element.
  48. //
  49. // Example: if you pass "+" for 'marker', and the following lines are in
  50. // the comments:
  51. //
  52. // +foo=val1 // foo
  53. // +bar
  54. // +foo=val2 // also foo
  55. // +foo()=val3 // still foo
  56. // +baz="qux"
  57. //
  58. // Then this function will return:
  59. //
  60. // map[string][]string{"foo":{"val1", "val2", "val3"}, "bar": {""}, "baz": {`"qux"`}}
  61. func ExtractCommentTagsWithoutArguments(marker string, tagNames []string, lines []string) (map[string][]string, error) {
  62. functionStyleTags, err := gengo.ExtractFunctionStyleCommentTags(marker, tagNames, lines)
  63. if err != nil {
  64. return nil, err
  65. }
  66. out := make(map[string][]string)
  67. for tagName, tags := range functionStyleTags {
  68. values := make([]string, 0)
  69. for _, tag := range tags {
  70. if tag.Args == nil {
  71. values = append(values, tag.Value)
  72. } else {
  73. return nil, fmt.Errorf(`failed to parse tag %s: expected no arguments, found "%s"`, tag, tag.Args[0])
  74. }
  75. }
  76. if len(values) > 0 {
  77. out[tagName] = values
  78. }
  79. }
  80. return out, nil
  81. }