@@ -49,13 +49,16 @@ const FIELD_NAMESPACE = "namespace"
49
49
const FIELD_SKIP = "skipMe"
50
50
51
51
const KIND_PROTOTYPE = "prototype"
52
+ const KIND_FUNCTION = "function"
52
53
const KIND_PROTOTYPE_MODIFIERS = "prototype_modifiers"
53
54
54
55
const TEMPLATE = "template"
55
56
const STATIC = "static"
57
+ const TRUE = "true"
56
58
57
59
var FIELDS = map [string ]bool {"kind" : true , "line" : true , "typeref" : true , "signature" : true , "returntype" : true , "class" : true , "struct" : true , "namespace" : true }
58
60
var KNOWN_TAG_KINDS = map [string ]bool {"prototype" : true , "function" : true }
61
+ var FIELDS_MARKING_UNHANDLED_TAGS = []string {FIELD_CLASS , FIELD_STRUCT , FIELD_NAMESPACE }
59
62
60
63
type CTagsParser struct {
61
64
PrototypesField string
@@ -71,22 +74,20 @@ func (s *CTagsParser) Run(context map[string]interface{}) error {
71
74
tags = append (tags , parseTag (row ))
72
75
}
73
76
74
- tags = filterOutUnknownTags (tags )
75
- tags = filterOutTagsWithField (tags , FIELD_CLASS )
76
- tags = filterOutTagsWithField (tags , FIELD_STRUCT )
77
- tags = filterOutTagsWithField (tags , FIELD_NAMESPACE )
78
- tags = skipTagsWhere (tags , signatureContainsDefaultArg )
79
- tags = addPrototypes (tags )
80
- tags = removeDefinedProtypes (tags )
81
- tags = removeDuplicate (tags )
82
- tags = skipTagsWhere (tags , prototypeAndCodeDontMatch )
83
-
84
- if len (tags ) > 0 {
85
- line , err := strconv .Atoi (tags [0 ][FIELD_LINE ])
86
- if err != nil {
87
- return utils .WrapError (err )
88
- }
89
- context [constants .CTX_FIRST_FUNCTION_AT_LINE ] = line
77
+ skipTagsWhere (tags , tagIsUnknown )
78
+ skipTagsWithField (tags , FIELDS_MARKING_UNHANDLED_TAGS )
79
+ skipTagsWhere (tags , signatureContainsDefaultArg )
80
+ addPrototypes (tags )
81
+ removeDefinedProtypes (tags )
82
+ removeDuplicate (tags )
83
+ skipTagsWhere (tags , prototypeAndCodeDontMatch )
84
+
85
+ lineWhereToInsertPrototypes , err := findLineWhereToInsertPrototypes (tags )
86
+ if err != nil {
87
+ return utils .WrapError (err )
88
+ }
89
+ if lineWhereToInsertPrototypes != - 1 {
90
+ context [constants .CTX_LINE_WHERE_TO_INSERT_PROTOTYPES ] = lineWhereToInsertPrototypes
90
91
}
91
92
92
93
prototypes := toPrototypes (tags )
@@ -96,22 +97,83 @@ func (s *CTagsParser) Run(context map[string]interface{}) error {
96
97
return nil
97
98
}
98
99
100
+ func findLineWhereToInsertPrototypes (tags []map [string ]string ) (int , error ) {
101
+ firstFunctionLine , err := firstFunctionAtLine (tags )
102
+ if err != nil {
103
+ return - 1 , utils .WrapError (err )
104
+ }
105
+ firstFunctionPointerAsArgument , err := firstFunctionPointerUsedAsArgument (tags )
106
+ if err != nil {
107
+ return - 1 , utils .WrapError (err )
108
+ }
109
+ if firstFunctionLine != - 1 && firstFunctionPointerAsArgument != - 1 {
110
+ if firstFunctionLine < firstFunctionPointerAsArgument {
111
+ return firstFunctionLine , nil
112
+ } else {
113
+ return firstFunctionPointerAsArgument , nil
114
+ }
115
+ } else if firstFunctionLine == - 1 {
116
+ return firstFunctionPointerAsArgument , nil
117
+ } else {
118
+ return firstFunctionLine , nil
119
+ }
120
+ }
121
+
122
+ func firstFunctionPointerUsedAsArgument (tags []map [string ]string ) (int , error ) {
123
+ functionNames := collectFunctionNames (tags )
124
+ for _ , tag := range tags {
125
+ if functionNameUsedAsFunctionPointerIn (tag , functionNames ) {
126
+ return strconv .Atoi (tag [FIELD_LINE ])
127
+ }
128
+ }
129
+ return - 1 , nil
130
+ }
131
+
132
+ func functionNameUsedAsFunctionPointerIn (tag map [string ]string , functionNames []string ) bool {
133
+ for _ , functionName := range functionNames {
134
+ if strings .Index (tag [FIELD_CODE ], "&" + functionName ) != - 1 {
135
+ return true
136
+ }
137
+ }
138
+ return false
139
+ }
140
+
141
+ func collectFunctionNames (tags []map [string ]string ) []string {
142
+ names := []string {}
143
+ for _ , tag := range tags {
144
+ if tag [FIELD_KIND ] == KIND_FUNCTION {
145
+ names = append (names , tag [FIELD_FUNCTION_NAME ])
146
+ }
147
+ }
148
+ return names
149
+ }
150
+
151
+ func firstFunctionAtLine (tags []map [string ]string ) (int , error ) {
152
+ for _ , tag := range tags {
153
+ if ! tagIsUnknown (tag ) && ! tagHasAtLeastOneField (tag , FIELDS_MARKING_UNHANDLED_TAGS ) && tag [FIELD_KIND ] == KIND_FUNCTION {
154
+ return strconv .Atoi (tag [FIELD_LINE ])
155
+ }
156
+ }
157
+ return - 1 , nil
158
+ }
159
+
99
160
func toPrototypes (tags []map [string ]string ) []* types.Prototype {
100
161
prototypes := []* types.Prototype {}
101
162
for _ , tag := range tags {
102
- if tag [FIELD_SKIP ] != "true" {
163
+ if tag [FIELD_SKIP ] != TRUE {
103
164
ctag := types.Prototype {FunctionName : tag [FIELD_FUNCTION_NAME ], Prototype : tag [KIND_PROTOTYPE ], Modifiers : tag [KIND_PROTOTYPE_MODIFIERS ], Fields : tag }
104
165
prototypes = append (prototypes , & ctag )
105
166
}
106
167
}
107
168
return prototypes
108
169
}
109
170
110
- func addPrototypes (tags []map [string ]string ) [] map [ string ] string {
171
+ func addPrototypes (tags []map [string ]string ) {
111
172
for _ , tag := range tags {
112
- addPrototype (tag )
173
+ if tag [FIELD_SKIP ] != TRUE {
174
+ addPrototype (tag )
175
+ }
113
176
}
114
- return tags
115
177
}
116
178
117
179
func addPrototype (tag map [string ]string ) {
@@ -135,55 +197,53 @@ func addPrototype(tag map[string]string) {
135
197
tag [KIND_PROTOTYPE_MODIFIERS ] = strings .TrimSpace (tag [KIND_PROTOTYPE_MODIFIERS ])
136
198
}
137
199
138
- func removeDefinedProtypes (tags []map [string ]string ) [] map [ string ] string {
200
+ func removeDefinedProtypes (tags []map [string ]string ) {
139
201
definedPrototypes := make (map [string ]bool )
140
202
for _ , tag := range tags {
141
203
if tag [FIELD_KIND ] == KIND_PROTOTYPE {
142
204
definedPrototypes [tag [KIND_PROTOTYPE ]] = true
143
205
}
144
206
}
145
207
146
- var newTags []map [string ]string
147
208
for _ , tag := range tags {
148
- if ! definedPrototypes [tag [KIND_PROTOTYPE ]] {
149
- newTags = append ( newTags , tag )
209
+ if definedPrototypes [tag [KIND_PROTOTYPE ]] {
210
+ tag [ FIELD_SKIP ] = TRUE
150
211
}
151
212
}
152
- return newTags
153
213
}
154
214
155
- func removeDuplicate (tags []map [string ]string ) [] map [ string ] string {
215
+ func removeDuplicate (tags []map [string ]string ) {
156
216
definedPrototypes := make (map [string ]bool )
157
217
158
- var newTags []map [string ]string
159
218
for _ , tag := range tags {
160
219
if ! definedPrototypes [tag [KIND_PROTOTYPE ]] {
161
- newTags = append (newTags , tag )
162
220
definedPrototypes [tag [KIND_PROTOTYPE ]] = true
221
+ } else {
222
+ tag [FIELD_SKIP ] = TRUE
163
223
}
164
224
}
165
- return newTags
166
225
}
167
226
168
227
type skipFuncType func (tag map [string ]string ) bool
169
228
170
- func skipTagsWhere (tags []map [string ]string , skipFuncs ... skipFuncType ) [] map [ string ] string {
229
+ func skipTagsWhere (tags []map [string ]string , skipFuncs ... skipFuncType ) {
171
230
for _ , tag := range tags {
172
- skip := skipFuncs [0 ](tag )
173
- for _ , skipFunc := range skipFuncs [1 :] {
174
- skip = skip || skipFunc (tag )
231
+ if tag [FIELD_SKIP ] != TRUE {
232
+ skip := skipFuncs [0 ](tag )
233
+ for _ , skipFunc := range skipFuncs [1 :] {
234
+ skip = skip || skipFunc (tag )
235
+ }
236
+ tag [FIELD_SKIP ] = strconv .FormatBool (skip )
175
237
}
176
- tag [FIELD_SKIP ] = strconv .FormatBool (skip )
177
238
}
178
- return tags
179
239
}
180
240
181
241
func signatureContainsDefaultArg (tag map [string ]string ) bool {
182
242
return strings .Contains (tag [FIELD_SIGNATURE ], "=" )
183
243
}
184
244
185
245
func prototypeAndCodeDontMatch (tag map [string ]string ) bool {
186
- if tag [FIELD_SKIP ] == "true" {
246
+ if tag [FIELD_SKIP ] == TRUE {
187
247
return true
188
248
}
189
249
@@ -204,24 +264,25 @@ func removeSpacesAndTabs(s string) string {
204
264
return s
205
265
}
206
266
207
- func filterOutTagsWithField (tags []map [string ]string , field string ) []map [string ]string {
208
- var newTags []map [string ]string
267
+ func skipTagsWithField (tags []map [string ]string , fields []string ) {
209
268
for _ , tag := range tags {
210
- if tag [ field ] == constants . EMPTY_STRING {
211
- newTags = append ( newTags , tag )
269
+ if tagHasAtLeastOneField ( tag , fields ) {
270
+ tag [ FIELD_SKIP ] = TRUE
212
271
}
213
272
}
214
- return newTags
215
273
}
216
274
217
- func filterOutUnknownTags (tags []map [string ]string ) []map [string ]string {
218
- var newTags []map [string ]string
219
- for _ , tag := range tags {
220
- if KNOWN_TAG_KINDS [tag [FIELD_KIND ]] {
221
- newTags = append (newTags , tag )
275
+ func tagHasAtLeastOneField (tag map [string ]string , fields []string ) bool {
276
+ for _ , field := range fields {
277
+ if tag [field ] != constants .EMPTY_STRING {
278
+ return true
222
279
}
223
280
}
224
- return newTags
281
+ return false
282
+ }
283
+
284
+ func tagIsUnknown (tag map [string ]string ) bool {
285
+ return ! KNOWN_TAG_KINDS [tag [FIELD_KIND ]]
225
286
}
226
287
227
288
func parseTag (row string ) map [string ]string {
0 commit comments