.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / github.com / !burnt!sushi / toml@v0.3.1 / type_fields.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/github.com/!burnt!sushi/toml@v0.3.1/type_fields.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/github.com/!burnt!sushi/toml@v0.3.1/type_fields.go
new file mode 100644 (file)
index 0000000..608997c
--- /dev/null
@@ -0,0 +1,242 @@
+package toml
+
+// Struct field handling is adapted from code in encoding/json:
+//
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the Go distribution.
+
+import (
+       "reflect"
+       "sort"
+       "sync"
+)
+
+// A field represents a single field found in a struct.
+type field struct {
+       name  string       // the name of the field (`toml` tag included)
+       tag   bool         // whether field has a `toml` tag
+       index []int        // represents the depth of an anonymous field
+       typ   reflect.Type // the type of the field
+}
+
+// byName sorts field by name, breaking ties with depth,
+// then breaking ties with "name came from toml tag", then
+// breaking ties with index sequence.
+type byName []field
+
+func (x byName) Len() int { return len(x) }
+
+func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byName) Less(i, j int) bool {
+       if x[i].name != x[j].name {
+               return x[i].name < x[j].name
+       }
+       if len(x[i].index) != len(x[j].index) {
+               return len(x[i].index) < len(x[j].index)
+       }
+       if x[i].tag != x[j].tag {
+               return x[i].tag
+       }
+       return byIndex(x).Less(i, j)
+}
+
+// byIndex sorts field by index sequence.
+type byIndex []field
+
+func (x byIndex) Len() int { return len(x) }
+
+func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byIndex) Less(i, j int) bool {
+       for k, xik := range x[i].index {
+               if k >= len(x[j].index) {
+                       return false
+               }
+               if xik != x[j].index[k] {
+                       return xik < x[j].index[k]
+               }
+       }
+       return len(x[i].index) < len(x[j].index)
+}
+
+// typeFields returns a list of fields that TOML should recognize for the given
+// type. The algorithm is breadth-first search over the set of structs to
+// include - the top struct and then any reachable anonymous structs.
+func typeFields(t reflect.Type) []field {
+       // Anonymous fields to explore at the current level and the next.
+       current := []field{}
+       next := []field{{typ: t}}
+
+       // Count of queued names for current level and the next.
+       count := map[reflect.Type]int{}
+       nextCount := map[reflect.Type]int{}
+
+       // Types already visited at an earlier level.
+       visited := map[reflect.Type]bool{}
+
+       // Fields found.
+       var fields []field
+
+       for len(next) > 0 {
+               current, next = next, current[:0]
+               count, nextCount = nextCount, map[reflect.Type]int{}
+
+               for _, f := range current {
+                       if visited[f.typ] {
+                               continue
+                       }
+                       visited[f.typ] = true
+
+                       // Scan f.typ for fields to include.
+                       for i := 0; i < f.typ.NumField(); i++ {
+                               sf := f.typ.Field(i)
+                               if sf.PkgPath != "" && !sf.Anonymous { // unexported
+                                       continue
+                               }
+                               opts := getOptions(sf.Tag)
+                               if opts.skip {
+                                       continue
+                               }
+                               index := make([]int, len(f.index)+1)
+                               copy(index, f.index)
+                               index[len(f.index)] = i
+
+                               ft := sf.Type
+                               if ft.Name() == "" && ft.Kind() == reflect.Ptr {
+                                       // Follow pointer.
+                                       ft = ft.Elem()
+                               }
+
+                               // Record found field and index sequence.
+                               if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
+                                       tagged := opts.name != ""
+                                       name := opts.name
+                                       if name == "" {
+                                               name = sf.Name
+                                       }
+                                       fields = append(fields, field{name, tagged, index, ft})
+                                       if count[f.typ] > 1 {
+                                               // If there were multiple instances, add a second,
+                                               // so that the annihilation code will see a duplicate.
+                                               // It only cares about the distinction between 1 or 2,
+                                               // so don't bother generating any more copies.
+                                               fields = append(fields, fields[len(fields)-1])
+                                       }
+                                       continue
+                               }
+
+                               // Record new anonymous struct to explore in next round.
+                               nextCount[ft]++
+                               if nextCount[ft] == 1 {
+                                       f := field{name: ft.Name(), index: index, typ: ft}
+                                       next = append(next, f)
+                               }
+                       }
+               }
+       }
+
+       sort.Sort(byName(fields))
+
+       // Delete all fields that are hidden by the Go rules for embedded fields,
+       // except that fields with TOML tags are promoted.
+
+       // The fields are sorted in primary order of name, secondary order
+       // of field index length. Loop over names; for each name, delete
+       // hidden fields by choosing the one dominant field that survives.
+       out := fields[:0]
+       for advance, i := 0, 0; i < len(fields); i += advance {
+               // One iteration per name.
+               // Find the sequence of fields with the name of this first field.
+               fi := fields[i]
+               name := fi.name
+               for advance = 1; i+advance < len(fields); advance++ {
+                       fj := fields[i+advance]
+                       if fj.name != name {
+                               break
+                       }
+               }
+               if advance == 1 { // Only one field with this name
+                       out = append(out, fi)
+                       continue
+               }
+               dominant, ok := dominantField(fields[i : i+advance])
+               if ok {
+                       out = append(out, dominant)
+               }
+       }
+
+       fields = out
+       sort.Sort(byIndex(fields))
+
+       return fields
+}
+
+// dominantField looks through the fields, all of which are known to
+// have the same name, to find the single field that dominates the
+// others using Go's embedding rules, modified by the presence of
+// TOML tags. If there are multiple top-level fields, the boolean
+// will be false: This condition is an error in Go and we skip all
+// the fields.
+func dominantField(fields []field) (field, bool) {
+       // The fields are sorted in increasing index-length order. The winner
+       // must therefore be one with the shortest index length. Drop all
+       // longer entries, which is easy: just truncate the slice.
+       length := len(fields[0].index)
+       tagged := -1 // Index of first tagged field.
+       for i, f := range fields {
+               if len(f.index) > length {
+                       fields = fields[:i]
+                       break
+               }
+               if f.tag {
+                       if tagged >= 0 {
+                               // Multiple tagged fields at the same level: conflict.
+                               // Return no field.
+                               return field{}, false
+                       }
+                       tagged = i
+               }
+       }
+       if tagged >= 0 {
+               return fields[tagged], true
+       }
+       // All remaining fields have the same length. If there's more than one,
+       // we have a conflict (two fields named "X" at the same level) and we
+       // return no field.
+       if len(fields) > 1 {
+               return field{}, false
+       }
+       return fields[0], true
+}
+
+var fieldCache struct {
+       sync.RWMutex
+       m map[reflect.Type][]field
+}
+
+// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
+func cachedTypeFields(t reflect.Type) []field {
+       fieldCache.RLock()
+       f := fieldCache.m[t]
+       fieldCache.RUnlock()
+       if f != nil {
+               return f
+       }
+
+       // Compute fields without lock.
+       // Might duplicate effort but won't hold other computations back.
+       f = typeFields(t)
+       if f == nil {
+               f = []field{}
+       }
+
+       fieldCache.Lock()
+       if fieldCache.m == nil {
+               fieldCache.m = map[reflect.Type][]field{}
+       }
+       fieldCache.m[t] = f
+       fieldCache.Unlock()
+       return f
+}