ruby_header_parser 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +55 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +5 -0
- data/CONFIG.md +126 -0
- data/LICENSE.txt +21 -0
- data/README.md +67 -0
- data/Rakefile +30 -0
- data/Steepfile +33 -0
- data/config/default.yml +170 -0
- data/lib/ruby_header_parser/argument_definition.rb +45 -0
- data/lib/ruby_header_parser/config.rb +77 -0
- data/lib/ruby_header_parser/enum_definition.rb +27 -0
- data/lib/ruby_header_parser/function_definition.rb +40 -0
- data/lib/ruby_header_parser/parser.rb +376 -0
- data/lib/ruby_header_parser/struct_definition.rb +21 -0
- data/lib/ruby_header_parser/type_definition.rb +21 -0
- data/lib/ruby_header_parser/typeref_definition.rb +32 -0
- data/lib/ruby_header_parser/util.rb +29 -0
- data/lib/ruby_header_parser/version.rb +5 -0
- data/lib/ruby_header_parser.rb +21 -0
- data/rbs_collection.lock.yaml +116 -0
- data/rbs_collection.yaml +26 -0
- data/sig/ruby_header_parser/argument_definition.rbs +14 -0
- data/sig/ruby_header_parser/config.rbs +19 -0
- data/sig/ruby_header_parser/enum_definition.rbs +10 -0
- data/sig/ruby_header_parser/function_definition.rbs +12 -0
- data/sig/ruby_header_parser/parser.rbs +84 -0
- data/sig/ruby_header_parser/struct_definition.rbs +9 -0
- data/sig/ruby_header_parser/type_definition.rbs +9 -0
- data/sig/ruby_header_parser/typeref_definition.rbs +12 -0
- data/sig/ruby_header_parser/util.rbs +9 -0
- data/sig/ruby_header_parser.rbs +7 -0
- metadata +207 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyHeaderParser
|
4
|
+
# function definition in header file
|
5
|
+
class FunctionDefinition
|
6
|
+
# @!attribute name
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @!attribute definition
|
11
|
+
# @return [String]
|
12
|
+
attr_accessor :definition
|
13
|
+
|
14
|
+
# @!attribute typeref
|
15
|
+
# @return [TyperefDefinition]
|
16
|
+
attr_accessor :typeref
|
17
|
+
|
18
|
+
# @!attribute args
|
19
|
+
# @return [Array<ArgumentDefinition>]
|
20
|
+
attr_accessor :args
|
21
|
+
|
22
|
+
# @param name [String]
|
23
|
+
# @param definition [String]
|
24
|
+
# @param typeref [TyperefDefinition]
|
25
|
+
# @param args [Array<ArgumentDefinition>]
|
26
|
+
def initialize(name:, definition:, typeref:, args:)
|
27
|
+
@name = name
|
28
|
+
@definition = definition
|
29
|
+
@typeref = typeref
|
30
|
+
@args = args
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param other [FunctionDefinition]
|
34
|
+
# @return [Boolean]
|
35
|
+
def ==(other)
|
36
|
+
other.is_a?(FunctionDefinition) && name == other.name && definition == other.definition &&
|
37
|
+
typeref == other.typeref && args == other.args
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,376 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyHeaderParser
|
4
|
+
# parse `ruby.h` using `ctags`
|
5
|
+
class Parser # rubocop:disable Metrics/ClassLength
|
6
|
+
# @!attribute [r] header_file
|
7
|
+
# @return [String]
|
8
|
+
attr_reader :header_file
|
9
|
+
|
10
|
+
# @!attribute [r] include_paths
|
11
|
+
# @return [Array<String>]
|
12
|
+
attr_reader :include_paths
|
13
|
+
|
14
|
+
# @!attribute [r] dist_preprocessed_header_file
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :dist_preprocessed_header_file
|
17
|
+
|
18
|
+
# @!attribute [r] data
|
19
|
+
# @return [RubyHeaderParser::Config]
|
20
|
+
attr_reader :config
|
21
|
+
|
22
|
+
DEFAULT_HEADER_FILE = "#{RbConfig::CONFIG["rubyhdrdir"]}/ruby.h".freeze
|
23
|
+
|
24
|
+
DEFAULT_INCLUDE_PATHS = [
|
25
|
+
RbConfig::CONFIG["rubyarchhdrdir"],
|
26
|
+
RbConfig::CONFIG["rubyhdrdir"],
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
# @param header_file [String] Path to `ruby.h`
|
30
|
+
# @param include_paths [Array<String>]
|
31
|
+
# @param dist_preprocessed_header_file [String,nil] Destination path to the output of preprocessed ruby.h.
|
32
|
+
# (default: `"#{Dir.tmpdir}/ruby_preprocessed.h"`)
|
33
|
+
# @param config_file [String,nil] Path to config file (default: `config/default.yml`)
|
34
|
+
#
|
35
|
+
# @note `dist_preprocessed_header_file` is used as the output destination for temporary files when the parser
|
36
|
+
# is executed
|
37
|
+
#
|
38
|
+
# @note See [CONFIG.md](../file.CONFIG.html) for config file details
|
39
|
+
def initialize(dist_preprocessed_header_file: nil, header_file: DEFAULT_HEADER_FILE,
|
40
|
+
include_paths: DEFAULT_INCLUDE_PATHS, config_file: nil)
|
41
|
+
@header_file = header_file
|
42
|
+
@include_paths = include_paths
|
43
|
+
@dist_preprocessed_header_file = dist_preprocessed_header_file || File.join(Dir.tmpdir, "ruby_preprocessed.h")
|
44
|
+
|
45
|
+
config_file ||= File.expand_path("../../config/default.yml", __dir__.to_s)
|
46
|
+
@config = Config.new(config_file)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Array<RubyHeaderParser::FunctionDefinition>]
|
50
|
+
def extract_function_definitions
|
51
|
+
__extract_function_definitions(c_kinds: "p", kind: "p", is_parse_multiline_definition: true)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Array<RubyHeaderParser::FunctionDefinition>]
|
55
|
+
def extract_static_inline_function_definitions
|
56
|
+
__extract_function_definitions(c_kinds: "+p-d", kind: "f", is_parse_multiline_definition: false)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Array<RubyHeaderParser::StructDefinition>]
|
60
|
+
def extract_struct_definitions
|
61
|
+
stdout = execute_ctags("--c-kinds=s --fields=+n")
|
62
|
+
|
63
|
+
stdout.each_line.with_object([]) do |line, definitions|
|
64
|
+
parts = line.split("\t")
|
65
|
+
|
66
|
+
struct_name = parts[0]
|
67
|
+
next unless config.should_generate_struct?(struct_name)
|
68
|
+
|
69
|
+
definitions << StructDefinition.new(
|
70
|
+
name: struct_name,
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Array<RubyHeaderParser::TyperefDefinition>]
|
76
|
+
def extract_type_definitions
|
77
|
+
stdout = execute_ctags("--c-kinds=t --fields=+n")
|
78
|
+
|
79
|
+
stdout.each_line.with_object([]) do |line, definitions|
|
80
|
+
parts = line.split("\t")
|
81
|
+
|
82
|
+
type_name = parts[0]
|
83
|
+
|
84
|
+
next unless config.should_generate_type?(type_name)
|
85
|
+
|
86
|
+
definitions << TypeDefinition.new(
|
87
|
+
name: type_name,
|
88
|
+
)
|
89
|
+
end.uniq(&:name)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Array<RubyHeaderParser::EnumDefinition>]
|
93
|
+
def extract_enum_definitions
|
94
|
+
stdout = execute_ctags("--c-kinds=e --fields=+n")
|
95
|
+
|
96
|
+
name_to_definitions =
|
97
|
+
stdout.each_line.with_object({}) do |line, hash|
|
98
|
+
parts = line.split("\t")
|
99
|
+
|
100
|
+
enum_name = Util.find_field(parts, "enum")
|
101
|
+
next unless enum_name
|
102
|
+
|
103
|
+
value = parts[0]
|
104
|
+
|
105
|
+
next unless config.should_generate_enum?(enum_name)
|
106
|
+
|
107
|
+
hash[enum_name] ||= EnumDefinition.new(name: enum_name)
|
108
|
+
hash[enum_name].values << value
|
109
|
+
end
|
110
|
+
|
111
|
+
name_to_definitions.values
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
# @param c_kinds [String]
|
117
|
+
# @param kind [String]
|
118
|
+
# @param is_parse_multiline_definition [Boolean]
|
119
|
+
# @return [Array<RubyHeaderParser::FunctionDefinition>]
|
120
|
+
def __extract_function_definitions(c_kinds:, kind:, is_parse_multiline_definition:)
|
121
|
+
stdout = execute_ctags("--c-kinds=#{c_kinds} --fields=+nS --extras=+q")
|
122
|
+
|
123
|
+
stdout.each_line.map do |line|
|
124
|
+
generate_function_definition_from_line(line:, kind:, is_parse_multiline_definition:)
|
125
|
+
end.compact.uniq(&:name)
|
126
|
+
end
|
127
|
+
|
128
|
+
# @param line [String]
|
129
|
+
# @param kind [String]
|
130
|
+
# @param is_parse_multiline_definition [Boolean]
|
131
|
+
#
|
132
|
+
# @return [RubyHeaderParser::FunctionDefinition, nil]
|
133
|
+
def generate_function_definition_from_line(line:, kind:, is_parse_multiline_definition:)
|
134
|
+
parts = line.split("\t")
|
135
|
+
|
136
|
+
function_name = parts[0]
|
137
|
+
filepath = parts[1]
|
138
|
+
|
139
|
+
return nil unless config.should_generate_function?(function_name)
|
140
|
+
|
141
|
+
return nil unless parts[3] == kind
|
142
|
+
|
143
|
+
line_num = Util.find_field(parts, "line").to_i
|
144
|
+
definition = parse_function_definition(filepath:, pattern: parts[2], line_num:, is_parse_multiline_definition:)
|
145
|
+
|
146
|
+
args = parse_definition_args(function_name, Util.find_field(parts, "signature"))
|
147
|
+
|
148
|
+
# Exclude functions with variable-length arguments
|
149
|
+
return nil if args&.last&.type == "..."
|
150
|
+
|
151
|
+
typeref_field = Util.find_field(parts, "typeref:typename")
|
152
|
+
|
153
|
+
FunctionDefinition.new(
|
154
|
+
definition:,
|
155
|
+
name: function_name,
|
156
|
+
typeref: create_typeref(definition:, function_name:, typeref_field:, filepath:, line_num:),
|
157
|
+
args:,
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
161
|
+
# @param args [String]
|
162
|
+
# @return [String]
|
163
|
+
def execute_ctags(args = "")
|
164
|
+
unless File.exist?(dist_preprocessed_header_file)
|
165
|
+
include_args = include_paths.map { |path| "-I #{path}" }.join(" ")
|
166
|
+
system("gcc -E #{include_args} #{header_file} -o #{dist_preprocessed_header_file}", exception: true)
|
167
|
+
end
|
168
|
+
|
169
|
+
`ctags --languages=C --language-force=C #{args} -f - #{dist_preprocessed_header_file}`
|
170
|
+
end
|
171
|
+
|
172
|
+
# @param file [String]
|
173
|
+
# @param line_num [Integer]
|
174
|
+
def read_definition_from_header_file(file, line_num)
|
175
|
+
definition = +""
|
176
|
+
|
177
|
+
File.open(file, "r") do |f|
|
178
|
+
f.each_with_index do |line, index|
|
179
|
+
if index + 1 >= line_num
|
180
|
+
definition << line.strip
|
181
|
+
return definition if definition.end_with?(");")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
""
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param filepath [String]
|
189
|
+
# @param pattern [String]
|
190
|
+
# @param line_num [Integer]
|
191
|
+
# @param is_parse_multiline_definition [Boolean]
|
192
|
+
# @return [String]
|
193
|
+
def parse_function_definition(filepath:, pattern:, line_num:, is_parse_multiline_definition:)
|
194
|
+
definition =
|
195
|
+
if pattern.end_with?("$/;\"")
|
196
|
+
pattern.delete_prefix("/^").delete_suffix("$/;\"")
|
197
|
+
elsif is_parse_multiline_definition
|
198
|
+
read_definition_from_header_file(filepath, line_num)
|
199
|
+
else
|
200
|
+
pattern.delete_prefix("/^")
|
201
|
+
end
|
202
|
+
|
203
|
+
definition.strip.delete_suffix(";")
|
204
|
+
end
|
205
|
+
|
206
|
+
# @param function_name [String]
|
207
|
+
# @param signature [String,nil]
|
208
|
+
# @return [Array<RubyHeaderParser::ArgumentDefinition>]
|
209
|
+
def parse_definition_args(function_name, signature)
|
210
|
+
return [] unless signature
|
211
|
+
|
212
|
+
signature = signature.strip.delete_prefix("(").delete_suffix(")")
|
213
|
+
return [] if signature.match?(/^void$/i)
|
214
|
+
|
215
|
+
args = Util.split_signature(signature)
|
216
|
+
|
217
|
+
arg_pos = 0
|
218
|
+
args.map do |arg|
|
219
|
+
arg_pos += 1
|
220
|
+
generate_argument_definition(function_name:, arg:, arg_pos:)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# @param definition [String]
|
225
|
+
# @param function_name [String]
|
226
|
+
# @param typeref_field [String,nil]
|
227
|
+
# @param filepath [String]
|
228
|
+
# @param line_num [Integer]
|
229
|
+
# @return [RubyHeaderParser::TyperefDefinition]
|
230
|
+
def create_typeref(definition:, function_name:, typeref_field:, filepath:, line_num:)
|
231
|
+
typeref_type = parse_typeref_type(definition:, function_name:, typeref_field:, filepath:, line_num:)
|
232
|
+
|
233
|
+
typeref_pointer = nil
|
234
|
+
if typeref_type.match?(/\*+$/)
|
235
|
+
typeref_type = typeref_type.gsub(/\*+$/, "").strip
|
236
|
+
typeref_pointer = config.function_self_pointer_hint(function_name)
|
237
|
+
end
|
238
|
+
|
239
|
+
TyperefDefinition.new(type: typeref_type, pointer: typeref_pointer)
|
240
|
+
end
|
241
|
+
|
242
|
+
# @param definition [String]
|
243
|
+
# @param function_name [String]
|
244
|
+
# @param typeref_field [String,nil]
|
245
|
+
# @param filepath [String]
|
246
|
+
# @param line_num [Integer]
|
247
|
+
# @return [String]
|
248
|
+
def parse_typeref_type(definition:, function_name:, typeref_field:, filepath:, line_num:)
|
249
|
+
typeref_type =
|
250
|
+
if typeref_field
|
251
|
+
typeref_field.gsub(/[A-Z_]+\s*\(\(.*\)\)/, "")
|
252
|
+
else
|
253
|
+
# parse typeref in definition
|
254
|
+
type = definition[0...definition.index(function_name)] || ""
|
255
|
+
type.gsub("char *", "char*").strip
|
256
|
+
end
|
257
|
+
|
258
|
+
typeref_type = Util.sanitize_type(typeref_type)
|
259
|
+
return typeref_type unless typeref_type.empty?
|
260
|
+
|
261
|
+
# Check prev line
|
262
|
+
line = read_file_line(filepath:, line_num: line_num - 1)
|
263
|
+
return Util.sanitize_type(line) if line
|
264
|
+
|
265
|
+
""
|
266
|
+
end
|
267
|
+
|
268
|
+
# @param filepath [String]
|
269
|
+
# @param line_num [Integer]
|
270
|
+
def read_file_line(filepath:, line_num:)
|
271
|
+
return nil if line_num < 1
|
272
|
+
|
273
|
+
lines = File.open(filepath, "rb") { |f| f.readlines(chomp: true) }
|
274
|
+
lines[line_num - 1]
|
275
|
+
end
|
276
|
+
|
277
|
+
# @param function_name [String]
|
278
|
+
# @param arg [String]
|
279
|
+
# @param arg_pos [Integer]
|
280
|
+
#
|
281
|
+
# @return [ArgumentDefinition]
|
282
|
+
def generate_argument_definition(function_name:, arg:, arg_pos:)
|
283
|
+
parts = arg.split
|
284
|
+
|
285
|
+
if parts.count < 2
|
286
|
+
return ArgumentDefinition.new(
|
287
|
+
type: parts[0],
|
288
|
+
name: "arg#{arg_pos}",
|
289
|
+
pointer: nil,
|
290
|
+
)
|
291
|
+
end
|
292
|
+
|
293
|
+
loop do
|
294
|
+
pointer_index = parts.index("*")
|
295
|
+
break unless pointer_index
|
296
|
+
|
297
|
+
parts[pointer_index - 1] << "*"
|
298
|
+
parts.delete_at(pointer_index)
|
299
|
+
end
|
300
|
+
|
301
|
+
type, pointer, length = analyze_argument_type(function_name:, arg_pos:, parts:)
|
302
|
+
|
303
|
+
ArgumentDefinition.new(
|
304
|
+
name: parts[-1],
|
305
|
+
type:,
|
306
|
+
pointer:,
|
307
|
+
length:,
|
308
|
+
)
|
309
|
+
end
|
310
|
+
|
311
|
+
# @param function_name [String]
|
312
|
+
# @param arg_pos [Integer]
|
313
|
+
# @param parts [Array<String>]
|
314
|
+
#
|
315
|
+
# @return [Array<String, Symbol, Integer>]
|
316
|
+
# - type [String]
|
317
|
+
# - pointer [Symbol]
|
318
|
+
# - length [Integer]
|
319
|
+
def analyze_argument_type(function_name:, arg_pos:, parts:)
|
320
|
+
pointer, length = prepare_argument_parts(arg_pos:, parts:)
|
321
|
+
type = parts[0...-1] || []
|
322
|
+
original_type = Util.sanitize_type(type.join(" "))
|
323
|
+
|
324
|
+
case original_type
|
325
|
+
when /\*+$/
|
326
|
+
type = original_type.gsub(/\*+$/, "").strip
|
327
|
+
pointer = config.function_arg_pointer_hint(function_name:, pos: arg_pos)
|
328
|
+
|
329
|
+
when /^void\s*/, /\(.*\)/
|
330
|
+
# function pointer (e.g. void *(*func)(void *)) is treated as `void*`
|
331
|
+
type = "void"
|
332
|
+
pointer = config.function_arg_pointer_hint(function_name:, pos: arg_pos)
|
333
|
+
|
334
|
+
else
|
335
|
+
type = original_type
|
336
|
+
end
|
337
|
+
|
338
|
+
length = pointer_length(original_type) if pointer == :sref
|
339
|
+
|
340
|
+
[type, pointer, length]
|
341
|
+
end
|
342
|
+
|
343
|
+
# @param arg_pos [Integer]
|
344
|
+
# @param parts [Array<String>]
|
345
|
+
#
|
346
|
+
# @return [Array<Symbol, Integer>]
|
347
|
+
# - pointer [Symbol,nil]
|
348
|
+
# - length [Integer]
|
349
|
+
def prepare_argument_parts(parts:, arg_pos:)
|
350
|
+
if parts[-1] =~ /\[([0-9]+)?\]$/
|
351
|
+
parts[-1].gsub!(/\[([0-9]+)?\]$/, "")
|
352
|
+
length = ::Regexp.last_match(1).to_i
|
353
|
+
|
354
|
+
unless parts[-1] =~ /^[0-9a-zA-Z_]+$/
|
355
|
+
# last elements isn't dummy argument
|
356
|
+
parts << "arg#{arg_pos}"
|
357
|
+
end
|
358
|
+
|
359
|
+
return [:array, length]
|
360
|
+
end
|
361
|
+
|
362
|
+
unless parts[-1] =~ /^[0-9a-zA-Z_]+$/
|
363
|
+
# last elements isn't dummy argument
|
364
|
+
parts << "arg#{arg_pos}"
|
365
|
+
end
|
366
|
+
|
367
|
+
[nil, 0]
|
368
|
+
end
|
369
|
+
|
370
|
+
# @param type [String]
|
371
|
+
def pointer_length(type)
|
372
|
+
type =~ /(\*+)$/
|
373
|
+
::Regexp.last_match(1)&.length || 0
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyHeaderParser
|
4
|
+
# struct definition in header file
|
5
|
+
class StructDefinition
|
6
|
+
# @!attribute name
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @param name [String]
|
11
|
+
def initialize(name:)
|
12
|
+
@name = name
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param other [StructDefinition]
|
16
|
+
# @return [Boolean]
|
17
|
+
def ==(other)
|
18
|
+
other.is_a?(StructDefinition) && name == other.name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyHeaderParser
|
4
|
+
# type definition in header file
|
5
|
+
class TypeDefinition
|
6
|
+
# @!attribute name
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @param name [String]
|
11
|
+
def initialize(name:)
|
12
|
+
@name = name
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param other [TypeDefinition]
|
16
|
+
# @return [Boolean]
|
17
|
+
def ==(other)
|
18
|
+
other.is_a?(TypeDefinition) && name == other.name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyHeaderParser
|
4
|
+
# typeref definition for {RubyHeaderParser::FunctionDefinition}
|
5
|
+
class TyperefDefinition
|
6
|
+
# @!attribute type
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :type
|
9
|
+
|
10
|
+
# @!attribute pointer
|
11
|
+
# @return [Symbol,nil] :ref, :raw
|
12
|
+
attr_accessor :pointer
|
13
|
+
|
14
|
+
# @param type [String]
|
15
|
+
# @param pointer [Symbol,nil] :ref, :raw
|
16
|
+
def initialize(type:, pointer: nil)
|
17
|
+
@type = type
|
18
|
+
@pointer = pointer
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Boolean]
|
22
|
+
def pointer?
|
23
|
+
!!pointer
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param other [TyperefDefinition]
|
27
|
+
# @return [Boolean]
|
28
|
+
def ==(other)
|
29
|
+
other.is_a?(TyperefDefinition) && type == other.type && pointer == other.pointer
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyHeaderParser
|
4
|
+
# util methods
|
5
|
+
module Util
|
6
|
+
# @param array [Array<String>]
|
7
|
+
# @param field_name [String]
|
8
|
+
# @return [String,nil]
|
9
|
+
def self.find_field(array, field_name)
|
10
|
+
array.each do |element|
|
11
|
+
return element.delete_prefix("#{field_name}:").strip if element.start_with?("#{field_name}:")
|
12
|
+
end
|
13
|
+
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param signature [String]
|
18
|
+
# @return [Array<String>]
|
19
|
+
def self.split_signature(signature)
|
20
|
+
signature.scan(/[^,]+\([^()]*\)|[^,]+/).flatten.map(&:strip)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param type [String]
|
24
|
+
# @return [String]
|
25
|
+
def self.sanitize_type(type)
|
26
|
+
type.gsub(/(enum|volatile|const|struct|static\s+inline)\s+/i, "").gsub("const*", "").strip
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "tmpdir"
|
5
|
+
|
6
|
+
require_relative "ruby_header_parser/version"
|
7
|
+
|
8
|
+
# Parser for ruby.h
|
9
|
+
module RubyHeaderParser
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
autoload :ArgumentDefinition, "ruby_header_parser/argument_definition"
|
13
|
+
autoload :Config, "ruby_header_parser/config"
|
14
|
+
autoload :EnumDefinition, "ruby_header_parser/enum_definition"
|
15
|
+
autoload :FunctionDefinition, "ruby_header_parser/function_definition"
|
16
|
+
autoload :Parser, "ruby_header_parser/parser"
|
17
|
+
autoload :StructDefinition, "ruby_header_parser/struct_definition"
|
18
|
+
autoload :TypeDefinition, "ruby_header_parser/type_definition"
|
19
|
+
autoload :TyperefDefinition, "ruby_header_parser/typeref_definition"
|
20
|
+
autoload :Util, "ruby_header_parser/util"
|
21
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
---
|
2
|
+
path: ".gem_rbs_collection"
|
3
|
+
gems:
|
4
|
+
- name: ast
|
5
|
+
version: '2.4'
|
6
|
+
source:
|
7
|
+
type: git
|
8
|
+
name: ruby/gem_rbs_collection
|
9
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
10
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
11
|
+
repo_dir: gems
|
12
|
+
- name: binding_of_caller
|
13
|
+
version: '1.0'
|
14
|
+
source:
|
15
|
+
type: git
|
16
|
+
name: ruby/gem_rbs_collection
|
17
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
18
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
19
|
+
repo_dir: gems
|
20
|
+
- name: dbm
|
21
|
+
version: '0'
|
22
|
+
source:
|
23
|
+
type: stdlib
|
24
|
+
- name: diff-lcs
|
25
|
+
version: '1.5'
|
26
|
+
source:
|
27
|
+
type: git
|
28
|
+
name: ruby/gem_rbs_collection
|
29
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
30
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
31
|
+
repo_dir: gems
|
32
|
+
- name: fileutils
|
33
|
+
version: '0'
|
34
|
+
source:
|
35
|
+
type: stdlib
|
36
|
+
- name: json
|
37
|
+
version: '0'
|
38
|
+
source:
|
39
|
+
type: stdlib
|
40
|
+
- name: parallel
|
41
|
+
version: '1.20'
|
42
|
+
source:
|
43
|
+
type: git
|
44
|
+
name: ruby/gem_rbs_collection
|
45
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
46
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
47
|
+
repo_dir: gems
|
48
|
+
- name: parser
|
49
|
+
version: '3.2'
|
50
|
+
source:
|
51
|
+
type: git
|
52
|
+
name: ruby/gem_rbs_collection
|
53
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
54
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
55
|
+
repo_dir: gems
|
56
|
+
- name: pstore
|
57
|
+
version: '0'
|
58
|
+
source:
|
59
|
+
type: stdlib
|
60
|
+
- name: psych
|
61
|
+
version: '0'
|
62
|
+
source:
|
63
|
+
type: stdlib
|
64
|
+
- name: rainbow
|
65
|
+
version: '3.0'
|
66
|
+
source:
|
67
|
+
type: git
|
68
|
+
name: ruby/gem_rbs_collection
|
69
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
70
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
71
|
+
repo_dir: gems
|
72
|
+
- name: rake
|
73
|
+
version: '13.0'
|
74
|
+
source:
|
75
|
+
type: git
|
76
|
+
name: ruby/gem_rbs_collection
|
77
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
78
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
79
|
+
repo_dir: gems
|
80
|
+
- name: regexp_parser
|
81
|
+
version: '2.8'
|
82
|
+
source:
|
83
|
+
type: git
|
84
|
+
name: ruby/gem_rbs_collection
|
85
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
86
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
87
|
+
repo_dir: gems
|
88
|
+
- name: rspec-parameterized-core
|
89
|
+
version: 1.0.1
|
90
|
+
source:
|
91
|
+
type: rubygems
|
92
|
+
- name: rspec-parameterized-table_syntax
|
93
|
+
version: 1.0.1
|
94
|
+
source:
|
95
|
+
type: rubygems
|
96
|
+
- name: rubocop
|
97
|
+
version: '1.57'
|
98
|
+
source:
|
99
|
+
type: git
|
100
|
+
name: ruby/gem_rbs_collection
|
101
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
102
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
103
|
+
repo_dir: gems
|
104
|
+
- name: rubocop-ast
|
105
|
+
version: '1.30'
|
106
|
+
source:
|
107
|
+
type: git
|
108
|
+
name: ruby/gem_rbs_collection
|
109
|
+
revision: 704f7e6b395fca717cc25c562598ca86015ed545
|
110
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
111
|
+
repo_dir: gems
|
112
|
+
- name: yaml
|
113
|
+
version: '0'
|
114
|
+
source:
|
115
|
+
type: stdlib
|
116
|
+
gemfile_lock_path: Gemfile.lock
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- type: git
|
4
|
+
name: ruby/gem_rbs_collection
|
5
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
6
|
+
revision: main
|
7
|
+
repo_dir: gems
|
8
|
+
|
9
|
+
# You can specify local directories as sources also.
|
10
|
+
# - type: local
|
11
|
+
# path: path/to/your/local/repository
|
12
|
+
|
13
|
+
# A directory to install the downloaded RBSs
|
14
|
+
path: .gem_rbs_collection
|
15
|
+
|
16
|
+
gems:
|
17
|
+
- name: rbs
|
18
|
+
ignore: true
|
19
|
+
- name: steep
|
20
|
+
ignore: true
|
21
|
+
- name: yard
|
22
|
+
ignore: true
|
23
|
+
- name: ruby_header_parser
|
24
|
+
ignore: true
|
25
|
+
|
26
|
+
- name: yaml
|