[ruby/rdoc] Allow boolean arguments to rb_attr and rb_define_attr

Currently only literal `0` and `1` are accepted as `read`/`write`
flags.
This patch allows other boolean arguments, C macros (`FALSE`/`TRUE`),
Ruby `VALUE`s (`Qfalse`/`Qtrue`), and C99 `bool`s (`false`/`true`), as
well.

https://github.com/ruby/rdoc/commit/169dc02e3c
This commit is contained in:
Nobuyoshi Nakada 2022-06-07 09:18:35 +09:00 committed by git
parent cfcf33f127
commit dbfb3b1917
2 changed files with 32 additions and 78 deletions

View File

@ -122,6 +122,11 @@ class RDoc::Parser::C < RDoc::Parser
include RDoc::Text include RDoc::Text
#--
BOOL_ARG_PATTERN = /\s*+\b([01]|Q?(?:true|false)|TRUE|FALSE)\b\s*/
TRUE_VALUES = ['1', 'TRUE', 'true', 'Qtrue'].freeze
#++
## ##
# Maps C variable names to names of Ruby classes or modules # Maps C variable names to names of Ruby classes or modules
@ -259,18 +264,18 @@ class RDoc::Parser::C < RDoc::Parser
@content.scan(/rb_attr\s*\( @content.scan(/rb_attr\s*\(
\s*(\w+), \s*(\w+),
\s*([\w"()]+), \s*([\w"()]+),
\s*([01]), #{BOOL_ARG_PATTERN},
\s*([01]), #{BOOL_ARG_PATTERN},
\s*\w+\);/xm) do |var_name, attr_name, read, write| \s*\w+\);/xmo) do |var_name, attr_name, read, write|
handle_attr var_name, attr_name, read, write handle_attr var_name, attr_name, read, write
end end
@content.scan(%r%rb_define_attr\( @content.scan(%r%rb_define_attr\(
\s*([\w\.]+), \s*([\w\.]+),
\s*"([^"]+)", \s*"([^"]+)",
\s*(\d+), #{BOOL_ARG_PATTERN},
\s*(\d+)\s*\); #{BOOL_ARG_PATTERN}\);
%xm) do |var_name, attr_name, read, write| %xmo) do |var_name, attr_name, read, write|
handle_attr var_name, attr_name, read, write handle_attr var_name, attr_name, read, write
end end
end end
@ -815,8 +820,8 @@ class RDoc::Parser::C < RDoc::Parser
def handle_attr(var_name, attr_name, read, write) def handle_attr(var_name, attr_name, read, write)
rw = '' rw = ''
rw += 'R' if '1' == read rw += 'R' if TRUE_VALUES.include?(read)
rw += 'W' if '1' == write rw += 'W' if TRUE_VALUES.include?(write)
class_name = @known_classes[var_name] class_name = @known_classes[var_name]

View File

@ -132,7 +132,7 @@ class TestRDocParserC < RDoc::TestCase
assert_equal expected, known_classes assert_equal expected, known_classes
end end
def test_do_attr_rb_attr def assert_do_attr(flags)
content = <<-EOF content = <<-EOF
void Init_Blah(void) { void Init_Blah(void) {
cBlah = rb_define_class("Blah", rb_cObject); cBlah = rb_define_class("Blah", rb_cObject);
@ -140,17 +140,17 @@ void Init_Blah(void) {
/* /*
* This is an accessor * This is an accessor
*/ */
rb_attr(cBlah, rb_intern("accessor"), 1, 1, Qfalse); #{yield "cBlah", "accessor", flags[1], flags[1]};
/* /*
* This is a reader * This is a reader
*/ */
rb_attr(cBlah, rb_intern("reader"), 1, 0, Qfalse); #{yield "cBlah", "reader", flags[1], flags[0]};
/* /*
* This is a writer * This is a writer
*/ */
rb_attr(cBlah, rb_intern("writer"), 0, 1, Qfalse); #{yield "cBlah", "writer", flags[0], flags[1]};
} }
EOF EOF
@ -176,72 +176,21 @@ void Init_Blah(void) {
assert_equal 'This is a writer', writer.comment.text assert_equal 'This is a writer', writer.comment.text
end end
def test_do_attr_rb_attr_2 {
content = <<-EOF num: %w[0 1],
void Init_Blah(void) { macro: %w[FALSE TRUE],
cBlah = rb_define_class("Blah", rb_cObject); ruby: %w[Qfalse Qtrue],
bool: %w[false true],
/* }.each_pair do |name, values|
* This is an accessor define_method("test_do_attr:rb_attr:intern:#{name}") do
*/ assert_do_attr(values) {|c, name, r, w| %[rb_attr(#{c}, rb_intern("#{name}"), #{r}, #{w}, Qfalse)]}
rb_attr(cBlah, rb_intern_const("accessor"), 1, 1, Qfalse); end
define_method("test_do_attr:rb_attr:intern_const:#{name}") do
/* assert_do_attr(values) {|c, name, r, w| %[rb_attr(#{c}, rb_intern_const("#{name}"), #{r}, #{w}, Qfalse)]}
* This is a reader end
*/ define_method("test_do_attr:rb_define_attr:#{name}") do
rb_attr(cBlah, rb_intern_const("reader"), 1, 0, Qfalse); assert_do_attr(values) {|c, name, r, w| %[rb_define_attr(#{c}, "#{name}", #{r}, #{w})]}
end
/*
* This is a writer
*/
rb_attr(cBlah, rb_intern_const("writer"), 0, 1, Qfalse);
}
EOF
klass = util_get_class content, 'cBlah'
attrs = klass.attributes
assert_equal 3, attrs.length, attrs.inspect
accessor = attrs.shift
assert_equal 'accessor', accessor.name
assert_equal 'RW', accessor.rw
assert_equal 'This is an accessor', accessor.comment.text
assert_equal @top_level, accessor.file
reader = attrs.shift
assert_equal 'reader', reader.name
assert_equal 'R', reader.rw
assert_equal 'This is a reader', reader.comment.text
writer = attrs.shift
assert_equal 'writer', writer.name
assert_equal 'W', writer.rw
assert_equal 'This is a writer', writer.comment.text
end
def test_do_attr_rb_define_attr
content = <<-EOF
void Init_Blah(void) {
cBlah = rb_define_class("Blah", rb_cObject);
/*
* This is an accessor
*/
rb_define_attr(cBlah, "accessor", 1, 1);
}
EOF
klass = util_get_class content, 'cBlah'
attrs = klass.attributes
assert_equal 1, attrs.length, attrs.inspect
accessor = attrs.shift
assert_equal 'accessor', accessor.name
assert_equal 'RW', accessor.rw
assert_equal 'This is an accessor', accessor.comment.text
assert_equal @top_level, accessor.file
end end
def test_do_aliases def test_do_aliases