rdoc 7.2.0 → 8.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 +4 -4
- data/CONTRIBUTING.md +4 -7
- data/LICENSE.rdoc +4 -0
- data/README.md +43 -2
- data/RI.md +75 -75
- data/doc/markup_reference/markdown.md +104 -3
- data/exe/rdoc +2 -2
- data/lib/rdoc/code_object/alias.rb +70 -74
- data/lib/rdoc/code_object/any_method.rb +305 -298
- data/lib/rdoc/code_object/attr.rb +150 -143
- data/lib/rdoc/code_object/class_module.rb +801 -765
- data/lib/rdoc/code_object/constant.rb +178 -150
- data/lib/rdoc/code_object/context/section.rb +133 -160
- data/lib/rdoc/code_object/context.rb +925 -952
- data/lib/rdoc/code_object/extend.rb +7 -5
- data/lib/rdoc/code_object/include.rb +7 -5
- data/lib/rdoc/code_object/method_attr.rb +325 -324
- data/lib/rdoc/code_object/mixin.rb +97 -95
- data/lib/rdoc/code_object/normal_class.rb +77 -78
- data/lib/rdoc/code_object/normal_module.rb +61 -59
- data/lib/rdoc/code_object/require.rb +23 -39
- data/lib/rdoc/code_object/single_class.rb +21 -19
- data/lib/rdoc/code_object/top_level.rb +212 -213
- data/lib/rdoc/code_object.rb +305 -305
- data/lib/rdoc/comment.rb +274 -337
- data/lib/rdoc/cross_reference.rb +194 -212
- data/lib/rdoc/encoding.rb +105 -103
- data/lib/rdoc/erb_partial.rb +13 -11
- data/lib/rdoc/erbio.rb +29 -27
- data/lib/rdoc/generator/aliki.rb +165 -140
- data/lib/rdoc/generator/darkfish.rb +647 -631
- data/lib/rdoc/generator/json_index.rb +233 -229
- data/lib/rdoc/generator/markup.rb +165 -122
- data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
- data/lib/rdoc/generator/pot/po.rb +52 -51
- data/lib/rdoc/generator/pot/po_entry.rb +138 -132
- data/lib/rdoc/generator/pot.rb +85 -81
- data/lib/rdoc/generator/ri.rb +23 -19
- data/lib/rdoc/generator/template/aliki/DESIGN.md +538 -0
- data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_head.rhtml +11 -11
- data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
- data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +8 -6
- data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +8 -6
- data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +2 -2
- data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
- data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/class.rhtml +56 -46
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +538 -283
- data/lib/rdoc/generator/template/aliki/index.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/js/aliki.js +80 -102
- data/lib/rdoc/generator/template/aliki/page.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +2 -2
- data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +8 -6
- data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +8 -6
- data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +5 -5
- data/lib/rdoc/generator/template/darkfish/class.rhtml +18 -21
- data/lib/rdoc/generator/template/darkfish/css/rdoc.css +0 -1
- data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +3 -3
- data/lib/rdoc/generator.rb +48 -46
- data/lib/rdoc/i18n/locale.rb +99 -95
- data/lib/rdoc/i18n/text.rb +109 -105
- data/lib/rdoc/i18n.rb +7 -5
- data/lib/rdoc/markdown/byte_runtime.rb +80 -0
- data/lib/rdoc/markdown.kpeg +30 -21
- data/lib/rdoc/markdown.rb +329 -151
- data/lib/rdoc/markup/block_quote.rb +12 -8
- data/lib/rdoc/markup/document.rb +127 -123
- data/lib/rdoc/markup/formatter.rb +215 -221
- data/lib/rdoc/markup/heading.rb +1 -4
- data/lib/rdoc/markup/include.rb +33 -29
- data/lib/rdoc/markup/indented_paragraph.rb +37 -33
- data/lib/rdoc/markup/inline_parser.rb +281 -277
- data/lib/rdoc/markup/list.rb +80 -88
- data/lib/rdoc/markup/list_item.rb +73 -85
- data/lib/rdoc/markup/paragraph.rb +23 -19
- data/lib/rdoc/markup/parser.rb +501 -497
- data/lib/rdoc/markup/pre_process.rb +284 -305
- data/lib/rdoc/markup/raw.rb +2 -2
- data/lib/rdoc/markup/rule.rb +16 -12
- data/lib/rdoc/markup/to_ansi.rb +143 -139
- data/lib/rdoc/markup/to_bs.rb +72 -68
- data/lib/rdoc/markup/to_html.rb +600 -493
- data/lib/rdoc/markup/to_html_crossref.rb +221 -191
- data/lib/rdoc/markup/to_html_snippet.rb +232 -227
- data/lib/rdoc/markup/to_joined_paragraph.rb +40 -41
- data/lib/rdoc/markup/to_label.rb +63 -59
- data/lib/rdoc/markup/to_markdown.rb +212 -208
- data/lib/rdoc/markup/to_rdoc.rb +336 -332
- data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
- data/lib/rdoc/markup/to_test.rb +60 -56
- data/lib/rdoc/markup/to_tt_only.rb +83 -86
- data/lib/rdoc/markup/verbatim.rb +62 -58
- data/lib/rdoc/markup.rb +198 -196
- data/lib/rdoc/options.rb +1063 -1076
- data/lib/rdoc/parser/c.rb +1039 -1036
- data/lib/rdoc/parser/changelog.rb +319 -315
- data/lib/rdoc/parser/markdown.rb +17 -13
- data/lib/rdoc/parser/rbs.rb +279 -0
- data/lib/rdoc/parser/rd.rb +17 -13
- data/lib/rdoc/parser/ruby.rb +1231 -2222
- data/lib/rdoc/parser/ruby_colorizer.rb +303 -0
- data/lib/rdoc/parser/simple.rb +31 -27
- data/lib/rdoc/parser/text.rb +12 -8
- data/lib/rdoc/parser.rb +230 -221
- data/lib/rdoc/rbs_helper.rb +186 -0
- data/lib/rdoc/rd/inline.rb +57 -53
- data/lib/rdoc/rd.rb +90 -88
- data/lib/rdoc/rdoc.rb +547 -366
- data/lib/rdoc/ri/driver.rb +1141 -1130
- data/lib/rdoc/ri/formatter.rb +7 -3
- data/lib/rdoc/ri/paths.rb +140 -136
- data/lib/rdoc/ri/servlet.rb +456 -0
- data/lib/rdoc/ri/store.rb +4 -2
- data/lib/rdoc/ri/task.rb +55 -51
- data/lib/rdoc/ri.rb +14 -11
- data/lib/rdoc/rubygems_hook.rb +194 -192
- data/lib/rdoc/server.rb +462 -0
- data/lib/rdoc/stats/normal.rb +46 -42
- data/lib/rdoc/stats/quiet.rb +39 -35
- data/lib/rdoc/stats/verbose.rb +35 -31
- data/lib/rdoc/stats.rb +363 -338
- data/lib/rdoc/store.rb +919 -725
- data/lib/rdoc/task.rb +260 -255
- data/lib/rdoc/text.rb +130 -245
- data/lib/rdoc/token_stream.rb +101 -115
- data/lib/rdoc/tom_doc.rb +203 -201
- data/lib/rdoc/version.rb +1 -1
- data/lib/rdoc.rb +35 -7
- data/lib/rubygems_plugin.rb +2 -11
- data/rdoc-logo.svg +43 -0
- data/rdoc.gemspec +6 -4
- metadata +36 -20
- data/lib/rdoc/code_object/anon_class.rb +0 -10
- data/lib/rdoc/code_object/ghost_method.rb +0 -6
- data/lib/rdoc/code_object/meta_method.rb +0 -6
- data/lib/rdoc/markdown/literals.kpeg +0 -21
- data/lib/rdoc/markdown/literals.rb +0 -454
- data/lib/rdoc/parser/prism_ruby.rb +0 -1112
- data/lib/rdoc/parser/ripper_state_lex.rb +0 -302
- data/lib/rdoc/parser/ruby_tools.rb +0 -163
- data/lib/rdoc/servlet.rb +0 -452
data/lib/rdoc/parser/c.rb
CHANGED
|
@@ -1,1226 +1,1229 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'tsort'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# *
|
|
20
|
-
# *
|
|
21
|
-
# *
|
|
22
|
-
# *
|
|
23
|
-
# *
|
|
24
|
-
# *
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# method
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
# *
|
|
104
|
-
# *
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
# *
|
|
111
|
-
# *
|
|
112
|
-
# *
|
|
113
|
-
# *
|
|
114
|
-
# *
|
|
115
|
-
# *
|
|
116
|
-
# *
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
4
|
+
module RDoc
|
|
5
|
+
class Parser
|
|
6
|
+
##
|
|
7
|
+
# RDoc::Parser::C attempts to parse C extension files. It looks for
|
|
8
|
+
# the standard patterns that you find in extensions: +rb_define_class+,
|
|
9
|
+
# +rb_define_method+ and so on. It tries to find the corresponding
|
|
10
|
+
# C source for the methods and extract comments, but if we fail
|
|
11
|
+
# we don't worry too much.
|
|
12
|
+
#
|
|
13
|
+
# The comments associated with a Ruby method are extracted from the C
|
|
14
|
+
# comment block associated with the routine that _implements_ that
|
|
15
|
+
# method, that is to say the method whose name is given in the
|
|
16
|
+
# +rb_define_method+ call. For example, you might write:
|
|
17
|
+
#
|
|
18
|
+
# /*
|
|
19
|
+
# * Returns a new array that is a one-dimensional flattening of this
|
|
20
|
+
# * array (recursively). That is, for every element that is an array,
|
|
21
|
+
# * extract its elements into the new array.
|
|
22
|
+
# *
|
|
23
|
+
# * s = [ 1, 2, 3 ] #=> [1, 2, 3]
|
|
24
|
+
# * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
|
|
25
|
+
# * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
|
|
26
|
+
# * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
27
|
+
# */
|
|
28
|
+
# static VALUE
|
|
29
|
+
# rb_ary_flatten(VALUE ary)
|
|
30
|
+
# {
|
|
31
|
+
# ary = rb_obj_dup(ary);
|
|
32
|
+
# rb_ary_flatten_bang(ary);
|
|
33
|
+
# return ary;
|
|
34
|
+
# }
|
|
35
|
+
#
|
|
36
|
+
# ...
|
|
37
|
+
#
|
|
38
|
+
# void
|
|
39
|
+
# Init_Array(void)
|
|
40
|
+
# {
|
|
41
|
+
# ...
|
|
42
|
+
# rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
|
|
43
|
+
#
|
|
44
|
+
# Here RDoc will determine from the +rb_define_method+ line that there's a
|
|
45
|
+
# method called "flatten" in class Array, and will look for the implementation
|
|
46
|
+
# in the method +rb_ary_flatten+. It will then use the comment from that
|
|
47
|
+
# method in the HTML output. This method must be in the same source file
|
|
48
|
+
# as the +rb_define_method+.
|
|
49
|
+
#
|
|
50
|
+
# The comment blocks may include special directives:
|
|
51
|
+
#
|
|
52
|
+
# [Document-class: +name+]
|
|
53
|
+
# Documentation for the named class.
|
|
54
|
+
#
|
|
55
|
+
# [Document-module: +name+]
|
|
56
|
+
# Documentation for the named module.
|
|
57
|
+
#
|
|
58
|
+
# [Document-const: +name+]
|
|
59
|
+
# Documentation for the named +rb_define_const+.
|
|
60
|
+
#
|
|
61
|
+
# Constant values can be supplied on the first line of the comment like so:
|
|
62
|
+
#
|
|
63
|
+
# /* 300: The highest possible score in bowling */
|
|
64
|
+
# rb_define_const(cFoo, "PERFECT", INT2FIX(300));
|
|
65
|
+
#
|
|
66
|
+
# The value can contain internal colons so long as they are escaped with a \
|
|
67
|
+
#
|
|
68
|
+
# [Document-global: +name+]
|
|
69
|
+
# Documentation for the named +rb_define_global_const+
|
|
70
|
+
#
|
|
71
|
+
# [Document-variable: +name+]
|
|
72
|
+
# Documentation for the named +rb_define_variable+
|
|
73
|
+
#
|
|
74
|
+
# [Document-method\: +method_name+]
|
|
75
|
+
# Documentation for the named method. Use this when the method name is
|
|
76
|
+
# unambiguous.
|
|
77
|
+
#
|
|
78
|
+
# [Document-method\: <tt>ClassName::method_name</tt>]
|
|
79
|
+
# Documentation for a singleton method in the given class. Use this when
|
|
80
|
+
# the method name alone is ambiguous.
|
|
81
|
+
#
|
|
82
|
+
# [Document-method\: <tt>ClassName#method_name</tt>]
|
|
83
|
+
# Documentation for a instance method in the given class. Use this when the
|
|
84
|
+
# method name alone is ambiguous.
|
|
85
|
+
#
|
|
86
|
+
# [Document-attr: +name+]
|
|
87
|
+
# Documentation for the named attribute.
|
|
88
|
+
#
|
|
89
|
+
# [call-seq: <i>text up to an empty line</i>]
|
|
90
|
+
# Because C source doesn't give descriptive names to Ruby-level parameters,
|
|
91
|
+
# you need to document the calling sequence explicitly
|
|
92
|
+
#
|
|
93
|
+
# In addition, RDoc assumes by default that the C method implementing a
|
|
94
|
+
# Ruby function is in the same source file as the rb_define_method call.
|
|
95
|
+
# If this isn't the case, add the comment:
|
|
96
|
+
#
|
|
97
|
+
# rb_define_method(....); // in filename
|
|
98
|
+
#
|
|
99
|
+
# As an example, we might have an extension that defines multiple classes
|
|
100
|
+
# in its Init_xxx method. We could document them using
|
|
101
|
+
#
|
|
102
|
+
# /*
|
|
103
|
+
# * Document-class: MyClass
|
|
104
|
+
# *
|
|
105
|
+
# * Encapsulate the writing and reading of the configuration
|
|
106
|
+
# * file. ...
|
|
107
|
+
# */
|
|
108
|
+
#
|
|
109
|
+
# /*
|
|
110
|
+
# * Document-method: read_value
|
|
111
|
+
# *
|
|
112
|
+
# * call-seq:
|
|
113
|
+
# * cfg.read_value(key) -> value
|
|
114
|
+
# * cfg.read_value(key} { |key| } -> value
|
|
115
|
+
# *
|
|
116
|
+
# * Return the value corresponding to +key+ from the configuration.
|
|
117
|
+
# * In the second form, if the key isn't found, invoke the
|
|
118
|
+
# * block and return its value.
|
|
119
|
+
# */
|
|
120
|
+
|
|
121
|
+
class C < Parser
|
|
122
|
+
|
|
123
|
+
parse_files_matching(/\.(?:([CcHh])\1?|c([+xp])\2|y)\z/)
|
|
124
|
+
|
|
125
|
+
include ::RDoc::Text
|
|
126
|
+
|
|
127
|
+
# :stopdoc:
|
|
128
|
+
BOOL_ARG_PATTERN = /\s*+\b([01]|Q?(?:true|false)|TRUE|FALSE)\b\s*/
|
|
129
|
+
TRUE_VALUES = ['1', 'TRUE', 'true', 'Qtrue'].freeze
|
|
130
|
+
# :startdoc:
|
|
131
|
+
|
|
132
|
+
##
|
|
133
|
+
# Maps C variable names to names of Ruby classes or modules
|
|
134
|
+
|
|
135
|
+
attr_reader :classes
|
|
136
|
+
|
|
137
|
+
##
|
|
138
|
+
# C file the parser is parsing
|
|
139
|
+
|
|
140
|
+
attr_accessor :content
|
|
141
|
+
|
|
142
|
+
##
|
|
143
|
+
# Dependencies from a missing enclosing class to the classes in
|
|
144
|
+
# missing_dependencies that depend upon it.
|
|
145
|
+
|
|
146
|
+
attr_reader :enclosure_dependencies
|
|
147
|
+
|
|
148
|
+
##
|
|
149
|
+
# Maps C variable names to names of Ruby classes (and singleton classes)
|
|
150
|
+
|
|
151
|
+
attr_reader :known_classes
|
|
152
|
+
|
|
153
|
+
##
|
|
154
|
+
# Classes found while parsing the C file that were not yet registered due to
|
|
155
|
+
# a missing enclosing class. These are processed by do_missing
|
|
156
|
+
|
|
157
|
+
attr_reader :missing_dependencies
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
# Maps C variable names to names of Ruby singleton classes
|
|
161
|
+
|
|
162
|
+
attr_reader :singleton_classes
|
|
163
|
+
|
|
164
|
+
##
|
|
165
|
+
# The TopLevel items in the parsed file belong to
|
|
166
|
+
|
|
167
|
+
attr_reader :top_level
|
|
168
|
+
|
|
169
|
+
##
|
|
170
|
+
# Prepares for parsing a C file. See RDoc::Parser#initialize for details on
|
|
171
|
+
# the arguments.
|
|
172
|
+
|
|
173
|
+
def initialize(top_level, content, options, stats)
|
|
174
|
+
super
|
|
175
|
+
|
|
176
|
+
@known_classes = KNOWN_CLASSES.dup
|
|
177
|
+
@content = handle_tab_width handle_ifdefs_in @content
|
|
178
|
+
@file_dir = File.dirname @file_name
|
|
177
179
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
@classes = load_variable_map :c_class_variables
|
|
181
|
+
@singleton_classes = load_variable_map :c_singleton_class_variables
|
|
180
182
|
|
|
181
|
-
|
|
183
|
+
@markup = @options.markup
|
|
182
184
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
# class_variable => { function => [method, ...] }
|
|
186
|
+
@methods = Hash.new { |h, f| h[f] = Hash.new { |i, m| i[m] = [] } }
|
|
185
187
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
# missing variable => [handle_class_module arguments]
|
|
189
|
+
@missing_dependencies = {}
|
|
188
190
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
# missing enclosure variable => [dependent handle_class_module arguments]
|
|
192
|
+
@enclosure_dependencies = Hash.new { |h, k| h[k] = [] }
|
|
193
|
+
@enclosure_dependencies.instance_variable_set :@missing_dependencies,
|
|
194
|
+
@missing_dependencies
|
|
193
195
|
|
|
194
|
-
|
|
196
|
+
@enclosure_dependencies.extend TSort
|
|
195
197
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
def @enclosure_dependencies.tsort_each_node(&block)
|
|
199
|
+
each_key(&block)
|
|
200
|
+
rescue TSort::Cyclic => e
|
|
201
|
+
cycle_vars = e.message.scan(/"(.*?)"/).flatten
|
|
200
202
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
+
cycle = cycle_vars.sort.map do |var_name|
|
|
204
|
+
delete var_name
|
|
203
205
|
|
|
204
|
-
|
|
206
|
+
var_name, type, mod_name, = @missing_dependencies[var_name]
|
|
205
207
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
"#{type} #{mod_name} (#{var_name})"
|
|
209
|
+
end.join ', '
|
|
208
210
|
|
|
209
|
-
|
|
211
|
+
warn "Unable to create #{cycle} due to a cyclic class or module creation"
|
|
210
212
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def @enclosure_dependencies.tsort_each_child(node, &block)
|
|
215
|
-
fetch(node, []).each(&block)
|
|
216
|
-
end
|
|
217
|
-
end
|
|
213
|
+
retry
|
|
214
|
+
end
|
|
218
215
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
def do_aliases
|
|
223
|
-
@content.scan(/rb_define_alias\s*\(
|
|
224
|
-
\s*(\w+),
|
|
225
|
-
\s*"(.+?)",
|
|
226
|
-
\s*"(.+?)"
|
|
227
|
-
\s*\)/xm) do |var_name, new_name, old_name|
|
|
228
|
-
class_name = @known_classes[var_name]
|
|
229
|
-
|
|
230
|
-
unless class_name then
|
|
231
|
-
@options.warn "Enclosing class or module %p for alias %s %s is not known" % [
|
|
232
|
-
var_name, new_name, old_name]
|
|
233
|
-
next
|
|
216
|
+
def @enclosure_dependencies.tsort_each_child(node, &block)
|
|
217
|
+
fetch(node, []).each(&block)
|
|
218
|
+
end
|
|
234
219
|
end
|
|
235
220
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
221
|
+
##
|
|
222
|
+
# Scans #content for rb_define_alias
|
|
223
|
+
|
|
224
|
+
def do_aliases
|
|
225
|
+
@content.scan(/rb_define_alias\s*\(
|
|
226
|
+
\s*(\w+),
|
|
227
|
+
\s*"(.+?)",
|
|
228
|
+
\s*"(.+?)"
|
|
229
|
+
\s*\)/xm) do |var_name, new_name, old_name|
|
|
230
|
+
class_name = @known_classes[var_name]
|
|
231
|
+
|
|
232
|
+
unless class_name
|
|
233
|
+
@options.warn "Enclosing class or module %p for alias %s %s is not known" % [
|
|
234
|
+
var_name, new_name, old_name]
|
|
235
|
+
next
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
class_obj = find_class var_name, class_name
|
|
239
|
+
comment = find_alias_comment var_name, new_name, old_name
|
|
240
|
+
comment.normalize
|
|
241
|
+
if comment.to_s.empty? and existing_method = class_obj.method_list.find { |m| m.name == old_name}
|
|
242
|
+
comment = existing_method.comment
|
|
243
|
+
end
|
|
244
|
+
add_alias(var_name, class_obj, old_name, new_name, comment, singleton: @singleton_classes.key?(var_name))
|
|
245
|
+
end
|
|
241
246
|
end
|
|
242
|
-
add_alias(var_name, class_obj, old_name, new_name, comment)
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
248
|
+
##
|
|
249
|
+
# Add alias, either from a direct alias definition, or from two
|
|
250
|
+
# method that reference the same function.
|
|
249
251
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
def add_alias(var_name, class_obj, old_name, new_name, comment, singleton:)
|
|
253
|
+
al = Alias.new old_name, new_name, comment, singleton: singleton
|
|
254
|
+
al.record_location @top_level
|
|
255
|
+
class_obj.add_alias al
|
|
256
|
+
@stats.add_alias al
|
|
257
|
+
al
|
|
258
|
+
end
|
|
257
259
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
260
|
+
##
|
|
261
|
+
# Scans #content for rb_attr and rb_define_attr
|
|
262
|
+
|
|
263
|
+
def do_attrs
|
|
264
|
+
@content.scan(/rb_attr\s*\(
|
|
265
|
+
\s*(\w+),
|
|
266
|
+
\s*([\w"()]+),
|
|
267
|
+
#{BOOL_ARG_PATTERN},
|
|
268
|
+
#{BOOL_ARG_PATTERN},
|
|
269
|
+
\s*\w+\);/xmo) do |var_name, attr_name, read, write|
|
|
270
|
+
handle_attr var_name, attr_name, read, write
|
|
271
|
+
end
|
|
270
272
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
273
|
+
@content.scan(%r%rb_define_attr\(
|
|
274
|
+
\s*([\w\.]+),
|
|
275
|
+
\s*"([^"]+)",
|
|
276
|
+
#{BOOL_ARG_PATTERN},
|
|
277
|
+
#{BOOL_ARG_PATTERN}\);
|
|
278
|
+
%xmo) do |var_name, attr_name, read, write|
|
|
279
|
+
handle_attr var_name, attr_name, read, write
|
|
280
|
+
end
|
|
281
|
+
end
|
|
280
282
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
##
|
|
284
|
+
# Scans #content for boot_defclass
|
|
283
285
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
def do_boot_defclass
|
|
287
|
+
@content.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do
|
|
288
|
+
|var_name, class_name, parent|
|
|
289
|
+
parent = nil if parent == "0"
|
|
290
|
+
handle_class_module(var_name, :class, class_name, parent, nil)
|
|
291
|
+
end
|
|
292
|
+
end
|
|
291
293
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
294
|
+
##
|
|
295
|
+
# Scans #content for rb_define_class, boot_defclass, rb_define_class_under
|
|
296
|
+
# and rb_singleton_class
|
|
297
|
+
|
|
298
|
+
def do_classes_and_modules
|
|
299
|
+
do_boot_defclass if @file_name == "class.c"
|
|
300
|
+
|
|
301
|
+
@content.scan(
|
|
302
|
+
%r(
|
|
303
|
+
(?<open>\s*\(\s*) {0}
|
|
304
|
+
(?<close>\s*\)\s*) {0}
|
|
305
|
+
(?<name>\s*"(?<class_name>\w+)") {0}
|
|
306
|
+
(?<parent>\s*(?:
|
|
307
|
+
(?<parent_name>[\w\*\s\(\)\.\->]+) |
|
|
308
|
+
rb_path2class\s*\(\s*"(?<path>[\w:]+)"\s*\)
|
|
309
|
+
)) {0}
|
|
310
|
+
(?<under>\w+) {0}
|
|
311
|
+
|
|
312
|
+
(?<var_name>[\w\.]+)\s* =
|
|
313
|
+
\s*rb_(?:
|
|
314
|
+
define_(?:
|
|
315
|
+
class(?: # rb_define_class(name, parent_name)
|
|
316
|
+
\(\s*
|
|
317
|
+
\g<name>,
|
|
318
|
+
\g<parent>
|
|
319
|
+
\s*\)
|
|
320
|
+
|
|
|
321
|
+
_under\g<open> # rb_define_class_under(under, name, parent_name...)
|
|
322
|
+
\g<under>,
|
|
323
|
+
\g<name>,
|
|
324
|
+
\g<parent>
|
|
325
|
+
\g<close>
|
|
326
|
+
)
|
|
327
|
+
|
|
|
328
|
+
(?<module>)
|
|
329
|
+
module(?: # rb_define_module(name)
|
|
330
|
+
\g<open>
|
|
331
|
+
\g<name>
|
|
332
|
+
\g<close>
|
|
333
|
+
|
|
|
334
|
+
_under\g<open> # rb_define_module_under(under, name)
|
|
335
|
+
\g<under>,
|
|
336
|
+
\g<name>
|
|
337
|
+
\g<close>
|
|
338
|
+
)
|
|
339
|
+
)
|
|
340
|
+
|
|
|
341
|
+
(?<attributes>(?:\s*"\w+",)*\s*NULL\s*) {0}
|
|
342
|
+
struct_define(?:
|
|
343
|
+
\g<open> # rb_struct_define(name, ...)
|
|
315
344
|
\g<name>,
|
|
316
|
-
\g<parent>
|
|
317
|
-
\s*\)
|
|
318
345
|
|
|
|
319
|
-
_under\g<open> #
|
|
346
|
+
_under\g<open> # rb_struct_define_under(under, name, ...)
|
|
320
347
|
\g<under>,
|
|
321
348
|
\g<name>,
|
|
322
|
-
\g<parent>
|
|
323
|
-
\g<close>
|
|
324
|
-
)
|
|
325
|
-
|
|
|
326
|
-
(?<module>)
|
|
327
|
-
module(?: # rb_define_module(name)
|
|
328
|
-
\g<open>
|
|
329
|
-
\g<name>
|
|
330
|
-
\g<close>
|
|
331
349
|
|
|
|
332
|
-
|
|
333
|
-
\g<
|
|
334
|
-
|
|
335
|
-
|
|
350
|
+
_without_accessor(?:
|
|
351
|
+
\g<open> # rb_struct_define_without_accessor(name, parent_name, ...)
|
|
352
|
+
|
|
|
353
|
+
_under\g<open> # rb_struct_define_without_accessor_under(under, name, parent_name, ...)
|
|
354
|
+
\g<under>,
|
|
355
|
+
)
|
|
356
|
+
\g<name>,
|
|
357
|
+
\g<parent>,
|
|
358
|
+
\s*\w+, # Allocation function
|
|
336
359
|
)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
(?<attributes>(?:\s*"\w+",)*\s*NULL\s*) {0}
|
|
340
|
-
struct_define(?:
|
|
341
|
-
\g<open> # rb_struct_define(name, ...)
|
|
342
|
-
\g<name>,
|
|
343
|
-
|
|
|
344
|
-
_under\g<open> # rb_struct_define_under(under, name, ...)
|
|
345
|
-
\g<under>,
|
|
346
|
-
\g<name>,
|
|
347
|
-
|
|
|
348
|
-
_without_accessor(?:
|
|
349
|
-
\g<open> # rb_struct_define_without_accessor(name, parent_name, ...)
|
|
360
|
+
\g<attributes>
|
|
361
|
+
\g<close>
|
|
350
362
|
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
363
|
+
singleton_class\g<open> # rb_singleton_class(target_class_name)
|
|
364
|
+
(?<target_class_name>\w+)
|
|
365
|
+
\g<close>
|
|
366
|
+
)
|
|
367
|
+
)mx
|
|
368
|
+
) do
|
|
369
|
+
if target_class_name = $~[:target_class_name]
|
|
370
|
+
# rb_singleton_class(target_class_name)
|
|
371
|
+
handle_singleton $~[:var_name], target_class_name
|
|
372
|
+
next
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
var_name = $~[:var_name]
|
|
376
|
+
type = $~[:module] ? :module : :class
|
|
377
|
+
class_name = $~[:class_name]
|
|
378
|
+
parent_name = $~[:parent_name] || $~[:path]
|
|
379
|
+
under = $~[:under]
|
|
380
|
+
attributes = $~[:attributes]
|
|
381
|
+
|
|
382
|
+
handle_class_module(var_name, type, class_name, parent_name, under)
|
|
383
|
+
if attributes and !parent_name # rb_struct_define *not* without_accessor
|
|
384
|
+
true_flag = 'Qtrue'
|
|
385
|
+
attributes.scan(/"\K\w+(?=")/) do |attr_name|
|
|
386
|
+
handle_attr var_name, attr_name, true_flag, true_flag
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
371
390
|
end
|
|
372
391
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
392
|
+
##
|
|
393
|
+
# Scans #content for rb_define_variable, rb_define_readonly_variable,
|
|
394
|
+
# rb_define_const and rb_define_global_const
|
|
395
|
+
|
|
396
|
+
def do_constants
|
|
397
|
+
@content.scan(%r%\Wrb_define_
|
|
398
|
+
( variable |
|
|
399
|
+
readonly_variable |
|
|
400
|
+
const |
|
|
401
|
+
global_const )
|
|
402
|
+
\s*\(
|
|
403
|
+
(?:\s*(\w+),)?
|
|
404
|
+
\s*"(\w+)",
|
|
405
|
+
\s*(.*?)\s*\)\s*;
|
|
406
|
+
%xm) do |type, var_name, const_name, definition|
|
|
407
|
+
var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
|
|
408
|
+
type = "const" if type == "global_const"
|
|
409
|
+
handle_constants type, var_name, const_name, definition
|
|
385
410
|
end
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
end
|
|
389
411
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
\s*"(\w+)",
|
|
403
|
-
\s*(.*?)\s*\)\s*;
|
|
404
|
-
%xm) do |type, var_name, const_name, definition|
|
|
405
|
-
var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
|
|
406
|
-
type = "const" if type == "global_const"
|
|
407
|
-
handle_constants type, var_name, const_name, definition
|
|
408
|
-
end
|
|
412
|
+
@content.scan(%r%
|
|
413
|
+
\Wrb_curses_define_const
|
|
414
|
+
\s*\(
|
|
415
|
+
\s*
|
|
416
|
+
(\w+)
|
|
417
|
+
\s*
|
|
418
|
+
\)
|
|
419
|
+
\s*;%xm) do |consts|
|
|
420
|
+
const = consts.first
|
|
421
|
+
|
|
422
|
+
handle_constants 'const', 'mCurses', const, "UINT2NUM(#{const})"
|
|
423
|
+
end
|
|
409
424
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
425
|
+
@content.scan(%r%
|
|
426
|
+
\Wrb_file_const
|
|
427
|
+
\s*\(
|
|
428
|
+
\s*
|
|
429
|
+
"([^"]+)",
|
|
430
|
+
\s*
|
|
431
|
+
(.*?)
|
|
432
|
+
\s*
|
|
433
|
+
\)
|
|
434
|
+
\s*;%xm) do |name, value|
|
|
435
|
+
handle_constants 'const', 'rb_mFConst', name, value
|
|
436
|
+
end
|
|
437
|
+
end
|
|
422
438
|
|
|
423
|
-
@content.scan(%r%
|
|
424
|
-
\Wrb_file_const
|
|
425
|
-
\s*\(
|
|
426
|
-
\s*
|
|
427
|
-
"([^"]+)",
|
|
428
|
-
\s*
|
|
429
|
-
(.*?)
|
|
430
|
-
\s*
|
|
431
|
-
\)
|
|
432
|
-
\s*;%xm) do |name, value|
|
|
433
|
-
handle_constants 'const', 'rb_mFConst', name, value
|
|
434
|
-
end
|
|
435
|
-
end
|
|
436
439
|
|
|
440
|
+
##
|
|
441
|
+
# Scans #content for rb_include_module
|
|
437
442
|
|
|
438
|
-
|
|
439
|
-
|
|
443
|
+
def do_includes
|
|
444
|
+
@content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c, m|
|
|
445
|
+
next unless cls = @classes[c]
|
|
446
|
+
m = @known_classes[m] || m
|
|
440
447
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
448
|
+
comment = new_comment '', @top_level, :c
|
|
449
|
+
incl = cls.add_include Include.new(m, comment)
|
|
450
|
+
incl.record_location @top_level
|
|
451
|
+
end
|
|
452
|
+
end
|
|
445
453
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
454
|
+
##
|
|
455
|
+
# Scans #content for rb_define_method, rb_define_singleton_method,
|
|
456
|
+
# rb_define_module_function, rb_define_private_method,
|
|
457
|
+
# rb_define_global_function and define_filetest_function
|
|
458
|
+
|
|
459
|
+
def do_methods
|
|
460
|
+
@content.scan(%r%rb_define_
|
|
461
|
+
(
|
|
462
|
+
singleton_method |
|
|
463
|
+
method |
|
|
464
|
+
module_function |
|
|
465
|
+
private_method
|
|
466
|
+
)
|
|
467
|
+
\s*\(\s*([\w\.]+),
|
|
468
|
+
\s*"([^"]+)",
|
|
469
|
+
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\(|\(METHOD\))?(\w+)\)?,
|
|
470
|
+
\s*(-?\w+)\s*\)
|
|
471
|
+
(?:;\s*/[*/]\s+in\s+(\w+?\.(?:cpp|c|y)))?
|
|
472
|
+
%xm) do |type, var_name, meth_name, function, param_count, source_file|
|
|
473
|
+
|
|
474
|
+
# Ignore top-object and weird struct.c dynamic stuff
|
|
475
|
+
next if var_name == "ruby_top_self"
|
|
476
|
+
next if var_name == "nstr"
|
|
477
|
+
|
|
478
|
+
var_name = "rb_cObject" if var_name == "rb_mKernel"
|
|
479
|
+
handle_method(type, var_name, meth_name, function, param_count,
|
|
480
|
+
source_file)
|
|
481
|
+
end
|
|
451
482
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
method |
|
|
462
|
-
module_function |
|
|
463
|
-
private_method
|
|
464
|
-
)
|
|
465
|
-
\s*\(\s*([\w\.]+),
|
|
466
|
-
\s*"([^"]+)",
|
|
467
|
-
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\(|\(METHOD\))?(\w+)\)?,
|
|
468
|
-
\s*(-?\w+)\s*\)
|
|
469
|
-
(?:;\s*/[*/]\s+in\s+(\w+?\.(?:cpp|c|y)))?
|
|
470
|
-
%xm) do |type, var_name, meth_name, function, param_count, source_file|
|
|
471
|
-
|
|
472
|
-
# Ignore top-object and weird struct.c dynamic stuff
|
|
473
|
-
next if var_name == "ruby_top_self"
|
|
474
|
-
next if var_name == "nstr"
|
|
475
|
-
|
|
476
|
-
var_name = "rb_cObject" if var_name == "rb_mKernel"
|
|
477
|
-
handle_method(type, var_name, meth_name, function, param_count,
|
|
478
|
-
source_file)
|
|
479
|
-
end
|
|
483
|
+
@content.scan(%r%rb_define_global_function\s*\(
|
|
484
|
+
\s*"([^"]+)",
|
|
485
|
+
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
|
|
486
|
+
\s*(-?\w+)\s*\)
|
|
487
|
+
(?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
|
|
488
|
+
%xm) do |meth_name, function, param_count, source_file|
|
|
489
|
+
handle_method("method", "rb_mKernel", meth_name, function, param_count,
|
|
490
|
+
source_file)
|
|
491
|
+
end
|
|
480
492
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
(?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
|
|
486
|
-
%xm) do |meth_name, function, param_count, source_file|
|
|
487
|
-
handle_method("method", "rb_mKernel", meth_name, function, param_count,
|
|
488
|
-
source_file)
|
|
489
|
-
end
|
|
493
|
+
@content.scan(/define_filetest_function\s*\(
|
|
494
|
+
\s*"([^"]+)",
|
|
495
|
+
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
|
|
496
|
+
\s*(-?\w+)\s*\)/xm) do |meth_name, function, param_count|
|
|
490
497
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
498
|
+
handle_method("method", "rb_mFileTest", meth_name, function, param_count)
|
|
499
|
+
handle_method("singleton_method", "rb_cFile", meth_name, function,
|
|
500
|
+
param_count)
|
|
501
|
+
end
|
|
502
|
+
end
|
|
495
503
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
end
|
|
500
|
-
end
|
|
504
|
+
##
|
|
505
|
+
# Creates classes and module that were missing were defined due to the file
|
|
506
|
+
# order being different than the declaration order.
|
|
501
507
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
# order being different than the declaration order.
|
|
508
|
+
def do_missing
|
|
509
|
+
return if @missing_dependencies.empty?
|
|
505
510
|
|
|
506
|
-
|
|
507
|
-
|
|
511
|
+
@enclosure_dependencies.tsort.each do |in_module|
|
|
512
|
+
arguments = @missing_dependencies.delete in_module
|
|
508
513
|
|
|
509
|
-
|
|
510
|
-
arguments = @missing_dependencies.delete in_module
|
|
514
|
+
next unless arguments # dependency on existing class
|
|
511
515
|
|
|
512
|
-
|
|
516
|
+
handle_class_module(*arguments)
|
|
517
|
+
end
|
|
518
|
+
end
|
|
513
519
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
520
|
+
##
|
|
521
|
+
# Finds the comment for an alias on +class_name+ from +new_name+ to
|
|
522
|
+
# +old_name+
|
|
517
523
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
524
|
+
def find_alias_comment(class_name, new_name, old_name)
|
|
525
|
+
content =~ %r%((?>/\*.*?\*/\s+))
|
|
526
|
+
rb_define_alias\(\s*#{Regexp.escape class_name}\s*,
|
|
527
|
+
\s*"#{Regexp.escape new_name}"\s*,
|
|
528
|
+
\s*"#{Regexp.escape old_name}"\s*\);%xm
|
|
521
529
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
rb_define_alias\(\s*#{Regexp.escape class_name}\s*,
|
|
525
|
-
\s*"#{Regexp.escape new_name}"\s*,
|
|
526
|
-
\s*"#{Regexp.escape old_name}"\s*\);%xm
|
|
530
|
+
new_comment($1 || '', @top_level, :c)
|
|
531
|
+
end
|
|
527
532
|
|
|
528
|
-
|
|
529
|
-
|
|
533
|
+
##
|
|
534
|
+
# Finds a comment for rb_define_attr, rb_attr or Document-attr.
|
|
535
|
+
#
|
|
536
|
+
# +var_name+ is the C class variable the attribute is defined on.
|
|
537
|
+
# +attr_name+ is the attribute's name.
|
|
538
|
+
#
|
|
539
|
+
# +read+ and +write+ are the read/write flags ('1' or '0'). Either both or
|
|
540
|
+
# neither must be provided.
|
|
541
|
+
|
|
542
|
+
def find_attr_comment(var_name, attr_name, read = nil, write = nil)
|
|
543
|
+
attr_name = Regexp.escape attr_name
|
|
544
|
+
|
|
545
|
+
rw = if read and write
|
|
546
|
+
/\s*#{read}\s*,\s*#{write}\s*/xm
|
|
547
|
+
else
|
|
548
|
+
/.*?/m
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
comment = if @content =~ %r%((?>/\*.*?\*/\s+))
|
|
552
|
+
rb_define_attr\((?:\s*#{var_name},)?\s*
|
|
553
|
+
"#{attr_name}"\s*,
|
|
554
|
+
#{rw}\)\s*;%xm
|
|
555
|
+
$1
|
|
556
|
+
elsif @content =~ %r%((?>/\*.*?\*/\s+))
|
|
557
|
+
rb_attr\(\s*#{var_name}\s*,
|
|
558
|
+
\s*#{attr_name}\s*,
|
|
559
|
+
#{rw},.*?\)\s*;%xm
|
|
560
|
+
$1
|
|
561
|
+
elsif @content =~ %r%(/\*.*?(?:\s*\*\s*)?)
|
|
562
|
+
Document-attr:\s#{attr_name}\s*?\n
|
|
563
|
+
((?>(.|\n)*?\*/))%x
|
|
564
|
+
"#{$1}\n#{$2}"
|
|
565
|
+
else
|
|
566
|
+
''
|
|
567
|
+
end
|
|
530
568
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
#
|
|
534
|
-
# +var_name+ is the C class variable the attribute is defined on.
|
|
535
|
-
# +attr_name+ is the attribute's name.
|
|
536
|
-
#
|
|
537
|
-
# +read+ and +write+ are the read/write flags ('1' or '0'). Either both or
|
|
538
|
-
# neither must be provided.
|
|
539
|
-
|
|
540
|
-
def find_attr_comment(var_name, attr_name, read = nil, write = nil)
|
|
541
|
-
attr_name = Regexp.escape attr_name
|
|
542
|
-
|
|
543
|
-
rw = if read and write then
|
|
544
|
-
/\s*#{read}\s*,\s*#{write}\s*/xm
|
|
545
|
-
else
|
|
546
|
-
/.*?/m
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
comment = if @content =~ %r%((?>/\*.*?\*/\s+))
|
|
550
|
-
rb_define_attr\((?:\s*#{var_name},)?\s*
|
|
551
|
-
"#{attr_name}"\s*,
|
|
552
|
-
#{rw}\)\s*;%xm then
|
|
553
|
-
$1
|
|
554
|
-
elsif @content =~ %r%((?>/\*.*?\*/\s+))
|
|
555
|
-
rb_attr\(\s*#{var_name}\s*,
|
|
556
|
-
\s*#{attr_name}\s*,
|
|
557
|
-
#{rw},.*?\)\s*;%xm then
|
|
558
|
-
$1
|
|
559
|
-
elsif @content =~ %r%(/\*.*?(?:\s*\*\s*)?)
|
|
560
|
-
Document-attr:\s#{attr_name}\s*?\n
|
|
561
|
-
((?>(.|\n)*?\*/))%x then
|
|
562
|
-
"#{$1}\n#{$2}"
|
|
563
|
-
else
|
|
564
|
-
''
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
new_comment comment, @top_level, :c
|
|
568
|
-
end
|
|
569
|
+
new_comment comment, @top_level, :c
|
|
570
|
+
end
|
|
569
571
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
572
|
+
##
|
|
573
|
+
# Generate a Ruby-method table
|
|
574
|
+
|
|
575
|
+
def gen_body_table(file_content)
|
|
576
|
+
table = {}
|
|
577
|
+
file_content.scan(%r{
|
|
578
|
+
((?>/\*.*?\*/\s*)?)
|
|
579
|
+
((?:\w+\s+){0,2} VALUE\s+(\w+)
|
|
580
|
+
\s*(?:\([^\)]*\))(?:[^\);]|$))
|
|
581
|
+
| ((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+(\w+)\s+(\w+))
|
|
582
|
+
| ^\s*\#\s*define\s+(\w+)\s+(\w+)
|
|
583
|
+
}xm) do
|
|
584
|
+
case
|
|
585
|
+
when name = $3
|
|
586
|
+
table[name] = [:func_def, $1, $2, $~.offset(2)] if !(t = table[name]) || t[0] != :func_def
|
|
587
|
+
when name = $6
|
|
588
|
+
table[name] = [:macro_def, $4, $5, $~.offset(5), $7] if !(t = table[name]) || t[0] == :macro_alias
|
|
589
|
+
when name = $8
|
|
590
|
+
table[name] ||= [:macro_alias, $9]
|
|
591
|
+
end
|
|
592
|
+
end
|
|
593
|
+
table
|
|
589
594
|
end
|
|
590
|
-
end
|
|
591
|
-
table
|
|
592
|
-
end
|
|
593
595
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
+
##
|
|
597
|
+
# Find the C code corresponding to a Ruby method
|
|
596
598
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
599
|
+
def find_body(class_name, meth_name, meth_obj, file_content, quiet = false)
|
|
600
|
+
if file_content
|
|
601
|
+
@body_table ||= {}
|
|
602
|
+
@body_table[file_content] ||= gen_body_table file_content
|
|
603
|
+
type, *args = @body_table[file_content][meth_name]
|
|
604
|
+
end
|
|
603
605
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
606
|
+
case type
|
|
607
|
+
when :func_def
|
|
608
|
+
comment = new_comment args[0], @top_level, :c
|
|
609
|
+
body = args[1]
|
|
610
|
+
offset, = args[2]
|
|
609
611
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
+
# try to find the whole body
|
|
613
|
+
body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content
|
|
612
614
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
615
|
+
# The comment block may have been overridden with a 'Document-method'
|
|
616
|
+
# block. This happens in the interpreter when multiple methods are
|
|
617
|
+
# vectored through to the same C method but those methods are logically
|
|
618
|
+
# distinct (for example Kernel.hash and Kernel.object_id share the same
|
|
619
|
+
# implementation
|
|
618
620
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
+
override_comment = find_override_comment class_name, meth_obj
|
|
622
|
+
comment = override_comment if override_comment
|
|
621
623
|
|
|
622
|
-
|
|
624
|
+
find_modifiers comment, meth_obj if comment
|
|
623
625
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
626
|
+
#meth_obj.params = params
|
|
627
|
+
meth_obj.start_collecting_tokens(:c)
|
|
628
|
+
tk = { :line_no => 1, :char_no => 1, :text => body }
|
|
629
|
+
meth_obj.add_token tk
|
|
630
|
+
meth_obj.comment = comment
|
|
631
|
+
meth_obj.line = file_content[0, offset].count("\n") + 1
|
|
630
632
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
633
|
+
body
|
|
634
|
+
when :macro_def
|
|
635
|
+
comment = new_comment args[0], @top_level, :c
|
|
636
|
+
body = args[1]
|
|
637
|
+
offset, = args[2]
|
|
636
638
|
|
|
637
|
-
|
|
639
|
+
find_body class_name, args[3], meth_obj, file_content, true
|
|
638
640
|
|
|
639
|
-
|
|
641
|
+
find_modifiers comment, meth_obj
|
|
640
642
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
643
|
+
meth_obj.start_collecting_tokens(:c)
|
|
644
|
+
tk = { :line_no => 1, :char_no => 1, :text => body }
|
|
645
|
+
meth_obj.add_token tk
|
|
646
|
+
meth_obj.comment = comment
|
|
647
|
+
meth_obj.line = file_content[0, offset].count("\n") + 1
|
|
646
648
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
649
|
+
body
|
|
650
|
+
when :macro_alias
|
|
651
|
+
# with no comment we hope the aliased definition has it and use it's
|
|
652
|
+
# definition
|
|
651
653
|
|
|
652
|
-
|
|
654
|
+
body = find_body(class_name, args[0], meth_obj, file_content, true)
|
|
653
655
|
|
|
654
|
-
|
|
656
|
+
return body if body
|
|
655
657
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
658
|
+
@options.warn "No definition for #{meth_name}"
|
|
659
|
+
false
|
|
660
|
+
else # No body, but might still have an override comment
|
|
661
|
+
comment = find_override_comment class_name, meth_obj
|
|
660
662
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
663
|
+
if comment
|
|
664
|
+
find_modifiers comment, meth_obj
|
|
665
|
+
meth_obj.comment = comment
|
|
664
666
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
667
|
+
''
|
|
668
|
+
else
|
|
669
|
+
@options.warn "No definition for #{meth_name}"
|
|
670
|
+
false
|
|
671
|
+
end
|
|
672
|
+
end
|
|
669
673
|
end
|
|
670
|
-
end
|
|
671
|
-
end
|
|
672
674
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
675
|
+
##
|
|
676
|
+
# Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+
|
|
677
|
+
|
|
678
|
+
def find_class(raw_name, name, base_name = nil)
|
|
679
|
+
unless @classes[raw_name]
|
|
680
|
+
if raw_name =~ /^rb_m/
|
|
681
|
+
container = @top_level.add_module NormalModule, name
|
|
682
|
+
else
|
|
683
|
+
container = @top_level.add_class NormalClass, name
|
|
684
|
+
end
|
|
685
|
+
container.name = base_name if base_name
|
|
686
|
+
|
|
687
|
+
container.record_location @top_level
|
|
688
|
+
@top_level.add_to_classes_or_modules container
|
|
689
|
+
@classes[raw_name] = container
|
|
690
|
+
end
|
|
691
|
+
@classes[raw_name]
|
|
682
692
|
end
|
|
683
|
-
container.name = base_name if base_name
|
|
684
693
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
elsif @content =~ %r%((?>/\*.*?\*/\s+))
|
|
733
|
-
([\w\. \t]+ = \s+)?rb_define_(class|module)_under[\t\w, (]*?"(#{class_name.split('::').last})"%xm then
|
|
734
|
-
comment = $1
|
|
735
|
-
else
|
|
736
|
-
comment = ''
|
|
737
|
-
end
|
|
738
|
-
|
|
739
|
-
comment = new_comment comment, @top_level, :c
|
|
694
|
+
##
|
|
695
|
+
# Look for class or module documentation above Init_+class_name+(void),
|
|
696
|
+
# in a Document-class +class_name+ (or module) comment or above an
|
|
697
|
+
# rb_define_class (or module). If a comment is supplied above a matching
|
|
698
|
+
# Init_ and a rb_define_class the Init_ comment is used.
|
|
699
|
+
#
|
|
700
|
+
# /*
|
|
701
|
+
# * This is a comment for Foo
|
|
702
|
+
# */
|
|
703
|
+
# Init_Foo(void) {
|
|
704
|
+
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
|
|
705
|
+
# }
|
|
706
|
+
#
|
|
707
|
+
# /*
|
|
708
|
+
# * Document-class: Foo
|
|
709
|
+
# * This is a comment for Foo
|
|
710
|
+
# */
|
|
711
|
+
# Init_foo(void) {
|
|
712
|
+
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
|
|
713
|
+
# }
|
|
714
|
+
#
|
|
715
|
+
# /*
|
|
716
|
+
# * This is a comment for Foo
|
|
717
|
+
# */
|
|
718
|
+
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
|
|
719
|
+
|
|
720
|
+
def find_class_comment(class_name, class_mod)
|
|
721
|
+
comment = nil
|
|
722
|
+
|
|
723
|
+
if @content =~ %r%
|
|
724
|
+
((?>/\*.*?\*/\s+))
|
|
725
|
+
(static\s+)?
|
|
726
|
+
void\s+
|
|
727
|
+
Init(?:VM)?_(?i:#{class_name})\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xm
|
|
728
|
+
comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '')
|
|
729
|
+
elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*?
|
|
730
|
+
(?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm
|
|
731
|
+
comment = "/*\n#{$1}"
|
|
732
|
+
elsif @content =~ %r%((?>/\*.*?\*/\s+))
|
|
733
|
+
([\w\.\s]+\s* = \s+)?rb_define_(class|module)[\t (]*?"(#{class_name})"%xm
|
|
734
|
+
comment = $1
|
|
735
|
+
elsif @content =~ %r%((?>/\*.*?\*/\s+))
|
|
736
|
+
([\w\. \t]+ = \s+)?rb_define_(class|module)_under[\t\w, (]*?"(#{class_name.split('::').last})"%xm
|
|
737
|
+
comment = $1
|
|
738
|
+
else
|
|
739
|
+
comment = ''
|
|
740
|
+
end
|
|
740
741
|
|
|
741
|
-
|
|
742
|
+
comment = new_comment comment, @top_level, :c
|
|
742
743
|
|
|
743
|
-
|
|
744
|
-
end
|
|
744
|
+
look_for_directives_in class_mod, comment
|
|
745
745
|
|
|
746
|
-
|
|
747
|
-
# Generate a const table
|
|
748
|
-
|
|
749
|
-
def gen_const_table(file_content)
|
|
750
|
-
table = {}
|
|
751
|
-
@content.scan(%r{
|
|
752
|
-
(?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
753
|
-
rb_define_(?<type>\w+)\(\s*(?:\w+),\s*
|
|
754
|
-
"(?<name>\w+)"\s*,
|
|
755
|
-
.*?\)\s*;
|
|
756
|
-
| (?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
757
|
-
rb_define_global_(?<type>const)\(\s*
|
|
758
|
-
"(?<name>\w+)"\s*,
|
|
759
|
-
.*?\)\s*;
|
|
760
|
-
| (?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
761
|
-
rb_file_(?<type>const)\(\s*
|
|
762
|
-
"(?<name>\w+)"\s*,
|
|
763
|
-
.*?\)\s*;
|
|
764
|
-
| (?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
765
|
-
rb_curses_define_(?<type>const)\(\s*
|
|
766
|
-
(?<name>\w+)
|
|
767
|
-
\s*\)\s*;
|
|
768
|
-
| Document-(?:const|global|variable):\s
|
|
769
|
-
(?<name>(?:\w+::)*\w+)
|
|
770
|
-
\s*?\n(?<doc>(?>.*?\*/))
|
|
771
|
-
}mxi) do
|
|
772
|
-
name, doc, type = $~.values_at(:name, :doc, :type)
|
|
773
|
-
if type
|
|
774
|
-
table[[type, name]] = doc
|
|
775
|
-
else
|
|
776
|
-
table[name] = "/*\n" + doc
|
|
746
|
+
class_mod.add_comment comment, @top_level
|
|
777
747
|
end
|
|
778
|
-
end
|
|
779
|
-
table
|
|
780
|
-
end
|
|
781
|
-
|
|
782
|
-
##
|
|
783
|
-
# Finds a comment matching +type+ and +const_name+ either above the
|
|
784
|
-
# comment or in the matching Document- section.
|
|
785
|
-
|
|
786
|
-
def find_const_comment(type, const_name, class_name = nil)
|
|
787
|
-
@const_table ||= {}
|
|
788
|
-
@const_table[@content] ||= gen_const_table @content
|
|
789
|
-
table = @const_table[@content]
|
|
790
|
-
|
|
791
|
-
comment =
|
|
792
|
-
table[[type, const_name]] ||
|
|
793
|
-
(class_name && table[class_name + "::" + const_name]) ||
|
|
794
|
-
table[const_name] ||
|
|
795
|
-
''
|
|
796
|
-
|
|
797
|
-
new_comment comment, @top_level, :c
|
|
798
|
-
end
|
|
799
|
-
|
|
800
|
-
##
|
|
801
|
-
# Handles modifiers in +comment+ and updates +meth_obj+ as appropriate.
|
|
802
748
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
749
|
+
##
|
|
750
|
+
# Generate a const table
|
|
751
|
+
|
|
752
|
+
def gen_const_table(file_content)
|
|
753
|
+
table = {}
|
|
754
|
+
@content.scan(%r{
|
|
755
|
+
(?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
756
|
+
rb_define_(?<type>\w+)\(\s*(?:\w+),\s*
|
|
757
|
+
"(?<name>\w+)"\s*,
|
|
758
|
+
.*?\)\s*;
|
|
759
|
+
| (?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
760
|
+
rb_define_global_(?<type>const)\(\s*
|
|
761
|
+
"(?<name>\w+)"\s*,
|
|
762
|
+
.*?\)\s*;
|
|
763
|
+
| (?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
764
|
+
rb_file_(?<type>const)\(\s*
|
|
765
|
+
"(?<name>\w+)"\s*,
|
|
766
|
+
.*?\)\s*;
|
|
767
|
+
| (?<doc>(?>^\s*/\*.*?\*/\s+))
|
|
768
|
+
rb_curses_define_(?<type>const)\(\s*
|
|
769
|
+
(?<name>\w+)
|
|
770
|
+
\s*\)\s*;
|
|
771
|
+
| Document-(?:const|global|variable):\s
|
|
772
|
+
(?<name>(?:\w+::)*\w+)
|
|
773
|
+
\s*?\n(?<doc>(?>.*?\*/))
|
|
774
|
+
}mxi) do
|
|
775
|
+
name, doc, type = $~.values_at(:name, :doc, :type)
|
|
776
|
+
if type
|
|
777
|
+
table[[type, name]] = doc
|
|
778
|
+
else
|
|
779
|
+
table[name] = "/*\n" + doc
|
|
780
|
+
end
|
|
781
|
+
end
|
|
782
|
+
table
|
|
783
|
+
end
|
|
813
784
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
"/*\n#{$1}"
|
|
818
|
-
elsif @content =~ %r%Document-method:
|
|
819
|
-
\s#{name}\s*?\n((?>.*?\*/))%xm then
|
|
820
|
-
"/*\n#{$1}"
|
|
821
|
-
end
|
|
785
|
+
##
|
|
786
|
+
# Finds a comment matching +type+ and +const_name+ either above the
|
|
787
|
+
# comment or in the matching Document- section.
|
|
822
788
|
|
|
823
|
-
|
|
789
|
+
def find_const_comment(type, const_name, class_name = nil)
|
|
790
|
+
@const_table ||= {}
|
|
791
|
+
@const_table[@content] ||= gen_const_table @content
|
|
792
|
+
table = @const_table[@content]
|
|
824
793
|
|
|
825
|
-
|
|
826
|
-
|
|
794
|
+
comment =
|
|
795
|
+
table[[type, const_name]] ||
|
|
796
|
+
(class_name && table[class_name + "::" + const_name]) ||
|
|
797
|
+
table[const_name] ||
|
|
798
|
+
''
|
|
827
799
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
# +read+, +write+ or both
|
|
800
|
+
new_comment comment, @top_level, :c
|
|
801
|
+
end
|
|
831
802
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
rw += 'R' if TRUE_VALUES.include?(read)
|
|
835
|
-
rw += 'W' if TRUE_VALUES.include?(write)
|
|
803
|
+
##
|
|
804
|
+
# Handles modifiers in +comment+ and updates +meth_obj+ as appropriate.
|
|
836
805
|
|
|
837
|
-
|
|
806
|
+
def find_modifiers(comment, meth_obj)
|
|
807
|
+
look_for_directives_in meth_obj, comment
|
|
808
|
+
end
|
|
838
809
|
|
|
839
|
-
|
|
810
|
+
##
|
|
811
|
+
# Finds a <tt>Document-method</tt> override for +meth_obj+ on +class_name+
|
|
840
812
|
|
|
841
|
-
|
|
813
|
+
def find_override_comment(class_name, meth_obj)
|
|
814
|
+
name = Regexp.escape meth_obj.name
|
|
815
|
+
prefix = Regexp.escape meth_obj.name_prefix
|
|
842
816
|
|
|
843
|
-
|
|
817
|
+
comment = if @content =~ %r%Document-method:
|
|
818
|
+
\s+#{class_name}#{prefix}#{name}
|
|
819
|
+
\s*?\n((?>.*?\*/))%xm
|
|
820
|
+
"/*\n#{$1}"
|
|
821
|
+
elsif @content =~ %r%Document-method:
|
|
822
|
+
\s#{name}\s*?\n((?>.*?\*/))%xm
|
|
823
|
+
"/*\n#{$1}"
|
|
824
|
+
end
|
|
844
825
|
|
|
845
|
-
|
|
846
|
-
comment.normalize
|
|
826
|
+
return unless comment
|
|
847
827
|
|
|
848
|
-
|
|
828
|
+
new_comment comment, @top_level, :c
|
|
829
|
+
end
|
|
849
830
|
|
|
850
|
-
|
|
831
|
+
##
|
|
832
|
+
# Creates a new RDoc::Attr +attr_name+ on class +var_name+ that is either
|
|
833
|
+
# +read+, +write+ or both
|
|
851
834
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
835
|
+
def handle_attr(var_name, attr_name, read, write)
|
|
836
|
+
rw = ''
|
|
837
|
+
rw += 'R' if TRUE_VALUES.include?(read)
|
|
838
|
+
rw += 'W' if TRUE_VALUES.include?(write)
|
|
856
839
|
|
|
857
|
-
|
|
858
|
-
# Creates a new RDoc::NormalClass or RDoc::NormalModule based on +type+
|
|
859
|
-
# named +class_name+ in +parent+ which was assigned to the C +var_name+.
|
|
840
|
+
class_name = @known_classes[var_name]
|
|
860
841
|
|
|
861
|
-
|
|
862
|
-
parent_name = @known_classes[parent] || parent
|
|
842
|
+
return unless class_name
|
|
863
843
|
|
|
864
|
-
|
|
865
|
-
enclosure = @classes[in_module] || @store.find_c_enclosure(in_module)
|
|
844
|
+
class_obj = find_class var_name, class_name
|
|
866
845
|
|
|
867
|
-
|
|
868
|
-
enc_type = /^rb_m/ =~ in_module ? :module : :class
|
|
869
|
-
handle_class_module in_module, enc_type, enclosure, nil, nil
|
|
870
|
-
enclosure = @classes[in_module]
|
|
871
|
-
end
|
|
846
|
+
return unless class_obj
|
|
872
847
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
@missing_dependencies[var_name] =
|
|
876
|
-
[var_name, type, class_name, parent, in_module]
|
|
848
|
+
comment = find_attr_comment var_name, attr_name
|
|
849
|
+
comment.normalize
|
|
877
850
|
|
|
878
|
-
|
|
879
|
-
end
|
|
880
|
-
else
|
|
881
|
-
enclosure = @top_level
|
|
882
|
-
end
|
|
851
|
+
name = attr_name.gsub(/rb_intern(?:_const)?\("([^"]+)"\)/, '\1')
|
|
883
852
|
|
|
884
|
-
|
|
885
|
-
full_name = if RDoc::ClassModule === enclosure then
|
|
886
|
-
enclosure.full_name + "::#{class_name}"
|
|
887
|
-
else
|
|
888
|
-
class_name
|
|
889
|
-
end
|
|
853
|
+
attr = Attr.new name, rw, comment
|
|
890
854
|
|
|
891
|
-
|
|
892
|
-
|
|
855
|
+
attr.record_location @top_level
|
|
856
|
+
class_obj.add_attribute attr
|
|
857
|
+
@stats.add_attribute attr
|
|
893
858
|
end
|
|
894
859
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
end
|
|
860
|
+
##
|
|
861
|
+
# Creates a new RDoc::NormalClass or RDoc::NormalModule based on +type+
|
|
862
|
+
# named +class_name+ in +parent+ which was assigned to the C +var_name+.
|
|
899
863
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
find_class_comment cm.full_name, cm
|
|
903
|
-
|
|
904
|
-
case cm
|
|
905
|
-
when RDoc::NormalClass
|
|
906
|
-
@stats.add_class cm
|
|
907
|
-
when RDoc::NormalModule
|
|
908
|
-
@stats.add_module cm
|
|
909
|
-
end
|
|
910
|
-
|
|
911
|
-
@classes[var_name] = cm
|
|
912
|
-
@known_classes[var_name] = cm.full_name
|
|
913
|
-
@store.add_c_enclosure var_name, cm
|
|
914
|
-
end
|
|
864
|
+
def handle_class_module(var_name, type, class_name, parent, in_module)
|
|
865
|
+
parent_name = @known_classes[parent] || parent
|
|
915
866
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
# can override the C value of the comment to give a friendly definition.
|
|
919
|
-
#
|
|
920
|
-
# /* 300: The perfect score in bowling */
|
|
921
|
-
# rb_define_const(cFoo, "PERFECT", INT2FIX(300));
|
|
922
|
-
#
|
|
923
|
-
# Will override <tt>INT2FIX(300)</tt> with the value +300+ in the output
|
|
924
|
-
# RDoc. Values may include quotes and escaped colons (\:).
|
|
867
|
+
if in_module
|
|
868
|
+
enclosure = @classes[in_module] || @store.find_c_enclosure(in_module)
|
|
925
869
|
|
|
926
|
-
|
|
927
|
-
|
|
870
|
+
if enclosure.nil? and enclosure = @known_classes[in_module]
|
|
871
|
+
enc_type = /^rb_m/ =~ in_module ? :module : :class
|
|
872
|
+
handle_class_module in_module, enc_type, enclosure, nil, nil
|
|
873
|
+
enclosure = @classes[in_module]
|
|
874
|
+
end
|
|
928
875
|
|
|
929
|
-
|
|
876
|
+
unless enclosure
|
|
877
|
+
@enclosure_dependencies[in_module] << var_name
|
|
878
|
+
@missing_dependencies[var_name] =
|
|
879
|
+
[var_name, type, class_name, parent, in_module]
|
|
930
880
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
end
|
|
881
|
+
return
|
|
882
|
+
end
|
|
883
|
+
else
|
|
884
|
+
enclosure = @top_level
|
|
885
|
+
end
|
|
937
886
|
|
|
938
|
-
|
|
939
|
-
|
|
887
|
+
if type == :class
|
|
888
|
+
full_name = if ClassModule === enclosure
|
|
889
|
+
enclosure.full_name + "::#{class_name}"
|
|
890
|
+
else
|
|
891
|
+
class_name
|
|
892
|
+
end
|
|
940
893
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
if type.downcase == 'const' then
|
|
945
|
-
if /\A(.+?)?:(?!\S)/ =~ comment.text
|
|
946
|
-
new_definition, new_comment = $1, $'
|
|
894
|
+
if @content =~ %r%Document-class:\s+#{full_name}\s*<\s+([:,\w]+)%
|
|
895
|
+
parent_name = $1
|
|
896
|
+
end
|
|
947
897
|
|
|
948
|
-
|
|
949
|
-
new_definition = definition
|
|
898
|
+
cm = enclosure.add_class NormalClass, class_name, parent_name
|
|
950
899
|
else
|
|
951
|
-
|
|
900
|
+
cm = enclosure.add_module NormalModule, class_name
|
|
952
901
|
end
|
|
953
902
|
|
|
954
|
-
|
|
903
|
+
cm.record_location enclosure.top_level
|
|
904
|
+
enclosure.top_level.add_to_classes_or_modules cm
|
|
955
905
|
|
|
956
|
-
|
|
906
|
+
find_class_comment cm.full_name, cm
|
|
957
907
|
|
|
958
|
-
|
|
908
|
+
case cm
|
|
909
|
+
when NormalClass
|
|
910
|
+
@stats.add_class cm
|
|
911
|
+
when NormalModule
|
|
912
|
+
@stats.add_module cm
|
|
913
|
+
end
|
|
959
914
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
915
|
+
@classes[var_name] = cm
|
|
916
|
+
@known_classes[var_name] = cm.full_name
|
|
917
|
+
@store.add_c_enclosure var_name, cm
|
|
963
918
|
end
|
|
964
|
-
else
|
|
965
|
-
con = RDoc::Constant.new const_name, definition, comment
|
|
966
|
-
end
|
|
967
919
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
920
|
+
##
|
|
921
|
+
# Adds constants. By providing some_value: at the start of the comment you
|
|
922
|
+
# can override the C value of the comment to give a friendly definition.
|
|
923
|
+
#
|
|
924
|
+
# /* 300: The perfect score in bowling */
|
|
925
|
+
# rb_define_const(cFoo, "PERFECT", INT2FIX(300));
|
|
926
|
+
#
|
|
927
|
+
# Will override <tt>INT2FIX(300)</tt> with the value +300+ in the output
|
|
928
|
+
# RDoc. Values may include quotes and escaped colons (\:).
|
|
972
929
|
|
|
973
|
-
|
|
974
|
-
|
|
930
|
+
def handle_constants(type, var_name, const_name, definition)
|
|
931
|
+
class_name = @known_classes[var_name]
|
|
975
932
|
|
|
976
|
-
|
|
977
|
-
body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1')
|
|
978
|
-
end
|
|
933
|
+
return unless class_name
|
|
979
934
|
|
|
980
|
-
|
|
981
|
-
# Adds an RDoc::AnyMethod +meth_name+ defined on a class or module assigned
|
|
982
|
-
# to +var_name+. +type+ is the type of method definition function used.
|
|
983
|
-
# +singleton_method+ and +module_function+ create a singleton method.
|
|
935
|
+
class_obj = find_class var_name, class_name, class_name[/::\K[^:]+\z/]
|
|
984
936
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
937
|
+
unless class_obj
|
|
938
|
+
@options.warn 'Enclosing class or module %p is not known' % [const_name]
|
|
939
|
+
return
|
|
940
|
+
end
|
|
989
941
|
|
|
990
|
-
|
|
942
|
+
comment = find_const_comment type, const_name, class_name
|
|
943
|
+
comment.normalize
|
|
991
944
|
|
|
992
|
-
|
|
945
|
+
# In the case of rb_define_const, the definition and comment are in
|
|
946
|
+
# "/* definition: comment */" form. The literal ':' and '\' characters
|
|
947
|
+
# can be escaped with a backslash.
|
|
948
|
+
if type.downcase == 'const'
|
|
949
|
+
if /\A(.+?)?:(?!\S)/ =~ comment.text
|
|
950
|
+
new_definition, new_comment = $1, $'
|
|
993
951
|
|
|
994
|
-
|
|
952
|
+
if !new_definition # Default to literal C definition
|
|
953
|
+
new_definition = definition
|
|
954
|
+
else
|
|
955
|
+
new_definition = new_definition.gsub(/\\([\\:])/, '\1')
|
|
956
|
+
end
|
|
995
957
|
|
|
996
|
-
|
|
997
|
-
add_alias(var_name, class_obj, existing_method.name, meth_name, existing_method.comment)
|
|
998
|
-
end
|
|
958
|
+
new_definition.sub!(/\A(\s+)/, '')
|
|
999
959
|
|
|
1000
|
-
|
|
1001
|
-
if meth_name == 'initialize' then
|
|
1002
|
-
meth_name = 'new'
|
|
1003
|
-
singleton = true
|
|
1004
|
-
type = 'method' # force public
|
|
1005
|
-
end
|
|
960
|
+
new_comment = "#{$1}#{new_comment.lstrip}"
|
|
1006
961
|
|
|
1007
|
-
|
|
1008
|
-
meth_obj = RDoc::AnyMethod.new '', meth_name, singleton: singleton
|
|
1009
|
-
meth_obj.c_function = function
|
|
962
|
+
new_comment = self.new_comment(new_comment, @top_level, :c)
|
|
1010
963
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
if File.exist? file_name then
|
|
1017
|
-
file_content = File.read file_name
|
|
964
|
+
con = Constant.new const_name, new_definition, new_comment
|
|
965
|
+
else
|
|
966
|
+
con = Constant.new const_name, definition, comment
|
|
967
|
+
end
|
|
1018
968
|
else
|
|
1019
|
-
|
|
969
|
+
con = Constant.new const_name, definition, comment
|
|
1020
970
|
end
|
|
1021
|
-
|
|
1022
|
-
|
|
971
|
+
|
|
972
|
+
con.record_location @top_level
|
|
973
|
+
@stats.add_constant con
|
|
974
|
+
class_obj.add_constant con
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
##
|
|
978
|
+
# Removes #ifdefs that would otherwise confuse us
|
|
979
|
+
|
|
980
|
+
def handle_ifdefs_in(body)
|
|
981
|
+
body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1')
|
|
1023
982
|
end
|
|
1024
983
|
|
|
1025
|
-
|
|
984
|
+
##
|
|
985
|
+
# Adds an RDoc::AnyMethod +meth_name+ defined on a class or module assigned
|
|
986
|
+
# to +var_name+. +type+ is the type of method definition function used.
|
|
987
|
+
# +singleton_method+ and +module_function+ create a singleton method.
|
|
988
|
+
|
|
989
|
+
def handle_method(type, var_name, meth_name, function, param_count,
|
|
990
|
+
source_file = nil)
|
|
991
|
+
class_name = @known_classes[var_name]
|
|
992
|
+
singleton = @singleton_classes.key?(var_name) || %w[singleton_method module_function].include?(type)
|
|
1026
993
|
|
|
1027
|
-
|
|
1028
|
-
meth_obj.params = if p_count < -1 then # -2 is Array
|
|
1029
|
-
'(*args)'
|
|
1030
|
-
elsif p_count == -1 then # argc, argv
|
|
1031
|
-
rb_scan_args body
|
|
1032
|
-
else
|
|
1033
|
-
args = (1..p_count).map { |i| "p#{i}" }
|
|
1034
|
-
"(#{args.join ', '})"
|
|
1035
|
-
end
|
|
994
|
+
@methods[var_name][function] << meth_name
|
|
1036
995
|
|
|
996
|
+
return unless class_name
|
|
1037
997
|
|
|
1038
|
-
|
|
998
|
+
class_obj = find_class var_name, class_name
|
|
1039
999
|
|
|
1040
|
-
if
|
|
1041
|
-
class_obj.
|
|
1000
|
+
if existing_method = class_obj.method_list.find { |m| m.c_function == function && m.singleton == singleton }
|
|
1001
|
+
add_alias(var_name, class_obj, existing_method.name, meth_name, existing_method.comment, singleton: singleton)
|
|
1042
1002
|
end
|
|
1043
|
-
class_obj.add_method meth_obj
|
|
1044
1003
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1004
|
+
if class_obj
|
|
1005
|
+
if meth_name == 'initialize'
|
|
1006
|
+
meth_name = 'new'
|
|
1007
|
+
singleton = true
|
|
1008
|
+
type = 'method' # force public
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
meth_obj = AnyMethod.new meth_name, singleton: singleton
|
|
1012
|
+
meth_obj.c_function = function
|
|
1013
|
+
|
|
1014
|
+
p_count = Integer(param_count) rescue -1
|
|
1015
|
+
|
|
1016
|
+
if source_file
|
|
1017
|
+
file_name = File.join @file_dir, source_file
|
|
1018
|
+
|
|
1019
|
+
if File.exist? file_name
|
|
1020
|
+
file_content = Encoding.read_file file_name, @options.encoding
|
|
1021
|
+
else
|
|
1022
|
+
@options.warn "unknown source #{source_file} for #{meth_name} in #{@file_name}"
|
|
1023
|
+
end
|
|
1024
|
+
else
|
|
1025
|
+
file_content = @content
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
body = find_body class_name, function, meth_obj, file_content
|
|
1029
|
+
|
|
1030
|
+
if body and meth_obj.document_self
|
|
1031
|
+
meth_obj.params = if p_count < -1 # -2 is Array
|
|
1032
|
+
'(*args)'
|
|
1033
|
+
elsif p_count == -1 # argc, argv
|
|
1034
|
+
rb_scan_args body
|
|
1035
|
+
else
|
|
1036
|
+
args = (1..p_count).map { |i| "p#{i}" }
|
|
1037
|
+
"(#{args.join ', '})"
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
meth_obj.record_location @top_level
|
|
1042
|
+
|
|
1043
|
+
if meth_obj.section_title
|
|
1044
|
+
class_obj.temporary_section = class_obj.add_section(meth_obj.section_title)
|
|
1045
|
+
end
|
|
1046
|
+
meth_obj.visibility = type == 'private_method' ? :private : :public
|
|
1047
|
+
class_obj.add_method meth_obj
|
|
1048
|
+
@stats.add_method meth_obj
|
|
1049
|
+
end
|
|
1050
|
+
end
|
|
1047
1051
|
end
|
|
1048
|
-
end
|
|
1049
|
-
end
|
|
1050
1052
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
+
##
|
|
1054
|
+
# Registers a singleton class +sclass_var+ as a singleton of +class_var+
|
|
1053
1055
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1056
|
+
def handle_singleton(sclass_var, class_var)
|
|
1057
|
+
if (klass = @classes[class_var])
|
|
1058
|
+
@classes[sclass_var] = klass
|
|
1059
|
+
end
|
|
1060
|
+
if (class_name = @known_classes[class_var])
|
|
1061
|
+
@known_classes[sclass_var] = class_name
|
|
1062
|
+
@singleton_classes[sclass_var] = class_name
|
|
1063
|
+
end
|
|
1064
|
+
end
|
|
1063
1065
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1066
|
+
##
|
|
1067
|
+
# Loads the variable map with the given +name+ from the RDoc::Store, if
|
|
1068
|
+
# present.
|
|
1067
1069
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1070
|
+
def load_variable_map(map_name)
|
|
1071
|
+
return {} unless files = @store.cache[map_name]
|
|
1072
|
+
return {} unless name_map = files[@file_name]
|
|
1071
1073
|
|
|
1072
|
-
|
|
1074
|
+
class_map = {}
|
|
1073
1075
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
+
name_map.each do |variable, name|
|
|
1077
|
+
next unless mod = @store.find_class_or_module(name)
|
|
1076
1078
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1079
|
+
class_map[variable] = if map_name == :c_class_variables
|
|
1080
|
+
mod
|
|
1081
|
+
else
|
|
1082
|
+
name
|
|
1083
|
+
end
|
|
1084
|
+
@known_classes[variable] = name
|
|
1085
|
+
end
|
|
1084
1086
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
+
class_map
|
|
1088
|
+
end
|
|
1087
1089
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
end
|
|
1090
|
+
##
|
|
1091
|
+
# Look for directives in a normal comment block:
|
|
1092
|
+
#
|
|
1093
|
+
# /*
|
|
1094
|
+
# * :nodoc:
|
|
1095
|
+
# */
|
|
1096
|
+
#
|
|
1097
|
+
# This method modifies the +comment+
|
|
1098
|
+
|
|
1099
|
+
def look_for_directives_in(context, comment)
|
|
1100
|
+
comment.text, format = @preprocess.run_pre_processes(comment.text, context, comment.line || 1, :c)
|
|
1101
|
+
comment.format = format if format
|
|
1102
|
+
@preprocess.run_post_processes(comment, context)
|
|
1103
|
+
comment.normalized = true
|
|
1104
|
+
comment
|
|
1105
|
+
end
|
|
1105
1106
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1107
|
+
##
|
|
1108
|
+
# Extracts parameters from the +method_body+ and returns a method
|
|
1109
|
+
# parameter string. Follows 1.9.3dev's scan-arg-spec, see README.EXT
|
|
1109
1110
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1111
|
+
def rb_scan_args(method_body)
|
|
1112
|
+
method_body =~ /rb_scan_args\((.*?)\)/m
|
|
1113
|
+
return '(*args)' unless $1
|
|
1113
1114
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1115
|
+
$1.split(/,/)[2] =~ /"(.*?)"/ # format argument
|
|
1116
|
+
format = $1.split(//)
|
|
1116
1117
|
|
|
1117
|
-
|
|
1118
|
+
lead = opt = trail = 0
|
|
1118
1119
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
format.shift
|
|
1122
|
-
if format.first =~ /\d/ then
|
|
1123
|
-
opt = $&.to_i
|
|
1124
|
-
format.shift
|
|
1125
|
-
if format.first =~ /\d/ then
|
|
1126
|
-
trail = $&.to_i
|
|
1120
|
+
if format.first =~ /\d/
|
|
1121
|
+
lead = $&.to_i
|
|
1127
1122
|
format.shift
|
|
1128
|
-
|
|
1123
|
+
if format.first =~ /\d/
|
|
1124
|
+
opt = $&.to_i
|
|
1125
|
+
format.shift
|
|
1126
|
+
if format.first =~ /\d/
|
|
1127
|
+
trail = $&.to_i
|
|
1128
|
+
format.shift
|
|
1129
|
+
block_arg = true
|
|
1130
|
+
end
|
|
1131
|
+
end
|
|
1129
1132
|
end
|
|
1130
|
-
end
|
|
1131
|
-
end
|
|
1132
1133
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1134
|
+
if format.first == '*' and not block_arg
|
|
1135
|
+
var = true
|
|
1136
|
+
format.shift
|
|
1137
|
+
if format.first =~ /\d/
|
|
1138
|
+
trail = $&.to_i
|
|
1139
|
+
format.shift
|
|
1140
|
+
end
|
|
1141
|
+
end
|
|
1141
1142
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1143
|
+
if format.first == ':'
|
|
1144
|
+
hash = true
|
|
1145
|
+
format.shift
|
|
1146
|
+
end
|
|
1146
1147
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1148
|
+
if format.first == '&'
|
|
1149
|
+
block = true
|
|
1150
|
+
format.shift
|
|
1151
|
+
end
|
|
1151
1152
|
|
|
1152
|
-
|
|
1153
|
+
# if the format string is not empty there's a bug in the C code, ignore it
|
|
1153
1154
|
|
|
1154
|
-
|
|
1155
|
-
|
|
1155
|
+
args = []
|
|
1156
|
+
position = 1
|
|
1156
1157
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1158
|
+
(1...(position + lead)).each do |index|
|
|
1159
|
+
args << "p#{index}"
|
|
1160
|
+
end
|
|
1160
1161
|
|
|
1161
|
-
|
|
1162
|
+
position += lead
|
|
1162
1163
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1164
|
+
(position...(position + opt)).each do |index|
|
|
1165
|
+
args << "p#{index} = v#{index}"
|
|
1166
|
+
end
|
|
1166
1167
|
|
|
1167
|
-
|
|
1168
|
+
position += opt
|
|
1168
1169
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1170
|
+
if var
|
|
1171
|
+
args << '*args'
|
|
1172
|
+
position += 1
|
|
1173
|
+
end
|
|
1173
1174
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1175
|
+
(position...(position + trail)).each do |index|
|
|
1176
|
+
args << "p#{index}"
|
|
1177
|
+
end
|
|
1177
1178
|
|
|
1178
|
-
|
|
1179
|
+
position += trail
|
|
1179
1180
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1181
|
+
if hash
|
|
1182
|
+
args << "p#{position} = {}"
|
|
1183
|
+
end
|
|
1183
1184
|
|
|
1184
|
-
|
|
1185
|
+
args << '&block' if block
|
|
1185
1186
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1187
|
+
"(#{args.join ', '})"
|
|
1188
|
+
end
|
|
1188
1189
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1190
|
+
##
|
|
1191
|
+
# Removes lines that are commented out that might otherwise get picked up
|
|
1192
|
+
# when scanning for classes and methods
|
|
1192
1193
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1194
|
+
def remove_commented_out_lines
|
|
1195
|
+
@content = @content.gsub(%r%//.*rb_define_%, '//')
|
|
1196
|
+
end
|
|
1196
1197
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1198
|
+
##
|
|
1199
|
+
# Extracts the classes, modules, methods, attributes, constants and aliases
|
|
1200
|
+
# from a C file and returns an RDoc::TopLevel for this file
|
|
1200
1201
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1202
|
+
def scan
|
|
1203
|
+
remove_commented_out_lines
|
|
1203
1204
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1205
|
+
do_classes_and_modules
|
|
1206
|
+
do_missing
|
|
1206
1207
|
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1208
|
+
do_constants
|
|
1209
|
+
do_methods
|
|
1210
|
+
do_includes
|
|
1211
|
+
do_aliases
|
|
1212
|
+
do_attrs
|
|
1212
1213
|
|
|
1213
|
-
|
|
1214
|
+
@store.add_c_variables self
|
|
1214
1215
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1216
|
+
@top_level
|
|
1217
|
+
end
|
|
1217
1218
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1219
|
+
##
|
|
1220
|
+
# Creates a RDoc::Comment instance.
|
|
1220
1221
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1222
|
+
def new_comment(text = nil, location = nil, language = nil)
|
|
1223
|
+
Comment.new(text, location, language).tap do |comment|
|
|
1224
|
+
comment.format = @markup
|
|
1225
|
+
end
|
|
1226
|
+
end
|
|
1224
1227
|
end
|
|
1225
1228
|
end
|
|
1226
1229
|
end
|