Skip to content

Commit 06f1c05

Browse files
committed
Impl extract_static_inline_function_definitions
1 parent d218c94 commit 06f1c05

File tree

2 files changed

+90
-35
lines changed

2 files changed

+90
-35
lines changed

_tools/ruby_h_to_go/lib/ruby_header_parser/parser.rb

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module RubyHeaderParser
44
# parse `ruby.h` using `ctags`
5-
class Parser
5+
class Parser # rubocop:disable Metrics/ClassLength
66
# @!attribute [r] header_dir
77
# @return [String]
88
attr_reader :header_dir
@@ -19,38 +19,12 @@ def initialize(header_dir)
1919

2020
# @return [Array<RubyHeaderParser::FunctionDefinition>]
2121
def extract_function_definitions
22-
stdout = execute_ctags("--c-kinds=p --fields=+nS --extras=+q")
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
4524

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)
5428
end
5529

5630
# @return [Array<RubyHeaderParser::StructDefinition>]
@@ -91,6 +65,40 @@ def extract_type_definitions
9165

9266
private
9367

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+
94102
# @param args [String]
95103
# @return [String]
96104
def execute_ctags(args = "")
@@ -113,6 +121,24 @@ def read_definition_from_header_file(file, line_num)
113121
""
114122
end
115123

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+
116142
# @param function_name [String]
117143
# @param signature [String,nil]
118144
# @return [Array<RubyHeaderParser::ArgumentDefinition>]
@@ -182,10 +208,17 @@ def parse_definition_args(function_name, signature)
182208

183209
# @param definition [String]
184210
# @param function_name [String]
211+
# @param typeref_field [String,nil]
185212
# @return [RubyHeaderParser::TyperefDefinition]
186-
def create_typeref(definition, function_name)
187-
typeref_type = definition[0...definition.index(function_name)].gsub("char *", "char*").strip
188-
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
189222

190223
typeref_pointer = nil
191224
if typeref_type.match?(/\*+$/)

_tools/ruby_h_to_go/spec/ruby_header_parser/parser_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,28 @@
138138
end
139139
end
140140

141+
describe "#extract_static_inline_function_definitions" do
142+
subject(:definitions) { parser.extract_static_inline_function_definitions }
143+
144+
its(:count) { should be > 0 }
145+
146+
context "rb_num2int_inline" do
147+
subject { definitions.find { |d| d.name == "rb_num2int_inline" } }
148+
149+
let(:args) do
150+
[
151+
argument(type: "VALUE", name: "x"),
152+
]
153+
end
154+
155+
its(:name) { should eq "rb_num2int_inline" }
156+
its(:definition) { should eq "rb_num2int_inline(VALUE x)" }
157+
its(:filepath) { should be_end_with "/ruby/internal/arithmetic/int.h" }
158+
its(:typeref) { should eq typedef(type: "int") }
159+
its(:args) { should eq args }
160+
end
161+
end
162+
141163
describe "#extract_struct_definitions" do
142164
subject(:definitions) { parser.extract_struct_definitions }
143165

0 commit comments

Comments
 (0)