-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathfields.go
87 lines (78 loc) · 2.26 KB
/
fields.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright 2017 Walter Schulze
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
package derive
import (
"go/types"
"strings"
)
// Named describes a named struct with a list of fields.
type Named struct {
Fields []*Field
Reflect bool
}
// Field describes a struct field.
type Field struct {
name string
external bool
Type types.Type
typeStr func() string
}
// Name returns the field name, given the receiver and the unsafe import, if needed.
func (f *Field) Name(recv string, unsafePkg Import) string {
if !f.Private() || !f.external {
return recv + "." + f.name
}
return `*(*` + f.typeStr() + `)(` + unsafePkg() + `.Pointer(` + recv + `.FieldByName("` + f.name + `").UnsafeAddr()))`
}
// DebugName simply returns the field name, without the receiver or any unsafe magic.
func (f *Field) DebugName() string {
return f.name
}
// Private whether the field is private
func (f *Field) Private() bool {
return strings.ToLower(f.name[0:1]) == f.name[0:1]
}
// Fields returns a new Named object containing a list of Fields for a given input struct.
func Fields(typesMap TypesMap, typ *types.Struct, external bool) *Named {
numFields := typ.NumFields()
n := &Named{
Fields: make([]*Field, numFields),
}
for i := 0; i < numFields; i++ {
field := typ.Field(i)
fieldType := field.Type()
fieldName := field.Name()
n.Fields[i] = &Field{
name: fieldName,
external: external,
Type: fieldType,
typeStr: func() string {
return typesMap.TypeString(fieldType)
},
}
if n.Fields[i].Private() {
if external {
n.Reflect = true
}
}
}
return n
}
func GetStructFields(s *types.Struct) []*types.Var {
fields := make([]*types.Var, s.NumFields())
for i := 0; i < s.NumFields(); i++ {
fields[i] = s.Field(i)
}
return fields
}