2
2
3
3
module RubyHeaderParser
4
4
# parse `ruby.h` using `ctags`
5
- class Parser
5
+ class Parser # rubocop:disable Metrics/ClassLength
6
6
# @!attribute [r] header_dir
7
7
# @return [String]
8
8
attr_reader :header_dir
@@ -19,43 +19,17 @@ def initialize(header_dir)
19
19
20
20
# @return [Array<RubyHeaderParser::FunctionDefinition>]
21
21
def extract_function_definitions
22
- stdout = `ctags --recurse --c-kinds=p --languages=C --language-force=C --fields=+nS --extras=+q -f - #{ header_dir } ` # rubocop:disable Layout/LineLength
23
-
24
- stdout . each_line . with_object ( [ ] ) do |line , definitions |
25
- parts = line . split ( "\t " )
26
-
27
- function_name = parts [ 0 ]
28
-
29
- next unless data . should_generate_function? ( function_name )
30
-
31
- definition =
32
- if parts [ 2 ] . end_with? ( ";$/;\" " )
33
- parts [ 2 ] . delete_prefix ( "/^" ) . delete_suffix ( ";$/;\" " )
34
- else
35
- line_num = Util . find_field ( parts , "line" ) . to_i
36
- read_definition_from_header_file ( parts [ 1 ] , line_num ) . delete_suffix ( ";" )
37
- end
38
-
39
- definition . gsub! ( /\) ;.*/ , ")" )
40
-
41
- args = parse_definition_args ( function_name , Util . find_field ( parts , "signature" ) )
42
-
43
- # Exclude functions with variable-length arguments
44
- next if args &.last &.type == "..."
22
+ __extract_function_definitions ( c_kinds : "p" , is_parse_multiline_definition : true )
23
+ end
45
24
46
- definitions << FunctionDefinition . new (
47
- definition :,
48
- name : parts [ 0 ] ,
49
- filepath : parts [ 1 ] ,
50
- typeref : create_typeref ( definition , function_name ) ,
51
- args :,
52
- )
53
- end
25
+ # @return [Array<RubyHeaderParser::FunctionDefinition>]
26
+ def extract_static_inline_function_definitions
27
+ __extract_function_definitions ( c_kinds : "+p-d" , is_parse_multiline_definition : false )
54
28
end
55
29
56
30
# @return [Array<RubyHeaderParser::StructDefinition>]
57
31
def extract_struct_definitions
58
- stdout = `ctags --recurse -- c-kinds=s --languages=C --language-force=C -- fields=+n -f - #{ header_dir } `
32
+ stdout = execute_ctags ( "-- c-kinds=s --fields=+n" )
59
33
60
34
stdout . each_line . with_object ( [ ] ) do |line , definitions |
61
35
parts = line . split ( "\t " )
@@ -73,7 +47,7 @@ def extract_struct_definitions
73
47
74
48
# @return [Array<RubyHeaderParser::TyperefDefinition>]
75
49
def extract_type_definitions
76
- stdout = `ctags --recurse -- c-kinds=t --languages=C --language-force=C -- fields=+n -f - #{ header_dir } `
50
+ stdout = execute_ctags ( "-- c-kinds=t --fields=+n" )
77
51
78
52
stdout . each_line . with_object ( [ ] ) do |line , definitions |
79
53
parts = line . split ( "\t " )
@@ -91,6 +65,46 @@ def extract_type_definitions
91
65
92
66
private
93
67
68
+ # @param c_kinds [String]
69
+ # @param is_parse_multiline_definition [Boolean]
70
+ # @return [Array<RubyHeaderParser::FunctionDefinition>]
71
+ def __extract_function_definitions ( c_kinds :, is_parse_multiline_definition :)
72
+ stdout = execute_ctags ( "--c-kinds=#{ c_kinds } --fields=+nS --extras=+q" )
73
+
74
+ stdout . each_line . with_object ( [ ] ) do |line , definitions |
75
+ parts = line . split ( "\t " )
76
+
77
+ function_name = parts [ 0 ]
78
+
79
+ next unless data . should_generate_function? ( function_name )
80
+
81
+ line_num = Util . find_field ( parts , "line" ) . to_i
82
+ definition =
83
+ parse_function_definition ( filepath : parts [ 1 ] , pattern : parts [ 2 ] , line_num :, is_parse_multiline_definition :)
84
+
85
+ args = parse_definition_args ( function_name , Util . find_field ( parts , "signature" ) )
86
+
87
+ # Exclude functions with variable-length arguments
88
+ next if args &.last &.type == "..."
89
+
90
+ typeref_field = Util . find_field ( parts , "typeref:typename" )
91
+
92
+ definitions << FunctionDefinition . new (
93
+ definition :,
94
+ name : parts [ 0 ] ,
95
+ filepath : parts [ 1 ] ,
96
+ typeref : create_typeref ( definition :, function_name :, typeref_field :) ,
97
+ args :,
98
+ )
99
+ end
100
+ end
101
+
102
+ # @param args [String]
103
+ # @return [String]
104
+ def execute_ctags ( args = "" )
105
+ `ctags --recurse --languages=C --language-force=C #{ args } -f - #{ header_dir } `
106
+ end
107
+
94
108
# @param file [String]
95
109
# @param line_num [Integer]
96
110
def read_definition_from_header_file ( file , line_num )
@@ -107,6 +121,24 @@ def read_definition_from_header_file(file, line_num)
107
121
""
108
122
end
109
123
124
+ # @param filepath [String]
125
+ # @param pattern [String]
126
+ # @param line_num [Integer]
127
+ # @param is_parse_multiline_definition [Boolean]
128
+ # @return [String]
129
+ def parse_function_definition ( filepath :, pattern :, line_num :, is_parse_multiline_definition :)
130
+ definition =
131
+ if pattern . end_with? ( "$/;\" " )
132
+ pattern . delete_prefix ( "/^" ) . delete_suffix ( "$/;\" " )
133
+ elsif is_parse_multiline_definition
134
+ read_definition_from_header_file ( filepath , line_num )
135
+ else
136
+ pattern . delete_prefix ( "/^" )
137
+ end
138
+
139
+ definition . delete_suffix ( ";" )
140
+ end
141
+
110
142
# @param function_name [String]
111
143
# @param signature [String,nil]
112
144
# @return [Array<RubyHeaderParser::ArgumentDefinition>]
@@ -176,10 +208,17 @@ def parse_definition_args(function_name, signature)
176
208
177
209
# @param definition [String]
178
210
# @param function_name [String]
211
+ # @param typeref_field [String,nil]
179
212
# @return [RubyHeaderParser::TyperefDefinition]
180
- def create_typeref ( definition , function_name )
181
- typeref_type = definition [ 0 ...definition . index ( function_name ) ] . gsub ( "char *" , "char*" ) . strip
182
- typeref_type = Util . sanitize_type ( typeref_type )
213
+ def create_typeref ( definition :, function_name :, typeref_field :)
214
+ typeref_type =
215
+ if typeref_field
216
+ typeref_field . gsub ( /^RBIMPL_ATTR_NONNULL\s *\( \( \) \) / , "" ) . strip
217
+ else
218
+ # parse typeref in definition
219
+ type = definition [ 0 ...definition . index ( function_name ) ] . gsub ( "char *" , "char*" ) . strip
220
+ Util . sanitize_type ( type )
221
+ end
183
222
184
223
typeref_pointer = nil
185
224
if typeref_type . match? ( /\* +$/ )
0 commit comments