-
Notifications
You must be signed in to change notification settings - Fork 5
/
struct.go
127 lines (101 loc) · 2.68 KB
/
struct.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package gen
import (
"fmt"
"strings"
"github.com/go-clang/bootstrap/clang"
)
// Struct represents a generation struct.
type Struct struct {
IncludeFiles
api *API
Name string
CName string
CNameIsTypeDef bool
Receiver Receiver
Comment string
IsPointerComposition bool
Fields []*StructField
Methods []interface{}
}
// StructField field of Struct.
type StructField struct {
CName string
Comment string
Type Type
}
// HandleStructCursor handles the struct cursor.
func HandleStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
s := &Struct{
IncludeFiles: NewIncludeFiles(),
Name: TrimLanguagePrefix(cname),
CName: cname,
CNameIsTypeDef: cnameIsTypeDef,
}
s.Comment = CleanDoxygenComment(s.Name, cursor.RawCommentText())
s.Receiver.Name = CommonReceiverName(s.Name)
cursor.Visit(func(cursor, _ clang.Cursor) clang.ChildVisitResult {
switch cursor.Kind() {
case clang.Cursor_FieldDecl:
typ, err := TypeFromClangType(cursor.Type())
if err != nil {
panic(fmt.Errorf("unexpected error: %w, cursor.Type(): %#v", err, cursor.Type()))
}
if typ.IsFunctionPointer {
return clang.ChildVisit_Continue
}
field := &StructField{
CName: cursor.DisplayName(),
Type: typ,
}
field.Comment = CleanDoxygenComment(TrimCommonFunctionName(field.CName, typ), cursor.RawCommentText())
s.Fields = append(s.Fields, field)
}
return clang.ChildVisit_Continue
})
return s
}
// ContainsMethod reports whether the contains name in Struct.
func (s *Struct) ContainsMethod(name string) bool {
for _, m := range s.Methods {
switch m := m.(type) {
case *Function:
if m.Name == name {
return true
}
case string:
if strings.Contains(m, ") "+name+"()") {
return true
}
}
}
return false
}
// Generate generates the struct.
func (s *Struct) Generate() error {
f := NewFile(strings.ToLower(s.Name))
f.Structs = append(f.Structs, s)
return f.Generate()
}
// AddFieldGetters adds field getters to s.
func (s *Struct) AddFieldGetters() error {
if s.api.PrepareStructFields != nil {
s.api.PrepareStructFields(s)
}
// generate the getters we can handle
for _, m := range s.Fields {
if s.api.FilterStructFieldGetter != nil && !s.api.FilterStructFieldGetter(m) {
continue
}
if m.Type.CGoName == "void" || m.Type.CGoName == "uintptr_t" {
continue
}
if m.Type.IsArray { // TODO(go-clang): generate arrays with the correct size and type https://github.com/go-clang/gen/issues/48
continue
}
f := NewFunction(m.CName, s.CName, m.Comment, m.CName, m.Type)
if !s.ContainsMethod(f.Name) {
s.Methods = append(s.Methods, f)
}
}
return nil
}