Skip to content

Commit 2161c20

Browse files
committed
Record line and byte offsets for C methods
1 parent 6772762 commit 2161c20

File tree

5 files changed

+96
-24
lines changed

5 files changed

+96
-24
lines changed

History.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
provide a call-seq.
77
* RDoc::Parser::C now records the function name for methods implemented in
88
C.
9+
* RDoc now records file and byte offset inforamtion for methods.
910
* Bug fixes
1011
* Locations of module aliases are now recorded.
1112
* RDoc::Parser::C finds method bodies better now.

lib/rdoc/code_object.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,23 @@ class RDoc::CodeObject
6060

6161
attr_reader :force_documentation
6262

63+
##
64+
# Line in #file where this CodeObject was defined
65+
66+
attr_accessor :line
67+
6368
##
6469
# Hash of arbitrary metadata for this CodeObject
6570

6671
attr_reader :metadata
6772

73+
##
74+
# Offset in #file where this CodeObject was defined
75+
#--
76+
# TODO character or byte?
77+
78+
attr_accessor :offset
79+
6880
##
6981
# Our parent CodeObject
7082

lib/rdoc/parser/c.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,11 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
379379
\s*(\(.*?\))([^;]|$))%xm then
380380
comment = $1
381381
body = $2
382+
offset = $~.offset(2).first
382383

383384
remove_private_comments comment if comment
384385

385-
# see if we can find the whole body
386-
386+
# try to find the whole body
387387
body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content
388388

389389
# The comment block may have been overridden with a 'Document-method'
@@ -403,11 +403,15 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
403403
tk.set_text body
404404
meth_obj.add_token tk
405405
meth_obj.comment = strip_stars comment
406+
meth_obj.offset = offset
407+
meth_obj.line = file_content[0, offset].count("\n") + 1
406408

407409
body
408410
when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m then
409411
comment = $1
410412
body = $2
413+
offset = $~.offset(2).first
414+
411415
find_body class_name, $3, meth_obj, file_content, true
412416
find_modifiers comment, meth_obj
413417

@@ -416,9 +420,14 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
416420
tk.set_text body
417421
meth_obj.add_token tk
418422
meth_obj.comment = strip_stars(comment) + meth_obj.comment.to_s
423+
meth_obj.offset = offset
424+
meth_obj.line = file_content[0, offset].count("\n") + 1
419425

420426
body
421427
when %r%^\s*\#\s*define\s+#{meth_name}\s+(\w+)%m then
428+
# with no comment we hope the aliased definition has it and use it's
429+
# definition
430+
422431
body = find_body(class_name, $1, meth_obj, file_content, true)
423432

424433
return body if body

test/test_rdoc_code_object.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ def test_full_name_equals
129129
assert_nil @co.instance_variable_get(:@full_name)
130130
end
131131

132+
def test_line
133+
@c1_m.line = 5
134+
135+
assert_equal 5, @c1_m.line
136+
end
137+
132138
def test_metadata
133139
assert_empty @co.metadata
134140

@@ -141,6 +147,12 @@ def test_metadata
141147
assert_equal 'not_rdoc', @co.metadata['markup']
142148
end
143149

150+
def test_offset
151+
@c1_m.offset = 5
152+
153+
assert_equal 5, @c1_m.offset
154+
end
155+
144156
def test_parent_file_name
145157
assert_equal '(unknown)', @co.parent_file_name
146158
assert_equal 'xref_data.rb', @c1.parent_file_name

test/test_rdoc_parser_c.rb

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,41 @@ def test_find_body_2
581581

582582
def test_find_body_define
583583
content = <<-EOF
584+
#define something something_else
585+
586+
#define other_function rb_other_function
587+
588+
/*
589+
* a comment for rb_other_function
590+
*/
591+
VALUE
592+
rb_other_function() {
593+
}
594+
595+
void
596+
Init_Foo(void) {
597+
VALUE foo = rb_define_class("Foo", rb_cObject);
598+
599+
rb_define_method(foo, "my_method", other_function, 0);
600+
}
601+
EOF
602+
603+
klass = util_get_class content, 'foo'
604+
other_function = klass.method_list.first
605+
606+
assert_equal 'my_method', other_function.name
607+
assert_equal 'a comment for rb_other_function', other_function.comment
608+
assert_equal '()', other_function.params
609+
assert_equal 118, other_function.offset
610+
assert_equal 8, other_function.line
611+
612+
code = other_function.token_stream.first.text
613+
614+
assert_equal "VALUE\nrb_other_function() {\n}", code
615+
end
616+
617+
def test_find_body_define_comment
618+
content = <<-EOF
584619
/*
585620
* a comment for other_function
586621
*/
@@ -603,9 +638,10 @@ def test_find_body_define
603638
other_function = klass.method_list.first
604639

605640
assert_equal 'my_method', other_function.name
606-
assert_equal "a comment for other_function",
607-
other_function.comment
641+
assert_equal 'a comment for other_function', other_function.comment
608642
assert_equal '()', other_function.params
643+
assert_equal 39, other_function.offset
644+
assert_equal 4, other_function.line
609645

610646
code = other_function.token_stream.first.text
611647

@@ -749,18 +785,36 @@ def test_find_modifiers_yields
749785
assert_equal expected, comment
750786
end
751787

752-
def test_handle_method
788+
def test_handle_method_args_minus_1
753789
parser = util_parser "Document-method: Object#m\n blah */"
754790

755-
parser.handle_method 'method', 'rb_cObject', 'm', 'rb_m', 2
791+
parser.content = <<-BODY
792+
VALUE
793+
rb_other(VALUE obj) {
794+
rb_funcall(obj, rb_intern("other"), 0);
795+
return rb_str_new2("blah, blah, blah");
796+
}
797+
798+
VALUE
799+
rb_m(int argc, VALUE *argv, VALUE obj) {
800+
VALUE o1, o2;
801+
rb_scan_args(argc, argv, "1", &o1, &o2);
802+
}
803+
BODY
804+
805+
parser.handle_method 'method', 'rb_cObject', 'm', 'rb_m', -1
756806

757807
m = @top_level.find_module_named('Object').method_list.first
758808

759809
assert_equal 'm', m.name
760-
assert_equal '(p1, p2)', m.params
761810
assert_equal @top_level, m.file
811+
assert_equal 115, m.offset
812+
assert_equal 7, m.line
813+
814+
assert_equal '(p1)', m.params
762815
end
763816

817+
764818
def test_handle_method_args_0
765819
parser = util_parser "Document-method: BasicObject#==\n blah */"
766820

@@ -803,23 +857,7 @@ def test_handle_method_args_2
803857
assert_equal '(p1, p2)', equals2.params
804858
end
805859

806-
def test_handle_method_args_minus_1
807-
parser = util_parser "Document-method: Object#m\n blah */"
808-
809-
parser.content = <<-BODY
810-
VALUE
811-
rb_m(int argc, VALUE *argv, VALUE obj) {
812-
VALUE o1, o2;
813-
rb_scan_args(argc, argv, "1", &o1, &o2);
814-
}
815-
BODY
816-
817-
parser.handle_method 'method', 'rb_cObject', 'm', 'rb_m', -1
818-
819-
m = @top_level.find_module_named('Object').method_list.first
820-
821-
assert_equal '(p1)', m.params
822-
end
860+
# test_handle_args_minus_1 handled by test_handle_method
823861

824862
def test_handle_method_args_minus_2
825863
parser = util_parser "Document-method: BasicObject#==\n blah */"

0 commit comments

Comments
 (0)