@@ -49,13 +49,16 @@ const FIELD_NAMESPACE = "namespace"
4949const FIELD_SKIP = "skipMe"
5050
5151const KIND_PROTOTYPE = "prototype"
52+ const KIND_FUNCTION = "function"
5253const KIND_PROTOTYPE_MODIFIERS = "prototype_modifiers"
5354
5455const TEMPLATE = "template"
5556const STATIC = "static"
57+ const TRUE = "true"
5658
5759var FIELDS = map [string ]bool {"kind" : true , "line" : true , "typeref" : true , "signature" : true , "returntype" : true , "class" : true , "struct" : true , "namespace" : true }
5860var KNOWN_TAG_KINDS = map [string ]bool {"prototype" : true , "function" : true }
61+ var FIELDS_MARKING_UNHANDLED_TAGS = []string {FIELD_CLASS , FIELD_STRUCT , FIELD_NAMESPACE }
5962
6063type CTagsParser struct {
6164 PrototypesField string
@@ -71,22 +74,20 @@ func (s *CTagsParser) Run(context map[string]interface{}) error {
7174 tags = append (tags , parseTag (row ))
7275 }
7376
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
9091 }
9192
9293 prototypes := toPrototypes (tags )
@@ -96,22 +97,83 @@ func (s *CTagsParser) Run(context map[string]interface{}) error {
9697 return nil
9798}
9899
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+
99160func toPrototypes (tags []map [string ]string ) []* types.Prototype {
100161 prototypes := []* types.Prototype {}
101162 for _ , tag := range tags {
102- if tag [FIELD_SKIP ] != "true" {
163+ if tag [FIELD_SKIP ] != TRUE {
103164 ctag := types.Prototype {FunctionName : tag [FIELD_FUNCTION_NAME ], Prototype : tag [KIND_PROTOTYPE ], Modifiers : tag [KIND_PROTOTYPE_MODIFIERS ], Fields : tag }
104165 prototypes = append (prototypes , & ctag )
105166 }
106167 }
107168 return prototypes
108169}
109170
110- func addPrototypes (tags []map [string ]string ) [] map [ string ] string {
171+ func addPrototypes (tags []map [string ]string ) {
111172 for _ , tag := range tags {
112- addPrototype (tag )
173+ if tag [FIELD_SKIP ] != TRUE {
174+ addPrototype (tag )
175+ }
113176 }
114- return tags
115177}
116178
117179func addPrototype (tag map [string ]string ) {
@@ -135,55 +197,53 @@ func addPrototype(tag map[string]string) {
135197 tag [KIND_PROTOTYPE_MODIFIERS ] = strings .TrimSpace (tag [KIND_PROTOTYPE_MODIFIERS ])
136198}
137199
138- func removeDefinedProtypes (tags []map [string ]string ) [] map [ string ] string {
200+ func removeDefinedProtypes (tags []map [string ]string ) {
139201 definedPrototypes := make (map [string ]bool )
140202 for _ , tag := range tags {
141203 if tag [FIELD_KIND ] == KIND_PROTOTYPE {
142204 definedPrototypes [tag [KIND_PROTOTYPE ]] = true
143205 }
144206 }
145207
146- var newTags []map [string ]string
147208 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
150211 }
151212 }
152- return newTags
153213}
154214
155- func removeDuplicate (tags []map [string ]string ) [] map [ string ] string {
215+ func removeDuplicate (tags []map [string ]string ) {
156216 definedPrototypes := make (map [string ]bool )
157217
158- var newTags []map [string ]string
159218 for _ , tag := range tags {
160219 if ! definedPrototypes [tag [KIND_PROTOTYPE ]] {
161- newTags = append (newTags , tag )
162220 definedPrototypes [tag [KIND_PROTOTYPE ]] = true
221+ } else {
222+ tag [FIELD_SKIP ] = TRUE
163223 }
164224 }
165- return newTags
166225}
167226
168227type skipFuncType func (tag map [string ]string ) bool
169228
170- func skipTagsWhere (tags []map [string ]string , skipFuncs ... skipFuncType ) [] map [ string ] string {
229+ func skipTagsWhere (tags []map [string ]string , skipFuncs ... skipFuncType ) {
171230 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 )
175237 }
176- tag [FIELD_SKIP ] = strconv .FormatBool (skip )
177238 }
178- return tags
179239}
180240
181241func signatureContainsDefaultArg (tag map [string ]string ) bool {
182242 return strings .Contains (tag [FIELD_SIGNATURE ], "=" )
183243}
184244
185245func prototypeAndCodeDontMatch (tag map [string ]string ) bool {
186- if tag [FIELD_SKIP ] == "true" {
246+ if tag [FIELD_SKIP ] == TRUE {
187247 return true
188248 }
189249
@@ -204,24 +264,25 @@ func removeSpacesAndTabs(s string) string {
204264 return s
205265}
206266
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 ) {
209268 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
212271 }
213272 }
214- return newTags
215273}
216274
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
222279 }
223280 }
224- return newTags
281+ return false
282+ }
283+
284+ func tagIsUnknown (tag map [string ]string ) bool {
285+ return ! KNOWN_TAG_KINDS [tag [FIELD_KIND ]]
225286}
226287
227288func parseTag (row string ) map [string ]string {
0 commit comments