parse.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /*
  2. Copyright 2019 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 markers
  14. import (
  15. "bytes"
  16. "fmt"
  17. "reflect"
  18. "strconv"
  19. "strings"
  20. sc "text/scanner"
  21. "unicode"
  22. "sigs.k8s.io/controller-tools/pkg/loader"
  23. )
  24. // expect checks that the next token of the scanner is the given token, adding an error
  25. // to the scanner if not. It returns whether the token was as expected.
  26. func expect(scanner *sc.Scanner, expected rune, errDesc string) bool {
  27. tok := scanner.Scan()
  28. if tok != expected {
  29. scanner.Error(scanner, fmt.Sprintf("expected %s, got %q", errDesc, scanner.TokenText()))
  30. return false
  31. }
  32. return true
  33. }
  34. // peekNoSpace is equivalent to scanner.Peek, except that it will consume intervening whitespace.
  35. func peekNoSpace(scanner *sc.Scanner) rune {
  36. hint := scanner.Peek()
  37. for ; hint <= rune(' ') && ((1<<uint64(hint))&scanner.Whitespace) != 0; hint = scanner.Peek() {
  38. scanner.Next() // skip the whitespace
  39. }
  40. return hint
  41. }
  42. var (
  43. // interfaceType is a pre-computed reflect.Type representing the empty interface.
  44. interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
  45. rawArgsType = reflect.TypeOf((*RawArguments)(nil)).Elem()
  46. )
  47. // lowerCamelCase converts PascalCase string to
  48. // a camelCase string (by lowering the first rune).
  49. func lowerCamelCase(in string) string {
  50. isFirst := true
  51. return strings.Map(func(inRune rune) rune {
  52. if isFirst {
  53. isFirst = false
  54. return unicode.ToLower(inRune)
  55. }
  56. return inRune
  57. }, in)
  58. }
  59. // RawArguments is a special type that can be used for a marker
  60. // to receive *all* raw, underparsed argument data for a marker.
  61. // You probably want to use `interface{}` to match any type instead.
  62. // Use *only* for legacy markers that don't follow Definition's normal
  63. // parsing logic. It should *not* be used as a field in a marker struct.
  64. type RawArguments []byte
  65. // ArgumentType is the kind of a marker argument type.
  66. // It's roughly analogous to a subset of reflect.Kind, with
  67. // an extra "AnyType" to represent the empty interface.
  68. type ArgumentType int
  69. const (
  70. // Invalid represents a type that can't be parsed, and should never be used.
  71. InvalidType ArgumentType = iota
  72. // IntType is an int
  73. IntType
  74. // NumberType is a float64
  75. NumberType
  76. // StringType is a string
  77. StringType
  78. // BoolType is a bool
  79. BoolType
  80. // AnyType is the empty interface, and matches the rest of the content
  81. AnyType
  82. // SliceType is any slice constructed of the ArgumentTypes
  83. SliceType
  84. // MapType is any map constructed of string keys, and ArgumentType values.
  85. // Keys are strings, and it's common to see AnyType (non-uniform) values.
  86. MapType
  87. // RawType represents content that gets passed directly to the marker
  88. // without any parsing. It should *only* be used with anonymous markers.
  89. RawType
  90. )
  91. // Argument is the type of a marker argument.
  92. type Argument struct {
  93. // Type is the type of this argument For non-scalar types (map and slice),
  94. // further information is specified in ItemType.
  95. Type ArgumentType
  96. // Optional indicates if this argument is optional.
  97. Optional bool
  98. // Pointer indicates if this argument was a pointer (this is really only
  99. // needed for deserialization, and should alway imply optional)
  100. Pointer bool
  101. // ItemType is the type of the slice item for slices, and the value type
  102. // for maps.
  103. ItemType *Argument
  104. }
  105. // typeString contains the internals of TypeString.
  106. func (a Argument) typeString(out *strings.Builder) {
  107. if a.Pointer {
  108. out.WriteRune('*')
  109. }
  110. switch a.Type {
  111. case InvalidType:
  112. out.WriteString("<invalid>")
  113. case IntType:
  114. out.WriteString("int")
  115. case NumberType:
  116. out.WriteString("float64")
  117. case StringType:
  118. out.WriteString("string")
  119. case BoolType:
  120. out.WriteString("bool")
  121. case AnyType:
  122. out.WriteString("<any>")
  123. case SliceType:
  124. out.WriteString("[]")
  125. // arguments can't be non-pointer optional, so just call into typeString again.
  126. a.ItemType.typeString(out)
  127. case MapType:
  128. out.WriteString("map[string]")
  129. a.ItemType.typeString(out)
  130. case RawType:
  131. out.WriteString("<raw>")
  132. }
  133. }
  134. // TypeString returns a string roughly equivalent
  135. // (but not identical) to the underlying Go type that
  136. // this argument would parse to. It's mainly useful
  137. // for user-friendly formatting of this argument (e.g.
  138. // help strings).
  139. func (a Argument) TypeString() string {
  140. out := &strings.Builder{}
  141. a.typeString(out)
  142. return out.String()
  143. }
  144. func (a Argument) String() string {
  145. if a.Optional {
  146. return fmt.Sprintf("<optional arg %s>", a.TypeString())
  147. }
  148. return fmt.Sprintf("<arg %s>", a.TypeString())
  149. }
  150. // castAndSet casts val to out's type if needed,
  151. // then sets out to val.
  152. func castAndSet(out, val reflect.Value) {
  153. outType := out.Type()
  154. if outType != val.Type() {
  155. val = val.Convert(outType)
  156. }
  157. out.Set(val)
  158. }
  159. // makeSliceType makes a reflect.Type for a slice of the given type.
  160. // Useful for constructing the out value for when AnyType's guess returns a slice.
  161. func makeSliceType(itemType Argument) (reflect.Type, error) {
  162. var itemReflectedType reflect.Type
  163. switch itemType.Type {
  164. case IntType:
  165. itemReflectedType = reflect.TypeOf(int(0))
  166. case NumberType:
  167. itemReflectedType = reflect.TypeOf(float64(0))
  168. case StringType:
  169. itemReflectedType = reflect.TypeOf("")
  170. case BoolType:
  171. itemReflectedType = reflect.TypeOf(false)
  172. case SliceType:
  173. subItemType, err := makeSliceType(*itemType.ItemType)
  174. if err != nil {
  175. return nil, err
  176. }
  177. itemReflectedType = subItemType
  178. case MapType:
  179. subItemType, err := makeMapType(*itemType.ItemType)
  180. if err != nil {
  181. return nil, err
  182. }
  183. itemReflectedType = subItemType
  184. // TODO(directxman12): support non-uniform slices? (probably not)
  185. default:
  186. return nil, fmt.Errorf("invalid type when constructing guessed slice out: %v", itemType.Type)
  187. }
  188. if itemType.Pointer {
  189. itemReflectedType = reflect.PtrTo(itemReflectedType)
  190. }
  191. return reflect.SliceOf(itemReflectedType), nil
  192. }
  193. // makeMapType makes a reflect.Type for a map of the given item type.
  194. // Useful for constructing the out value for when AnyType's guess returns a map.
  195. func makeMapType(itemType Argument) (reflect.Type, error) {
  196. var itemReflectedType reflect.Type
  197. switch itemType.Type {
  198. case IntType:
  199. itemReflectedType = reflect.TypeOf(int(0))
  200. case NumberType:
  201. itemReflectedType = reflect.TypeOf(float64(0))
  202. case StringType:
  203. itemReflectedType = reflect.TypeOf("")
  204. case BoolType:
  205. itemReflectedType = reflect.TypeOf(false)
  206. case SliceType:
  207. subItemType, err := makeSliceType(*itemType.ItemType)
  208. if err != nil {
  209. return nil, err
  210. }
  211. itemReflectedType = subItemType
  212. // TODO(directxman12): support non-uniform slices? (probably not)
  213. case MapType:
  214. subItemType, err := makeMapType(*itemType.ItemType)
  215. if err != nil {
  216. return nil, err
  217. }
  218. itemReflectedType = subItemType
  219. case AnyType:
  220. // NB(directxman12): maps explicitly allow non-uniform item types, unlike slices at the moment
  221. itemReflectedType = interfaceType
  222. default:
  223. return nil, fmt.Errorf("invalid type when constructing guessed slice out: %v", itemType.Type)
  224. }
  225. if itemType.Pointer {
  226. itemReflectedType = reflect.PtrTo(itemReflectedType)
  227. }
  228. return reflect.MapOf(reflect.TypeOf(""), itemReflectedType), nil
  229. }
  230. // guessType takes an educated guess about the type of the next field. If allowSlice
  231. // is false, it will not guess slices. It's less efficient than parsing with actual
  232. // type information, since we need to allocate to peek ahead full tokens, and the scanner
  233. // only allows peeking ahead one character.
  234. // Maps are *always* non-uniform (i.e. type the AnyType item type), since they're frequently
  235. // used to represent things like defaults for an object in JSON.
  236. func guessType(scanner *sc.Scanner, raw string, allowSlice bool) *Argument {
  237. if allowSlice {
  238. maybeItem := guessType(scanner, raw, false)
  239. subRaw := raw[scanner.Pos().Offset:]
  240. subScanner := parserScanner(subRaw, scanner.Error)
  241. var tok rune
  242. for {
  243. tok = subScanner.Scan()
  244. if tok == ',' || tok == sc.EOF || tok == ';' {
  245. break
  246. }
  247. // wait till we get something interesting
  248. }
  249. // semicolon means it's a legacy slice
  250. if tok == ';' {
  251. return &Argument{
  252. Type: SliceType,
  253. ItemType: maybeItem,
  254. }
  255. }
  256. return maybeItem
  257. }
  258. // everything else needs a duplicate scanner to scan properly
  259. // (so we don't consume our scanner tokens until we actually
  260. // go to use this -- Go doesn't like scanners that can be rewound).
  261. subRaw := raw[scanner.Pos().Offset:]
  262. subScanner := parserScanner(subRaw, scanner.Error)
  263. // skip whitespace
  264. hint := peekNoSpace(subScanner)
  265. // first, try the easy case -- quoted strings strings
  266. switch hint {
  267. case '"', '\'', '`':
  268. return &Argument{Type: StringType}
  269. }
  270. // next, check for slices or maps
  271. if hint == '{' {
  272. subScanner.Scan()
  273. // TODO(directxman12): this can't guess at empty objects, but that's generally ok.
  274. // We'll cross that bridge when we get there.
  275. // look ahead till we can figure out if this is a map or a slice
  276. hint = peekNoSpace(subScanner)
  277. firstElemType := guessType(subScanner, subRaw, false)
  278. if firstElemType.Type == StringType {
  279. // might be a map or slice, parse the string and check for colon
  280. // (blech, basically arbitrary look-ahead due to raw strings).
  281. var keyVal string // just ignore this
  282. (&Argument{Type: StringType}).parseString(subScanner, raw, reflect.Indirect(reflect.ValueOf(&keyVal)))
  283. if token := subScanner.Scan(); token == ':' || hint == '}' {
  284. // it's got a string followed by a colon -- it's a map
  285. // or an empty map in case of {}
  286. return &Argument{
  287. Type: MapType,
  288. ItemType: &Argument{Type: AnyType},
  289. }
  290. }
  291. }
  292. // definitely a slice -- maps have to have string keys and have a value followed by a colon
  293. return &Argument{
  294. Type: SliceType,
  295. ItemType: firstElemType,
  296. }
  297. }
  298. // then, bools...
  299. probablyString := false
  300. if hint == 't' || hint == 'f' {
  301. // maybe a bool
  302. if nextTok := subScanner.Scan(); nextTok == sc.Ident {
  303. switch subScanner.TokenText() {
  304. case "true", "false":
  305. // definitely a bool
  306. return &Argument{Type: BoolType}
  307. }
  308. // probably a string
  309. probablyString = true
  310. } else {
  311. // we shouldn't ever get here
  312. scanner.Error(scanner, fmt.Sprintf("got a token (%q) that looked like an ident, but was not", scanner.TokenText()))
  313. return &Argument{Type: InvalidType}
  314. }
  315. }
  316. // then, integers...
  317. if !probablyString {
  318. nextTok := subScanner.Scan()
  319. if nextTok == '-' {
  320. nextTok = subScanner.Scan()
  321. }
  322. if nextTok == sc.Int {
  323. return &Argument{Type: IntType}
  324. }
  325. if nextTok == sc.Float {
  326. return &Argument{Type: NumberType}
  327. }
  328. }
  329. // otherwise assume bare strings
  330. return &Argument{Type: StringType}
  331. }
  332. // parseString parses either of the two accepted string forms (quoted, or bare tokens).
  333. func (a *Argument) parseString(scanner *sc.Scanner, raw string, out reflect.Value) {
  334. // we need to temporarily disable the scanner's int/float parsing, since we want to
  335. // prevent number parsing errors.
  336. oldMode := scanner.Mode
  337. scanner.Mode = oldMode &^ sc.ScanInts &^ sc.ScanFloats
  338. defer func() {
  339. scanner.Mode = oldMode
  340. }()
  341. // strings are a bit weird -- the "easy" case is quoted strings (tokenized as strings),
  342. // the "hard" case (present for backwards compat) is a bare sequence of tokens that aren't
  343. // a comma.
  344. tok := scanner.Scan()
  345. if tok == sc.String || tok == sc.RawString {
  346. // the easy case
  347. val, err := strconv.Unquote(scanner.TokenText())
  348. if err != nil {
  349. scanner.Error(scanner, fmt.Sprintf("unable to parse string: %v", err))
  350. return
  351. }
  352. castAndSet(out, reflect.ValueOf(val))
  353. return
  354. }
  355. // the "hard" case -- bare tokens not including ',' (the argument
  356. // separator), ';' (the slice separator), ':' (the map separator), or '}'
  357. // (delimitted slice ender)
  358. startPos := scanner.Position.Offset
  359. for hint := peekNoSpace(scanner); hint != ',' && hint != ';' && hint != ':' && hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
  360. // skip this token
  361. scanner.Scan()
  362. }
  363. endPos := scanner.Position.Offset + len(scanner.TokenText())
  364. castAndSet(out, reflect.ValueOf(raw[startPos:endPos]))
  365. }
  366. // parseSlice parses either of the two slice forms (curly-brace-delimitted and semicolon-separated).
  367. func (a *Argument) parseSlice(scanner *sc.Scanner, raw string, out reflect.Value) {
  368. // slices have two supported formats, like string:
  369. // - `{val, val, val}` (preferred)
  370. // - `val;val;val` (legacy)
  371. resSlice := reflect.Zero(out.Type())
  372. elem := reflect.Indirect(reflect.New(out.Type().Elem()))
  373. // preferred case
  374. if peekNoSpace(scanner) == '{' {
  375. // NB(directxman12): supporting delimitted slices in bare slices
  376. // would require an extra look-ahead here :-/
  377. scanner.Scan() // skip '{'
  378. for hint := peekNoSpace(scanner); hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
  379. a.ItemType.parse(scanner, raw, elem, true /* parsing a slice */)
  380. resSlice = reflect.Append(resSlice, elem)
  381. tok := peekNoSpace(scanner)
  382. if tok == '}' {
  383. break
  384. }
  385. if !expect(scanner, ',', "comma") {
  386. return
  387. }
  388. }
  389. if !expect(scanner, '}', "close curly brace") {
  390. return
  391. }
  392. castAndSet(out, resSlice)
  393. return
  394. }
  395. // legacy case
  396. for hint := peekNoSpace(scanner); hint != ',' && hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
  397. a.ItemType.parse(scanner, raw, elem, true /* parsing a slice */)
  398. resSlice = reflect.Append(resSlice, elem)
  399. tok := peekNoSpace(scanner)
  400. if tok == ',' || tok == '}' || tok == sc.EOF {
  401. break
  402. }
  403. scanner.Scan()
  404. if tok != ';' {
  405. scanner.Error(scanner, fmt.Sprintf("expected comma, got %q", scanner.TokenText()))
  406. return
  407. }
  408. }
  409. castAndSet(out, resSlice)
  410. }
  411. // parseMap parses a map of the form {string: val, string: val, string: val}
  412. func (a *Argument) parseMap(scanner *sc.Scanner, raw string, out reflect.Value) {
  413. resMap := reflect.MakeMap(out.Type())
  414. elem := reflect.Indirect(reflect.New(out.Type().Elem()))
  415. key := reflect.Indirect(reflect.New(out.Type().Key()))
  416. if !expect(scanner, '{', "open curly brace") {
  417. return
  418. }
  419. for hint := peekNoSpace(scanner); hint != '}' && hint != sc.EOF; hint = peekNoSpace(scanner) {
  420. a.parseString(scanner, raw, key)
  421. if !expect(scanner, ':', "colon") {
  422. return
  423. }
  424. a.ItemType.parse(scanner, raw, elem, false /* not in a slice */)
  425. resMap.SetMapIndex(key, elem)
  426. if peekNoSpace(scanner) == '}' {
  427. break
  428. }
  429. if !expect(scanner, ',', "comma") {
  430. return
  431. }
  432. }
  433. if !expect(scanner, '}', "close curly brace") {
  434. return
  435. }
  436. castAndSet(out, resMap)
  437. }
  438. // parse functions like Parse, except that it allows passing down whether or not we're
  439. // already in a slice, to avoid duplicate legacy slice detection for AnyType
  440. func (a *Argument) parse(scanner *sc.Scanner, raw string, out reflect.Value, inSlice bool) {
  441. // nolint:gocyclo
  442. if a.Type == InvalidType {
  443. scanner.Error(scanner, "cannot parse invalid type")
  444. return
  445. }
  446. if a.Pointer {
  447. out.Set(reflect.New(out.Type().Elem()))
  448. out = reflect.Indirect(out)
  449. }
  450. switch a.Type {
  451. case RawType:
  452. // raw consumes everything else
  453. castAndSet(out, reflect.ValueOf(raw[scanner.Pos().Offset:]))
  454. // consume everything else
  455. var tok rune
  456. for {
  457. tok = scanner.Scan()
  458. if tok == sc.EOF {
  459. break
  460. }
  461. }
  462. case NumberType:
  463. nextChar := scanner.Peek()
  464. isNegative := false
  465. if nextChar == '-' {
  466. isNegative = true
  467. scanner.Scan() // eat the '-'
  468. }
  469. tok := scanner.Scan()
  470. if tok != sc.Float && tok != sc.Int {
  471. scanner.Error(scanner, fmt.Sprintf("expected integer or float, got %q", scanner.TokenText()))
  472. return
  473. }
  474. text := scanner.TokenText()
  475. if isNegative {
  476. text = "-" + text
  477. }
  478. val, err := strconv.ParseFloat(text, 64)
  479. if err != nil {
  480. scanner.Error(scanner, fmt.Sprintf("unable to parse number: %v", err))
  481. return
  482. }
  483. castAndSet(out, reflect.ValueOf(val))
  484. case IntType:
  485. nextChar := scanner.Peek()
  486. isNegative := false
  487. if nextChar == '-' {
  488. isNegative = true
  489. scanner.Scan() // eat the '-'
  490. }
  491. if !expect(scanner, sc.Int, "integer") {
  492. return
  493. }
  494. // TODO(directxman12): respect the size when parsing
  495. text := scanner.TokenText()
  496. if isNegative {
  497. text = "-" + text
  498. }
  499. val, err := strconv.Atoi(text)
  500. if err != nil {
  501. scanner.Error(scanner, fmt.Sprintf("unable to parse integer: %v", err))
  502. return
  503. }
  504. castAndSet(out, reflect.ValueOf(val))
  505. case StringType:
  506. // strings are a bit weird -- the "easy" case is quoted strings (tokenized as strings),
  507. // the "hard" case (present for backwards compat) is a bare sequence of tokens that aren't
  508. // a comma.
  509. a.parseString(scanner, raw, out)
  510. case BoolType:
  511. if !expect(scanner, sc.Ident, "true or false") {
  512. return
  513. }
  514. switch scanner.TokenText() {
  515. case "true":
  516. castAndSet(out, reflect.ValueOf(true))
  517. case "false":
  518. castAndSet(out, reflect.ValueOf(false))
  519. default:
  520. scanner.Error(scanner, fmt.Sprintf("expected true or false, got %q", scanner.TokenText()))
  521. return
  522. }
  523. case AnyType:
  524. guessedType := guessType(scanner, raw, !inSlice)
  525. newOut := out
  526. // we need to be able to construct the right element types, below
  527. // in parse, so construct a concretely-typed value to use as "out"
  528. switch guessedType.Type {
  529. case SliceType:
  530. newType, err := makeSliceType(*guessedType.ItemType)
  531. if err != nil {
  532. scanner.Error(scanner, err.Error())
  533. return
  534. }
  535. newOut = reflect.Indirect(reflect.New(newType))
  536. case MapType:
  537. newType, err := makeMapType(*guessedType.ItemType)
  538. if err != nil {
  539. scanner.Error(scanner, err.Error())
  540. return
  541. }
  542. newOut = reflect.Indirect(reflect.New(newType))
  543. }
  544. if !newOut.CanSet() {
  545. panic("at the disco") // TODO(directxman12): this is left over from debugging -- it might need to be an error
  546. }
  547. guessedType.Parse(scanner, raw, newOut)
  548. castAndSet(out, newOut)
  549. case SliceType:
  550. // slices have two supported formats, like string:
  551. // - `{val, val, val}` (preferred)
  552. // - `val;val;val` (legacy)
  553. a.parseSlice(scanner, raw, out)
  554. case MapType:
  555. // maps are {string: val, string: val, string: val}
  556. a.parseMap(scanner, raw, out)
  557. }
  558. }
  559. // Parse attempts to consume the argument from the given scanner (based on the given
  560. // raw input as well for collecting ranges of content), and places the output value
  561. // in the given reflect.Value. Errors are reported via the given scanner.
  562. func (a *Argument) Parse(scanner *sc.Scanner, raw string, out reflect.Value) {
  563. a.parse(scanner, raw, out, false)
  564. }
  565. // ArgumentFromType constructs an Argument by examining the given
  566. // raw reflect.Type. It can construct arguments from the Go types
  567. // corresponding to any of the types listed in ArgumentType.
  568. func ArgumentFromType(rawType reflect.Type) (Argument, error) {
  569. if rawType == rawArgsType {
  570. return Argument{
  571. Type: RawType,
  572. }, nil
  573. }
  574. if rawType == interfaceType {
  575. return Argument{
  576. Type: AnyType,
  577. }, nil
  578. }
  579. arg := Argument{}
  580. if rawType.Kind() == reflect.Ptr {
  581. rawType = rawType.Elem()
  582. arg.Pointer = true
  583. arg.Optional = true
  584. }
  585. switch rawType.Kind() {
  586. case reflect.String:
  587. arg.Type = StringType
  588. case reflect.Int, reflect.Int32: // NB(directxman12): all ints in kubernetes are int32, so explicitly support that
  589. arg.Type = IntType
  590. case reflect.Float64:
  591. arg.Type = NumberType
  592. case reflect.Bool:
  593. arg.Type = BoolType
  594. case reflect.Slice:
  595. arg.Type = SliceType
  596. itemType, err := ArgumentFromType(rawType.Elem())
  597. if err != nil {
  598. return Argument{}, fmt.Errorf("bad slice item type: %w", err)
  599. }
  600. arg.ItemType = &itemType
  601. case reflect.Map:
  602. arg.Type = MapType
  603. if rawType.Key().Kind() != reflect.String {
  604. return Argument{}, fmt.Errorf("bad map key type: map keys must be strings")
  605. }
  606. itemType, err := ArgumentFromType(rawType.Elem())
  607. if err != nil {
  608. return Argument{}, fmt.Errorf("bad slice item type: %w", err)
  609. }
  610. arg.ItemType = &itemType
  611. default:
  612. return Argument{}, fmt.Errorf("type has unsupported kind %s", rawType.Kind())
  613. }
  614. return arg, nil
  615. }
  616. // TargetType describes which kind of node a given marker is associated with.
  617. type TargetType int
  618. const (
  619. // DescribesPackage indicates that a marker is associated with a package.
  620. DescribesPackage TargetType = iota
  621. // DescribesType indicates that a marker is associated with a type declaration.
  622. DescribesType
  623. // DescribesField indicates that a marker is associated with a struct field.
  624. DescribesField
  625. )
  626. func (t TargetType) String() string {
  627. switch t {
  628. case DescribesPackage:
  629. return "package"
  630. case DescribesType:
  631. return "type"
  632. case DescribesField:
  633. return "field"
  634. default:
  635. return "(unknown)"
  636. }
  637. }
  638. // Definition is a parsed definition of a marker.
  639. type Definition struct {
  640. // Output is the deserialized Go type of the marker.
  641. Output reflect.Type
  642. // Name is the marker's name.
  643. Name string
  644. // Target indicates which kind of node this marker can be associated with.
  645. Target TargetType
  646. // Fields lists out the types of each field that this marker has, by
  647. // argument name as used in the marker (if the output type isn't a struct,
  648. // it'll have a single, blank field name). This only lists exported fields,
  649. // (as per reflection rules).
  650. Fields map[string]Argument
  651. // FieldNames maps argument names (as used in the marker) to struct field name
  652. // in the output type.
  653. FieldNames map[string]string
  654. // Strict indicates that this definition should error out when parsing if
  655. // not all non-optional fields were seen.
  656. Strict bool
  657. }
  658. // AnonymousField indicates that the definition has one field,
  659. // (actually the original object), and thus the field
  660. // doesn't get named as part of the name.
  661. func (d *Definition) AnonymousField() bool {
  662. if len(d.Fields) != 1 {
  663. return false
  664. }
  665. _, hasAnonField := d.Fields[""]
  666. return hasAnonField
  667. }
  668. // Empty indicates that this definition has no fields.
  669. func (d *Definition) Empty() bool {
  670. return len(d.Fields) == 0
  671. }
  672. // argumentInfo returns information about an argument field as the marker parser's field loader
  673. // would see it. This can be useful if you have to interact with marker definition structs
  674. // externally (e.g. at compile time).
  675. func argumentInfo(fieldName string, tag reflect.StructTag) (argName string, optionalOpt bool) {
  676. argName = lowerCamelCase(fieldName)
  677. markerTag, tagSpecified := tag.Lookup("marker")
  678. markerTagParts := strings.Split(markerTag, ",")
  679. if tagSpecified && markerTagParts[0] != "" {
  680. // allow overriding to support legacy cases where we don't follow camelCase conventions
  681. argName = markerTagParts[0]
  682. }
  683. optionalOpt = false
  684. for _, tagOption := range markerTagParts[1:] {
  685. switch tagOption {
  686. case "optional":
  687. optionalOpt = true
  688. }
  689. }
  690. return argName, optionalOpt
  691. }
  692. // loadFields uses reflection to populate argument information from the Output type.
  693. func (d *Definition) loadFields() error {
  694. if d.Fields == nil {
  695. d.Fields = make(map[string]Argument)
  696. d.FieldNames = make(map[string]string)
  697. }
  698. if d.Output.Kind() != reflect.Struct {
  699. // anonymous field type
  700. argType, err := ArgumentFromType(d.Output)
  701. if err != nil {
  702. return err
  703. }
  704. d.Fields[""] = argType
  705. d.FieldNames[""] = ""
  706. return nil
  707. }
  708. for i := 0; i < d.Output.NumField(); i++ {
  709. field := d.Output.Field(i)
  710. if field.PkgPath != "" {
  711. // as per the reflect package docs, pkgpath is empty for exported fields,
  712. // so non-empty package path means a private field, which we should skip
  713. continue
  714. }
  715. argName, optionalOpt := argumentInfo(field.Name, field.Tag)
  716. argType, err := ArgumentFromType(field.Type)
  717. if err != nil {
  718. return fmt.Errorf("unable to extract type information for field %q: %w", field.Name, err)
  719. }
  720. if argType.Type == RawType {
  721. return fmt.Errorf("RawArguments must be the direct type of a marker, and not a field")
  722. }
  723. argType.Optional = optionalOpt || argType.Optional
  724. d.Fields[argName] = argType
  725. d.FieldNames[argName] = field.Name
  726. }
  727. return nil
  728. }
  729. // parserScanner makes a new scanner appropriate for use in parsing definitions and arguments.
  730. func parserScanner(raw string, err func(*sc.Scanner, string)) *sc.Scanner {
  731. scanner := &sc.Scanner{}
  732. scanner.Init(bytes.NewBufferString(raw))
  733. scanner.Mode = sc.ScanIdents | sc.ScanInts | sc.ScanFloats | sc.ScanStrings | sc.ScanRawStrings | sc.SkipComments
  734. scanner.Error = err
  735. return scanner
  736. }
  737. // Parse uses the type information in this Definition to parse the given
  738. // raw marker in the form `+a:b:c=arg,d=arg` into an output object of the
  739. // type specified in the definition.
  740. func (d *Definition) Parse(rawMarker string) (interface{}, error) {
  741. name, anonName, fields := splitMarker(rawMarker)
  742. out := reflect.Indirect(reflect.New(d.Output))
  743. // if we're a not a struct or have no arguments, treat the full `a:b:c` as the name,
  744. // otherwise, treat `c` as a field name, and `a:b` as the marker name.
  745. if !d.AnonymousField() && !d.Empty() && len(anonName) >= len(name)+1 {
  746. fields = anonName[len(name)+1:] + "=" + fields
  747. }
  748. var errs []error
  749. scanner := parserScanner(fields, func(scanner *sc.Scanner, msg string) {
  750. errs = append(errs, &ScannerError{Msg: msg, Pos: scanner.Position})
  751. })
  752. // TODO(directxman12): strict parsing where we error out if certain fields aren't optional
  753. seen := make(map[string]struct{}, len(d.Fields))
  754. if d.AnonymousField() && scanner.Peek() != sc.EOF {
  755. // might still be a struct that something fiddled with, so double check
  756. structFieldName := d.FieldNames[""]
  757. outTarget := out
  758. if structFieldName != "" {
  759. // it's a struct field mapped to an anonymous marker
  760. outTarget = out.FieldByName(structFieldName)
  761. if !outTarget.CanSet() {
  762. scanner.Error(scanner, fmt.Sprintf("cannot set field %q (might not exist)", structFieldName))
  763. return out.Interface(), loader.MaybeErrList(errs)
  764. }
  765. }
  766. // no need for trying to parse field names if we're not a struct
  767. field := d.Fields[""]
  768. field.Parse(scanner, fields, outTarget)
  769. seen[""] = struct{}{} // mark as seen for strict definitions
  770. } else if !d.Empty() && scanner.Peek() != sc.EOF {
  771. // if we expect *and* actually have arguments passed
  772. for {
  773. // parse the argument name
  774. if !expect(scanner, sc.Ident, "argument name") {
  775. break
  776. }
  777. argName := scanner.TokenText()
  778. if !expect(scanner, '=', "equals") {
  779. break
  780. }
  781. // make sure we know the field
  782. fieldName, known := d.FieldNames[argName]
  783. if !known {
  784. scanner.Error(scanner, fmt.Sprintf("unknown argument %q", argName))
  785. break
  786. }
  787. fieldType, known := d.Fields[argName]
  788. if !known {
  789. scanner.Error(scanner, fmt.Sprintf("unknown argument %q", argName))
  790. break
  791. }
  792. seen[argName] = struct{}{} // mark as seen for strict definitions
  793. // parse the field value
  794. fieldVal := out.FieldByName(fieldName)
  795. if !fieldVal.CanSet() {
  796. scanner.Error(scanner, fmt.Sprintf("cannot set field %q (might not exist)", fieldName))
  797. break
  798. }
  799. fieldType.Parse(scanner, fields, fieldVal)
  800. if len(errs) > 0 {
  801. break
  802. }
  803. if scanner.Peek() == sc.EOF {
  804. break
  805. }
  806. if !expect(scanner, ',', "comma") {
  807. break
  808. }
  809. }
  810. }
  811. if tok := scanner.Scan(); tok != sc.EOF {
  812. scanner.Error(scanner, fmt.Sprintf("extra arguments provided: %q", fields[scanner.Position.Offset:]))
  813. }
  814. if d.Strict {
  815. for argName, arg := range d.Fields {
  816. if _, wasSeen := seen[argName]; !wasSeen && !arg.Optional {
  817. scanner.Error(scanner, fmt.Sprintf("missing argument %q", argName))
  818. }
  819. }
  820. }
  821. return out.Interface(), loader.MaybeErrList(errs)
  822. }
  823. // MakeDefinition constructs a definition from a name, type, and the output type.
  824. // All such definitions are strict by default. If a struct is passed as the output
  825. // type, its public fields will automatically be populated into Fields (and similar
  826. // fields in Definition). Other values will have a single, empty-string-named Fields
  827. // entry.
  828. func MakeDefinition(name string, target TargetType, output interface{}) (*Definition, error) {
  829. def := &Definition{
  830. Name: name,
  831. Target: target,
  832. Output: reflect.TypeOf(output),
  833. Strict: true,
  834. }
  835. if err := def.loadFields(); err != nil {
  836. return nil, err
  837. }
  838. return def, nil
  839. }
  840. // MakeAnyTypeDefinition constructs a definition for an output struct with a
  841. // field named `Value` of type `interface{}`. The argument to the marker will
  842. // be parsed as AnyType and assigned to the field named `Value`.
  843. func MakeAnyTypeDefinition(name string, target TargetType, output interface{}) (*Definition, error) {
  844. defn, err := MakeDefinition(name, target, output)
  845. if err != nil {
  846. return nil, err
  847. }
  848. defn.FieldNames = map[string]string{"": "Value"}
  849. defn.Fields = map[string]Argument{"": defn.Fields["value"]}
  850. return defn, nil
  851. }
  852. // splitMarker takes a marker in the form of `+a:b:c=arg,d=arg` and splits it
  853. // into the name (`a:b`), the name if it's not a struct (`a:b:c`), and the parts
  854. // that are definitely fields (`arg,d=arg`).
  855. func splitMarker(raw string) (name string, anonymousName string, restFields string) {
  856. raw = raw[1:] // get rid of the leading '+'
  857. nameFieldParts := strings.SplitN(raw, "=", 2)
  858. if len(nameFieldParts) == 1 {
  859. return nameFieldParts[0], nameFieldParts[0], ""
  860. }
  861. anonymousName = nameFieldParts[0]
  862. name = anonymousName
  863. restFields = nameFieldParts[1]
  864. nameParts := strings.Split(name, ":")
  865. if len(nameParts) > 1 {
  866. name = strings.Join(nameParts[:len(nameParts)-1], ":")
  867. }
  868. return name, anonymousName, restFields
  869. }
  870. type ScannerError struct {
  871. Msg string
  872. Pos sc.Position
  873. }
  874. func (e *ScannerError) Error() string {
  875. return fmt.Sprintf("%s (at %s)", e.Msg, e.Pos)
  876. }