Matthias Andreas Benkard | 832a54e | 2019-01-29 09:27:38 +0100 | [diff] [blame] | 1 | /* |
| 2 | Copyright 2015 The Kubernetes Authors. |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package types |
| 18 | |
| 19 | // FlattenMembers recursively takes any embedded members and puts them in the |
| 20 | // top level, correctly hiding them if the top level hides them. There must not |
| 21 | // be a cycle-- that implies infinite members. |
| 22 | // |
| 23 | // This is useful for e.g. computing all the valid keys in a json struct, |
| 24 | // properly considering any configuration of embedded structs. |
| 25 | func FlattenMembers(m []Member) []Member { |
| 26 | embedded := []Member{} |
| 27 | normal := []Member{} |
| 28 | type nameInfo struct { |
| 29 | top bool |
| 30 | i int |
| 31 | } |
| 32 | names := map[string]nameInfo{} |
| 33 | for i := range m { |
| 34 | if m[i].Embedded && m[i].Type.Kind == Struct { |
| 35 | embedded = append(embedded, m[i]) |
| 36 | } else { |
| 37 | normal = append(normal, m[i]) |
| 38 | names[m[i].Name] = nameInfo{true, len(normal) - 1} |
| 39 | } |
| 40 | } |
| 41 | for i := range embedded { |
| 42 | for _, e := range FlattenMembers(embedded[i].Type.Members) { |
| 43 | if info, found := names[e.Name]; found { |
| 44 | if info.top { |
| 45 | continue |
| 46 | } |
| 47 | if n := normal[info.i]; n.Name == e.Name && n.Type == e.Type { |
| 48 | continue |
| 49 | } |
| 50 | panic("conflicting members") |
| 51 | } |
| 52 | normal = append(normal, e) |
| 53 | names[e.Name] = nameInfo{false, len(normal) - 1} |
| 54 | } |
| 55 | } |
| 56 | return normal |
| 57 | } |