@@ -104,33 +104,42 @@ def extract_enum_definitions
104
104
def __extract_function_definitions ( c_kinds :, kind :, is_parse_multiline_definition :)
105
105
stdout = execute_ctags ( "--c-kinds=#{ c_kinds } --fields=+nS --extras=+q" )
106
106
107
- stdout . each_line . with_object ( [ ] ) do |line , definitions |
108
- parts = line . split ( "\t " )
107
+ stdout . each_line . map do |line |
108
+ generate_function_definition_from_line ( line :, kind :, is_parse_multiline_definition :)
109
+ end . compact . uniq ( &:name )
110
+ end
109
111
110
- function_name = parts [ 0 ]
111
- filepath = parts [ 1 ]
112
+ # @param line [String]
113
+ # @param kind [String]
114
+ # @param is_parse_multiline_definition [Boolean]
115
+ #
116
+ # @param [Array<RubyHeaderParser::FunctionDefinition>, nil]
117
+ def generate_function_definition_from_line ( line :, kind :, is_parse_multiline_definition :)
118
+ parts = line . split ( "\t " )
112
119
113
- next unless data . should_generate_function? ( function_name )
120
+ function_name = parts [ 0 ]
121
+ filepath = parts [ 1 ]
114
122
115
- next unless parts [ 3 ] == kind
123
+ return nil unless data . should_generate_function? ( function_name )
116
124
117
- line_num = Util . find_field ( parts , "line" ) . to_i
118
- definition = parse_function_definition ( filepath :, pattern : parts [ 2 ] , line_num :, is_parse_multiline_definition :)
125
+ return nil unless parts [ 3 ] == kind
119
126
120
- args = parse_definition_args ( function_name , Util . find_field ( parts , "signature" ) )
127
+ line_num = Util . find_field ( parts , "line" ) . to_i
128
+ definition = parse_function_definition ( filepath :, pattern : parts [ 2 ] , line_num :, is_parse_multiline_definition :)
121
129
122
- # Exclude functions with variable-length arguments
123
- next if args &.last &.type == "..."
130
+ args = parse_definition_args ( function_name , Util . find_field ( parts , "signature" ) )
124
131
125
- typeref_field = Util . find_field ( parts , "typeref:typename" )
132
+ # Exclude functions with variable-length arguments
133
+ return nil if args &.last &.type == "..."
126
134
127
- definitions << FunctionDefinition . new (
128
- definition :,
129
- name : function_name ,
130
- typeref : create_typeref ( definition :, function_name :, typeref_field :, filepath :, line_num :) ,
131
- args :,
132
- )
133
- end . uniq ( &:name )
135
+ typeref_field = Util . find_field ( parts , "typeref:typename" )
136
+
137
+ FunctionDefinition . new (
138
+ definition :,
139
+ name : function_name ,
140
+ typeref : create_typeref ( definition :, function_name :, typeref_field :, filepath :, line_num :) ,
141
+ args :,
142
+ )
134
143
end
135
144
136
145
# @param args [String]
@@ -272,45 +281,75 @@ def generate_argument_definition(function_name:, arg:, arg_pos:)
272
281
parts . delete_at ( pointer_index )
273
282
end
274
283
275
- pointer = nil
276
- length = 0
284
+ type , pointer , length = analyze_argument_type ( function_name :, arg_pos :, parts :)
277
285
278
- if parts [ -1 ] =~ /\[ ([0-9]+)?\] $/
279
- parts [ -1 ] . gsub! ( /\[ ([0-9]+)?\] $/ , "" )
280
- length = ::Regexp . last_match ( 1 ) . to_i
281
- pointer = :array
282
- end
283
-
284
- unless parts [ -1 ] =~ /^[0-9a-zA-Z_]+$/
285
- # last elements isn't dummy argument
286
- parts << "arg#{ arg_pos } "
287
- end
286
+ ArgumentDefinition . new (
287
+ name : parts [ -1 ] ,
288
+ type :,
289
+ pointer :,
290
+ length :,
291
+ )
292
+ end
288
293
294
+ # @param function_name [String]
295
+ # @param arg_pos [Integer]
296
+ # @param parts [Array<String>]
297
+ #
298
+ # @return [Array<String, Symbol, Integer>]
299
+ # - type [String]
300
+ # - pointer [Symbol]
301
+ # - length [Integer]
302
+ def analyze_argument_type ( function_name :, arg_pos :, parts :)
303
+ pointer , length = prepare_argument_parts ( arg_pos :, parts :)
289
304
original_type = Util . sanitize_type ( parts [ 0 ...-1 ] . join ( " " ) )
290
- name = parts [ -1 ]
291
305
292
- if original_type . match? ( /\* +$/ )
306
+ case original_type
307
+ when /\* +$/
293
308
type = original_type . gsub ( /\* +$/ , "" ) . strip
294
309
pointer = data . function_arg_pointer_hint ( function_name :, pos : arg_pos )
295
- elsif /^void\s *\s / . match? ( original_type ) || /\( .*\) / . match? ( original_type )
310
+
311
+ when /^void\s */ , /\( .*\) /
296
312
# function pointer (e.g. void *(*func)(void *)) is treated as `void*`
297
313
type = "void"
298
314
pointer = data . function_arg_pointer_hint ( function_name :, pos : arg_pos )
315
+
299
316
else
300
317
type = original_type
301
318
end
302
319
303
- if pointer == :sref
304
- original_type =~ /(\* +)$/
305
- length = ::Regexp . last_match ( 1 ) . length
320
+ length = pointer_length ( original_type ) if pointer == :sref
321
+
322
+ [ type , pointer , length ]
323
+ end
324
+
325
+ # @param arg_pos [Integer]
326
+ # @param parts [Array<String>]
327
+ #
328
+ # @return [Array<Symbol, Integer>]
329
+ # - pointer [Symbol,nil]
330
+ # - length [Integer]
331
+ def prepare_argument_parts ( parts :, arg_pos :)
332
+ pointer = nil
333
+ length = 0
334
+
335
+ if parts [ -1 ] =~ /\[ ([0-9]+)?\] $/
336
+ parts [ -1 ] . gsub! ( /\[ ([0-9]+)?\] $/ , "" )
337
+ length = ::Regexp . last_match ( 1 ) . to_i
338
+ pointer = :array
339
+ end
340
+
341
+ unless parts [ -1 ] =~ /^[0-9a-zA-Z_]+$/
342
+ # last elements isn't dummy argument
343
+ parts << "arg#{ arg_pos } "
306
344
end
307
345
308
- ArgumentDefinition . new (
309
- type :,
310
- name :,
311
- pointer :,
312
- length :,
313
- )
346
+ [ pointer , length ]
347
+ end
348
+
349
+ # @param type [String]
350
+ def pointer_length ( type )
351
+ type =~ /(\* +)$/
352
+ ::Regexp . last_match ( 1 ) . length
314
353
end
315
354
end
316
355
end
0 commit comments