pdoc 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/README.markdown +34 -0
  2. data/Rakefile +46 -0
  3. data/bin/pdoc +58 -0
  4. data/lib/pdoc.rb +32 -0
  5. data/lib/pdoc/error.rb +4 -0
  6. data/lib/pdoc/generators.rb +6 -0
  7. data/lib/pdoc/generators/abstract_generator.rb +16 -0
  8. data/lib/pdoc/generators/html.rb +8 -0
  9. data/lib/pdoc/generators/html/helpers.rb +256 -0
  10. data/lib/pdoc/generators/html/page.rb +71 -0
  11. data/lib/pdoc/generators/html/syntax_highlighter.rb +41 -0
  12. data/lib/pdoc/generators/html/template.rb +37 -0
  13. data/lib/pdoc/generators/html/website.rb +194 -0
  14. data/lib/pdoc/generators/json.rb +15 -0
  15. data/lib/pdoc/generators/pythonesque.rb +105 -0
  16. data/lib/pdoc/models.rb +47 -0
  17. data/lib/pdoc/models/argument.rb +37 -0
  18. data/lib/pdoc/models/base.rb +107 -0
  19. data/lib/pdoc/models/callable.rb +19 -0
  20. data/lib/pdoc/models/class.rb +28 -0
  21. data/lib/pdoc/models/class_method.rb +18 -0
  22. data/lib/pdoc/models/class_property.rb +9 -0
  23. data/lib/pdoc/models/constant.rb +9 -0
  24. data/lib/pdoc/models/constructor.rb +14 -0
  25. data/lib/pdoc/models/container.rb +114 -0
  26. data/lib/pdoc/models/entity.rb +54 -0
  27. data/lib/pdoc/models/instance_method.rb +18 -0
  28. data/lib/pdoc/models/instance_property.rb +9 -0
  29. data/lib/pdoc/models/mixin.rb +10 -0
  30. data/lib/pdoc/models/namespace.rb +10 -0
  31. data/lib/pdoc/models/root.rb +27 -0
  32. data/lib/pdoc/models/section.rb +19 -0
  33. data/lib/pdoc/models/signature.rb +27 -0
  34. data/lib/pdoc/models/utility.rb +11 -0
  35. data/lib/pdoc/parser.rb +109 -0
  36. data/lib/pdoc/parser/argument_description_nodes.rb +21 -0
  37. data/lib/pdoc/parser/basic_nodes.rb +31 -0
  38. data/lib/pdoc/parser/description_nodes.rb +42 -0
  39. data/lib/pdoc/parser/documentation_nodes.rb +483 -0
  40. data/lib/pdoc/parser/ebnf_arguments_nodes.rb +58 -0
  41. data/lib/pdoc/parser/ebnf_expression_nodes.rb +227 -0
  42. data/lib/pdoc/parser/fragment.rb +55 -0
  43. data/lib/pdoc/parser/section_content_nodes.rb +19 -0
  44. data/lib/pdoc/parser/tags_nodes.rb +14 -0
  45. data/lib/pdoc/parser/treetop_files/argument_description.treetop +31 -0
  46. data/lib/pdoc/parser/treetop_files/basic.treetop +41 -0
  47. data/lib/pdoc/parser/treetop_files/description.treetop +7 -0
  48. data/lib/pdoc/parser/treetop_files/documentation.treetop +75 -0
  49. data/lib/pdoc/parser/treetop_files/ebnf_arguments.treetop +33 -0
  50. data/lib/pdoc/parser/treetop_files/ebnf_expression.treetop +70 -0
  51. data/lib/pdoc/parser/treetop_files/ebnf_javascript.treetop +54 -0
  52. data/lib/pdoc/parser/treetop_files/events.treetop +17 -0
  53. data/lib/pdoc/parser/treetop_files/section_content.treetop +8 -0
  54. data/lib/pdoc/parser/treetop_files/tags.treetop +31 -0
  55. data/lib/pdoc/runner.rb +110 -0
  56. data/lib/pdoc/treemaker.rb +94 -0
  57. data/pdoc.gemspec +31 -0
  58. data/templates/html/assets/images/pdoc/alias.png +0 -0
  59. data/templates/html/assets/images/pdoc/class.png +0 -0
  60. data/templates/html/assets/images/pdoc/class_deprecated.png +0 -0
  61. data/templates/html/assets/images/pdoc/class_method.png +0 -0
  62. data/templates/html/assets/images/pdoc/class_property.png +0 -0
  63. data/templates/html/assets/images/pdoc/constant.png +0 -0
  64. data/templates/html/assets/images/pdoc/constructor.png +0 -0
  65. data/templates/html/assets/images/pdoc/deprecated.png +0 -0
  66. data/templates/html/assets/images/pdoc/description.png +0 -0
  67. data/templates/html/assets/images/pdoc/information.png +0 -0
  68. data/templates/html/assets/images/pdoc/instance_method.png +0 -0
  69. data/templates/html/assets/images/pdoc/instance_property.png +0 -0
  70. data/templates/html/assets/images/pdoc/method.png +0 -0
  71. data/templates/html/assets/images/pdoc/method_deprecated.png +0 -0
  72. data/templates/html/assets/images/pdoc/mixin.png +0 -0
  73. data/templates/html/assets/images/pdoc/namespace.png +0 -0
  74. data/templates/html/assets/images/pdoc/property.png +0 -0
  75. data/templates/html/assets/images/pdoc/related_to.png +0 -0
  76. data/templates/html/assets/images/pdoc/search-background.png +0 -0
  77. data/templates/html/assets/images/pdoc/section-background.png +0 -0
  78. data/templates/html/assets/images/pdoc/section.png +0 -0
  79. data/templates/html/assets/images/pdoc/selected-section-background.png +0 -0
  80. data/templates/html/assets/images/pdoc/subclass.png +0 -0
  81. data/templates/html/assets/images/pdoc/superclass.png +0 -0
  82. data/templates/html/assets/images/pdoc/utility.png +0 -0
  83. data/templates/html/assets/javascripts/pdoc/application.js +478 -0
  84. data/templates/html/assets/javascripts/pdoc/prototype.js +4874 -0
  85. data/templates/html/assets/javascripts/pdoc/tabs.js +506 -0
  86. data/templates/html/assets/stylesheets/pdoc/api.css +677 -0
  87. data/templates/html/assets/stylesheets/pdoc/pygments.css +62 -0
  88. data/templates/html/helpers.rb +35 -0
  89. data/templates/html/index.erb +18 -0
  90. data/templates/html/item_index.js.erb +6 -0
  91. data/templates/html/layout.erb +67 -0
  92. data/templates/html/leaf.erb +22 -0
  93. data/templates/html/node.erb +30 -0
  94. data/templates/html/partials/class_relationships.erb +19 -0
  95. data/templates/html/partials/classes.erb +7 -0
  96. data/templates/html/partials/constructor.erb +5 -0
  97. data/templates/html/partials/description.erb +5 -0
  98. data/templates/html/partials/link_list.erb +1 -0
  99. data/templates/html/partials/method_signatures.erb +14 -0
  100. data/templates/html/partials/methodized_note.erb +9 -0
  101. data/templates/html/partials/mixins.erb +7 -0
  102. data/templates/html/partials/namespaces.erb +7 -0
  103. data/templates/html/partials/related_utilities.erb +5 -0
  104. data/templates/html/partials/relationships.erb +11 -0
  105. data/templates/html/partials/short_description_list.erb +7 -0
  106. data/templates/html/partials/title.erb +22 -0
  107. data/templates/html/section.erb +18 -0
  108. data/test/unit/parser/argument_description_test.rb +40 -0
  109. data/test/unit/parser/basic_test.rb +55 -0
  110. data/test/unit/parser/description_test.rb +34 -0
  111. data/test/unit/parser/documentation_test.rb +520 -0
  112. data/test/unit/parser/ebnf_arguments_test.rb +81 -0
  113. data/test/unit/parser/ebnf_expression_test.rb +382 -0
  114. data/test/unit/parser/ebnf_javascript_test.rb +37 -0
  115. data/test/unit/parser/events_test.rb +27 -0
  116. data/test/unit/parser/section_content_test.rb +44 -0
  117. data/test/unit/parser/tags_test.rb +39 -0
  118. data/test/unit/parser/test_fragment.rb +80 -0
  119. data/test/unit/parser_test_helper.rb +62 -0
  120. data/test/unit/runner/basic_test.rb +14 -0
  121. data/test/unit/templates/html_helpers_test.rb +25 -0
  122. metadata +222 -0
@@ -0,0 +1,18 @@
1
+ module PDoc
2
+ module Models
3
+ class InstanceMethod < Entity
4
+ include Callable
5
+ attr_accessor :functionalized_self
6
+ def attach_to_parent(parent)
7
+ parent.instance_methods << self
8
+ end
9
+
10
+ def to_hash
11
+ f = functionalized_self
12
+ super.merge({
13
+ :functionalized_self => f ? f.id : nil
14
+ })
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module PDoc
2
+ module Models
3
+ class InstanceProperty < Entity
4
+ def attach_to_parent(parent)
5
+ parent.instance_properties << self
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module PDoc
2
+ module Models
3
+ class Mixin < Entity
4
+ include Container
5
+ def attach_to_parent(parent)
6
+ parent.mixins << self
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module PDoc
2
+ module Models
3
+ class Namespace < Entity
4
+ include Container
5
+ def attach_to_parent(parent)
6
+ parent.namespaces << self
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ module PDoc
2
+ module Models
3
+ class Root
4
+ include Container
5
+
6
+ def sections
7
+ @sections ||= []
8
+ end
9
+
10
+ def sections?
11
+ @sections && !@sections.empty?
12
+ end
13
+
14
+ def registry
15
+ @registry ||= {}
16
+ end
17
+
18
+ def find(id)
19
+ registry[id]
20
+ end
21
+
22
+ def parent
23
+ nil
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module PDoc
2
+ module Models
3
+ class Section < Base
4
+ include Container
5
+
6
+ def attach_to_parent(parent)
7
+ parent.sections << self
8
+ end
9
+
10
+ def name
11
+ @name ||= @id.sub(' section', '')
12
+ end
13
+
14
+ def normalized_name
15
+ super.downcase
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module PDoc
2
+ module Models
3
+ class Signature < Base
4
+ attr_reader :return_value
5
+ def attach_to_parent(parent)
6
+ parent.signatures << self
7
+ end
8
+
9
+ #TODO API cleanup
10
+
11
+ def to_s
12
+ @signature
13
+ end
14
+
15
+ def name
16
+ @signature
17
+ end
18
+
19
+ def to_hash
20
+ {
21
+ :name => name,
22
+ :return_value => return_value
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module PDoc
2
+ module Models
3
+ class Utility < Entity
4
+ include Callable
5
+
6
+ def attach_to_parent(parent)
7
+ parent.utilities << self
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,109 @@
1
+ require 'rubygems'
2
+ require 'treetop'
3
+
4
+ FILE_NAMES = %w[basic tags argument_description description ebnf_arguments ebnf_expression section_content documentation]
5
+
6
+ FILE_NAMES.each { |file_name| require "#{file_name}_nodes" }
7
+
8
+ %w[ebnf_javascript events].concat(FILE_NAMES).each do |file_name|
9
+ Treetop.load File.expand_path(File.join(PARSER_DIR, "treetop_files", file_name))
10
+ end
11
+
12
+ module PDoc
13
+ class Parser
14
+ def initialize(string)
15
+ @string = string
16
+ @parser = DocumentationParser.new
17
+ @percentage = 0
18
+ end
19
+
20
+ # Parses the preprocessed string. Returns an instance
21
+ # of Documentation::Doc
22
+ def parse
23
+ @finished = false
24
+ result = @parser.parse(pre_process)
25
+ @finished = true
26
+ raise ParseError, @parser unless result
27
+ result
28
+ end
29
+
30
+ # Preprocess the string before parsing.
31
+ # Converts "\r\n" to "\n" and avoids edge case
32
+ # by wrapping the string in line breaks.
33
+ def pre_process
34
+ string = @string.gsub(/\r\n/, "\n")
35
+ string = string.split("\n").map do |line|
36
+ line.gsub(/\s+$/, '')
37
+ end.join("\n")
38
+ "\n#{string}\n"
39
+ end
40
+
41
+ def completion_percentage
42
+ if @parser.index
43
+ ratio = @parser.index.to_f / @parser.input.size.to_f
44
+ percentage = (ratio * 100).floor
45
+ @percentage = percentage if percentage > @percentage
46
+ end
47
+ "#{@percentage}%"
48
+ end
49
+
50
+ def finished?
51
+ @finished
52
+ end
53
+ end
54
+
55
+ # Thrown by PDoc::Parser if the documentation is malformed.
56
+ class ParseError < StandardError
57
+ def initialize(parser)
58
+ @parser = parser
59
+ @lines = @parser.input.split("\n").unshift("")
60
+ end
61
+
62
+ def message
63
+ <<-EOS
64
+
65
+ ParseError: Expected #{expected_string} at line #{line}, column #{column} (byte #{index + 1}) after #{@parser.input[@parser.index...index].inspect}.
66
+
67
+ #{source_code}
68
+
69
+ EOS
70
+ end
71
+
72
+ def line
73
+ @parser.failure_line
74
+ end
75
+
76
+ def column
77
+ @parser.failure_column
78
+ end
79
+
80
+ def failures
81
+ @parser.terminal_failures
82
+ end
83
+
84
+ def index
85
+ @parser.failure_index
86
+ end
87
+
88
+ def source_code
89
+ ((line-2)..(line+2)).map do |index|
90
+ result = index == line ? "-->" : " "
91
+ "#{result} #{index.to_s.rjust(5)} #{@lines[index]}"
92
+ end.join("\n")
93
+ end
94
+
95
+ def failure_reason
96
+ ""
97
+ end
98
+
99
+ def expected_string
100
+ if failures.size == 1
101
+ failures.first.expected_string.inspect
102
+ else
103
+ expected = failures.map { |f| f.expected_string.inspect }.uniq
104
+ last = expected.pop
105
+ "one of #{expected.join(', ')} or #{last}"
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,21 @@
1
+ module ArgumentDescription
2
+ class ArgumentDescription < Treetop::Runtime::SyntaxNode
3
+ def name
4
+ first.argument_name.name.text_value
5
+ end
6
+
7
+ def types
8
+ if first.arg_types.empty?
9
+ []
10
+ else
11
+ args = first.arg_types.elements.last
12
+ [args.argument_type.text_value].concat(args.more.elements.map{ |e| e.argument_type.text_value })
13
+ end
14
+ end
15
+
16
+ def description
17
+ more_lines = more.elements.map{ |l| l.to_s.strip }.reject { |l| l.empty? }
18
+ [first.description.text_value.strip].concat(more_lines).join(" ")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module Basic
2
+ class BlankLine < Treetop::Runtime::SyntaxNode
3
+ def to_s
4
+ ""
5
+ end
6
+ end
7
+
8
+ class TextLine < Treetop::Runtime::SyntaxNode
9
+ def to_s
10
+ text.text_value
11
+ end
12
+ end
13
+
14
+ class Line < Treetop::Runtime::SyntaxNode
15
+ end
16
+
17
+ class CommentStart < Treetop::Runtime::SyntaxNode
18
+ end
19
+
20
+ class CommentEnd < Treetop::Runtime::SyntaxNode
21
+ end
22
+
23
+ class LineBreak < Treetop::Runtime::SyntaxNode
24
+ end
25
+
26
+ class Char < Treetop::Runtime::SyntaxNode
27
+ end
28
+
29
+ class Space < Treetop::Runtime::SyntaxNode
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ module Description
2
+ class Text < Treetop::Runtime::SyntaxNode
3
+ include Enumerable
4
+ def each
5
+ elements.map { |e| e.to_s }.each { |tag| yield tag }
6
+ end
7
+
8
+ def join(sep = "\n")
9
+ outdent.join(sep).strip
10
+ end
11
+
12
+ def to_s
13
+ join
14
+ end
15
+
16
+ def excerpt
17
+
18
+ end
19
+
20
+ def inspect
21
+ text = truncate(15).gsub(/\n/, " ").strip.inspect
22
+ "#<#{self.class} #{text}>"
23
+ end
24
+
25
+ def truncate(num = 30)
26
+ to_s.length < num ? to_s : to_s.slice(0..num) << "..."
27
+ end
28
+
29
+ def outdent
30
+ range = tab_length..-1
31
+ map { |l| l.slice(range) }
32
+ end
33
+
34
+ private
35
+ def tab_length
36
+ reject { |l| l =~ /^\s*$/ }.map do |line|
37
+ line = line.slice(/^\s*/)
38
+ line ? line.length : 0
39
+ end.min || 0
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,483 @@
1
+ module Documentation
2
+ class Doc < Treetop::Runtime::SyntaxNode
3
+ include Enumerable
4
+
5
+ def tags
6
+ @tags ||= elements.first.elements.map { |e| e.elements.last }
7
+ end
8
+
9
+ def each
10
+ tags.each { |tag| yield tag }
11
+ end
12
+
13
+ # find_by_name allows you to search through all the documented instances based on the
14
+ # instances Base#full_name.
15
+ # For example:
16
+ #
17
+ # PDoc::Parser.new("prototype.js").parse.root.find_by_name("Element#update")
18
+ #
19
+ # Return an instance of InstanceMethod corresponding to "Element#update".
20
+ def find_by_name(name)
21
+ find { |e| e.full_name == name }
22
+ end
23
+
24
+ def inspect
25
+ to_a.inspect
26
+ end
27
+
28
+ # Returns the total number of documented instances
29
+ def size
30
+ to_a.length
31
+ end
32
+
33
+ def name
34
+ "Home"
35
+ end
36
+
37
+ def serialize(serializer)
38
+ each { |obj| obj.serialize(serializer) }
39
+ end
40
+ end
41
+
42
+ module Memoized
43
+ def method_added(method_name)
44
+ if instance_method(method_name).arity.zero?
45
+ avoid_infinite_method_added_loop do
46
+ memoize(method_name)
47
+ end
48
+ end
49
+ end
50
+
51
+ def memoize(method_name)
52
+ sanitized_name = method_name.to_s
53
+ sanitized_name = sanitized_name.sub(/!$/, '_bang')
54
+ sanitized_name = sanitized_name.sub(/\?$/, '_question_mark')
55
+ complete_name = "#{sanitized_name}_#{object_id.abs}"
56
+
57
+ class_eval(<<-EVAL, __FILE__, __LINE__)
58
+ alias compute_#{complete_name} #{method_name} # alias compute_section_12235760 section
59
+ #
60
+ def #{method_name} # def section
61
+ unless defined?(@#{complete_name}) # unless defined?(@section_12235760)
62
+ @#{complete_name} = compute_#{complete_name} # @section_12235760 = compute_section_12235760
63
+ end # end
64
+ @#{complete_name} # @section_12235760
65
+ end # end
66
+ EVAL
67
+ end
68
+
69
+ def avoid_infinite_method_added_loop
70
+ unless @memoizing
71
+ @memoizing = true
72
+ yield
73
+ @memoizing = false
74
+ end
75
+ end
76
+ end
77
+
78
+ class Base < Treetop::Runtime::SyntaxNode
79
+ extend Memoized
80
+
81
+ # Returns an instance of Doc (the root of the tree outputed by the PDoc::Parser).
82
+ def root
83
+ parent.parent.parent
84
+ end
85
+
86
+ # True if the instance was tagged as deprecated.
87
+ def deprecated?
88
+ tags.include?("deprecated")
89
+ end
90
+
91
+ # If instance is tagged as an alias, alias_of returns the corresponding object.
92
+ # It will return nil otherwise.
93
+ def alias_of
94
+ tag = tags.find { |tag| tag.name == "alias of" }
95
+ tag.value if tag
96
+ end
97
+
98
+ def related_to
99
+ tag = tags.find { |tag| tag.name == "related to" }
100
+ tag.value if tag
101
+ end
102
+
103
+ # Returns an instance of Tags::Tags.
104
+ def tags
105
+ start.elements.last.empty? ? [] : start.elements.last
106
+ end
107
+
108
+ # Returns the instance's class name.
109
+ def klass_name
110
+ ebnf.klass_name
111
+ end
112
+
113
+ # Returns the instance's name. For example:
114
+ # root.find_by_name("Element#update").name
115
+ # # -> "update"
116
+ def name
117
+ ebnf.name
118
+ end
119
+
120
+ # Returns the instance's full_name. For example:
121
+ # root.find_by_name("Element#update").full_name
122
+ # # -> "Element#update"
123
+ def full_name
124
+ ebnf.full_name
125
+ end
126
+
127
+ # Returns the instance's namespace_string. Note that event if the instance is an method or property,
128
+ # the klass_name is not included in that string. So for example:
129
+ #
130
+ # root.find_by_name("Ajax.Request#request").namespace_string
131
+ # # -> "Ajax"
132
+ def namespace_string
133
+ ebnf.namespace
134
+ end
135
+
136
+ # Returns the Klass instance if object is a class, nil otherwise.
137
+ def klass
138
+ nil
139
+ end
140
+
141
+ # Returns the instance's closests namespace or nil when instance or instance's
142
+ # Klass is a global.
143
+ def namespace
144
+ @namespace ||= namespace_string.empty? ? nil : root.find_by_name(namespace_string)
145
+ end
146
+
147
+ # If instance is a global, returns its Section. Else its Namespace.
148
+ def doc_parent
149
+ namespace ? namespace : section
150
+ end
151
+
152
+ def ebnf_expressions
153
+ ebnf.elements.map { |e| e.elements.last }
154
+ end
155
+
156
+ def description
157
+ text.to_s
158
+ end
159
+
160
+ def signature
161
+ ebnf.text_value.strip
162
+ end
163
+
164
+ def inspect
165
+ "#<#{self.class} #{full_name}>"
166
+ end
167
+
168
+ def src_code_line
169
+ input.line_of(interval.last) - 1
170
+ end
171
+
172
+ def parent_id
173
+ namespace_string.empty? ? section_name : namespace_string
174
+ end
175
+
176
+ def section_name
177
+ if tags.include?('section')
178
+ value = tags.find { |tag| tag.name == 'section' }.value
179
+ "#{value} section"
180
+ end
181
+ end
182
+
183
+ def to_yaml
184
+ str = "id: #{full_name.inspect}"
185
+ str << "\nparent_id: #{parent_id.inspect}" if parent_id
186
+ str << "\ntype: #{type}"
187
+ str << "\nsuperclass_id: #{superclass.inspect}" if respond_to?(:superclass) && superclass
188
+ str << "\nincluded: #{mixins.inspect}" if respond_to?(:mixins) && !mixins.empty?
189
+ str << "\nline_number: #{src_code_line}"
190
+ str << "\ndeprecated: true" if deprecated?
191
+ str << "\nalias_of: #{alias_of.inspect}" if respond_to?(:alias_of) && alias_of
192
+ str << "\nrelated_to: #{related_to.inspect}" if respond_to?(:related_to) && related_to
193
+ str << "\ndescription: |\n#{indent(description)}\n"
194
+ end
195
+
196
+ def serialize(serializer)
197
+ serializer << to_yaml
198
+ end
199
+
200
+ private
201
+ def indent(str, prefix = ' ')
202
+ str.split($/).map { |line| "#{prefix}#{line}" } * $/
203
+ end
204
+ end
205
+
206
+ class Section < Base
207
+ # Returns section's name
208
+ def name
209
+ section.name
210
+ end
211
+
212
+ # Returns section's full_name
213
+ def full_name
214
+ "#{section.name} section"
215
+ end
216
+
217
+ # Returns section's title
218
+ def title
219
+ section.title
220
+ end
221
+
222
+ # Returns section's description
223
+ def description
224
+ section.description
225
+ end
226
+
227
+ # Returns section's text
228
+ def text
229
+ section.text
230
+ end
231
+
232
+ # Returns nil.
233
+ def klass_name
234
+ nil
235
+ end
236
+
237
+ # Returns false.
238
+ def global?
239
+ false
240
+ end
241
+
242
+ # Returns nil.
243
+ def namespace
244
+ nil
245
+ end
246
+
247
+ # Returns an empty string.
248
+ def namespace_string
249
+ ""
250
+ end
251
+
252
+ # Returns nil.
253
+ def section
254
+ nil
255
+ end
256
+
257
+ # Returns nil.
258
+ def doc_parent
259
+ nil
260
+ end
261
+
262
+ # Returns "section".
263
+ def type
264
+ "section"
265
+ end
266
+ end
267
+
268
+ class Method < Base
269
+ def klass
270
+ namespace
271
+ end
272
+
273
+ def klass_name
274
+ ebnf_expressions.first.klass_name
275
+ end
276
+
277
+ def full_name
278
+ ebnf_expressions.first.full_name
279
+ end
280
+
281
+ def name
282
+ ebnf_expressions.first.name
283
+ end
284
+
285
+ def methodized?
286
+ ebnf_expressions.first.methodized?
287
+ end
288
+
289
+ def namespace_string
290
+ ebnf_expressions.first.namespace
291
+ end
292
+
293
+ def arguments
294
+ args = argument_descriptions.elements
295
+ args ? args.first.elements : []
296
+ end
297
+
298
+ def signature
299
+ ebnf_expressions.first.signature
300
+ end
301
+
302
+ def returns
303
+ ebnf_expressions.first.returns
304
+ end
305
+
306
+ def fires
307
+ events.empty? ? [] : events.to_a
308
+ end
309
+
310
+ def signatures
311
+ ebnf_expressions
312
+ end
313
+
314
+ def serialize(serializer)
315
+ str = to_yaml
316
+ str << "\nmethodized: true" if respond_to?(:methodized?) && methodized?
317
+
318
+ serialize_signatures(str)
319
+
320
+ serialize_arguments(str) unless arguments.empty?
321
+
322
+ serializer << str
323
+ end
324
+
325
+ def serialize_signatures(str)
326
+ str << "\nsignatures:"
327
+ ebnf_expressions.each do |ebnf|
328
+ str << "\n -"
329
+ str << "\n signature: #{ebnf.signature.inspect}"
330
+ str << "\n return_value: #{ebnf.returns.inspect}" if ebnf.returns
331
+ end
332
+ end
333
+
334
+ def serialize_arguments(str)
335
+ str << "\narguments:"
336
+ arguments.each do |arg|
337
+ str << "\n -"
338
+ str << "\n name: #{arg.name}"
339
+ str << "\n types: [#{arg.types.join(', ')}]" unless arg.types.empty?
340
+ str << "\n description: >"
341
+ str << "\n #{arg.description}\n"
342
+ end
343
+ end
344
+ end
345
+
346
+ class Property < Base
347
+ def klass
348
+ namespace
349
+ end
350
+
351
+ def signature
352
+ ebnf.signature
353
+ end
354
+
355
+ def returns
356
+ ebnf.returns
357
+ end
358
+
359
+ def serialize(serializer)
360
+ str = to_yaml
361
+
362
+ str << "\nsignatures:"
363
+ str << "\n -"
364
+ str << "\n signature: #{signature.inspect}"
365
+ str << "\n return_value: #{returns.inspect}"
366
+
367
+ serializer << str
368
+ end
369
+ end
370
+
371
+ class KlassMethod < Method
372
+ def klass
373
+ namespace.is_a?(Klass) ? namespace : nil
374
+ end
375
+
376
+ def klass_name
377
+ klass ? klass.name : nil
378
+ end
379
+
380
+ def type
381
+ "class method"
382
+ end
383
+ end
384
+
385
+ class Utility < Method
386
+ def type
387
+ "utility"
388
+ end
389
+ end
390
+
391
+ class InstanceMethod < Method
392
+ def type
393
+ "instance method"
394
+ end
395
+ end
396
+
397
+ class Constructor < Method
398
+ def namespace_string
399
+ ebnf_expressions.first.namespace
400
+ end
401
+
402
+ def type
403
+ "constructor"
404
+ end
405
+ end
406
+
407
+ class KlassProperty < Property
408
+ def type
409
+ "class property"
410
+ end
411
+ end
412
+
413
+ class InstanceProperty < Property
414
+ def type
415
+ "instance property"
416
+ end
417
+ end
418
+
419
+ class Constant < Base
420
+ def klass
421
+ namespace.is_a?(Klass) ? namespace : nil
422
+ end
423
+
424
+ def klass_name
425
+ klass ? klass.name : nil
426
+ end
427
+
428
+ def returns
429
+ ebnf.returns
430
+ end
431
+
432
+ def signature
433
+ ebnf.signature
434
+ end
435
+
436
+ def type
437
+ "constant"
438
+ end
439
+ end
440
+
441
+ class Namespace < Base
442
+ def mixins
443
+ ebnf.mixins.map { |m| m.full_name }
444
+ end
445
+
446
+ def mixin?
447
+ false
448
+ end
449
+
450
+ def klass?
451
+ false
452
+ end
453
+
454
+ def type
455
+ "namespace"
456
+ end
457
+ end
458
+
459
+ class Klass < Namespace
460
+ def klass?
461
+ true
462
+ end
463
+
464
+ def superclass
465
+ sc = ebnf.superklass
466
+ sc.text_value if sc
467
+ end
468
+
469
+ def type
470
+ "class"
471
+ end
472
+ end
473
+
474
+ class Mixin < Namespace
475
+ def mixin?
476
+ true
477
+ end
478
+
479
+ def type
480
+ "mixin"
481
+ end
482
+ end
483
+ end