equal
deleted
inserted
replaced
121 // If set to true, calling nextExpr will not actually pull a new expression |
121 // If set to true, calling nextExpr will not actually pull a new expression |
122 // but turn off the flag instead. |
122 // but turn off the flag instead. |
123 stashedExpr bool |
123 stashedExpr bool |
124 |
124 |
125 // Skip expressions until a table is found. This is set to true when a |
125 // Skip expressions until a table is found. This is set to true when a |
126 // table could not be create (missing field in map), so all KV expressions |
126 // table could not be created (missing field in map), so all KV expressions |
127 // need to be skipped. |
127 // need to be skipped. |
128 skipUntilTable bool |
128 skipUntilTable bool |
129 |
129 |
130 // Tracks position in Go arrays. |
130 // Tracks position in Go arrays. |
131 // This is used when decoding [[array tables]] into Go arrays. Given array |
131 // This is used when decoding [[array tables]] into Go arrays. Given array |
481 } |
481 } |
482 t := v.Type() |
482 t := v.Type() |
483 d.errorContext.Struct = t |
483 d.errorContext.Struct = t |
484 d.errorContext.Field = path |
484 d.errorContext.Field = path |
485 |
485 |
486 f := v.FieldByIndex(path) |
486 f := fieldByIndex(v, path) |
487 x, err := nextFn(key, f) |
487 x, err := nextFn(key, f) |
488 if err != nil || d.skipUntilTable { |
488 if err != nil || d.skipUntilTable { |
489 return reflect.Value{}, err |
489 return reflect.Value{}, err |
490 } |
490 } |
491 if x.IsValid() { |
491 if x.IsValid() { |
1069 } |
1069 } |
1070 t := v.Type() |
1070 t := v.Type() |
1071 d.errorContext.Struct = t |
1071 d.errorContext.Struct = t |
1072 d.errorContext.Field = path |
1072 d.errorContext.Field = path |
1073 |
1073 |
1074 f := v.FieldByIndex(path) |
1074 f := fieldByIndex(v, path) |
1075 x, err := d.handleKeyValueInner(key, value, f) |
1075 x, err := d.handleKeyValueInner(key, value, f) |
1076 if err != nil { |
1076 if err != nil { |
1077 return reflect.Value{}, err |
1077 return reflect.Value{}, err |
1078 } |
1078 } |
1079 |
1079 |
1133 } |
1133 } |
1134 elem = v.Elem() |
1134 elem = v.Elem() |
1135 return elem |
1135 return elem |
1136 } |
1136 } |
1137 |
1137 |
|
1138 // Same as reflect.Value.FieldByIndex, but creates pointers if needed. |
|
1139 func fieldByIndex(v reflect.Value, path []int) reflect.Value { |
|
1140 for i, x := range path { |
|
1141 v = v.Field(x) |
|
1142 |
|
1143 if i < len(path)-1 && v.Kind() == reflect.Ptr { |
|
1144 if v.IsNil() { |
|
1145 v.Set(reflect.New(v.Type().Elem())) |
|
1146 } |
|
1147 v = v.Elem() |
|
1148 } |
|
1149 } |
|
1150 return v |
|
1151 } |
|
1152 |
1138 type fieldPathsMap = map[string][]int |
1153 type fieldPathsMap = map[string][]int |
1139 |
1154 |
1140 var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap |
1155 var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap |
1141 |
1156 |
1142 func structFieldPath(v reflect.Value, name string) ([]int, bool) { |
1157 func structFieldPath(v reflect.Value, name string) ([]int, bool) { |
1190 if i := strings.IndexByte(name, ','); i >= 0 { |
1205 if i := strings.IndexByte(name, ','); i >= 0 { |
1191 name = name[:i] |
1206 name = name[:i] |
1192 } |
1207 } |
1193 |
1208 |
1194 if f.Anonymous && name == "" { |
1209 if f.Anonymous && name == "" { |
1195 forEachField(f.Type, fieldPath, do) |
1210 t2 := f.Type |
|
1211 if t2.Kind() == reflect.Ptr { |
|
1212 t2 = t2.Elem() |
|
1213 } |
|
1214 |
|
1215 if t2.Kind() == reflect.Struct { |
|
1216 forEachField(t2, fieldPath, do) |
|
1217 } |
1196 continue |
1218 continue |
1197 } |
1219 } |
1198 |
1220 |
1199 if name == "" { |
1221 if name == "" { |
1200 name = f.Name |
1222 name = f.Name |