ruby_header_parser 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|