jsduck 4.10.4 → 5.0.0.beta01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. data/.travis.yml +0 -1
  2. data/README.md +32 -6
  3. data/Rakefile +10 -18
  4. data/bin/compare +5 -5
  5. data/bin/jsduck +2 -3
  6. data/jsduck.gemspec +3 -4
  7. data/lib/jsduck/aggregator.rb +21 -80
  8. data/lib/jsduck/app.rb +7 -14
  9. data/lib/jsduck/app_data.rb +4 -5
  10. data/lib/jsduck/assets.rb +4 -7
  11. data/lib/jsduck/base_type.rb +53 -0
  12. data/lib/jsduck/batch_parser.rb +8 -87
  13. data/lib/jsduck/batch_processor.rb +77 -0
  14. data/lib/jsduck/categories/auto.rb +83 -0
  15. data/lib/jsduck/categories/class_name.rb +63 -0
  16. data/lib/jsduck/categories/factory.rb +113 -0
  17. data/lib/jsduck/categories/file.rb +75 -0
  18. data/lib/jsduck/class.rb +3 -9
  19. data/lib/jsduck/class_doc_expander.rb +1 -1
  20. data/lib/jsduck/css/lexer.rb +203 -0
  21. data/lib/jsduck/css/parser.rb +121 -0
  22. data/lib/jsduck/doc/comment.rb +40 -0
  23. data/lib/jsduck/doc/map.rb +23 -0
  24. data/lib/jsduck/doc/parser.rb +128 -0
  25. data/lib/jsduck/doc/processor.rb +52 -0
  26. data/lib/jsduck/doc/scanner.rb +76 -0
  27. data/lib/jsduck/doc/standard_tag_parser.rb +154 -0
  28. data/lib/jsduck/doc/subproperties.rb +64 -0
  29. data/lib/jsduck/docs_code_comparer.rb +31 -0
  30. data/lib/jsduck/export_writer.rb +2 -2
  31. data/lib/jsduck/exporter/app.rb +16 -4
  32. data/lib/jsduck/exporter/full.rb +2 -2
  33. data/lib/jsduck/format/batch.rb +58 -0
  34. data/lib/jsduck/format/class.rb +62 -0
  35. data/lib/jsduck/format/doc.rb +172 -0
  36. data/lib/jsduck/format/html_stack.rb +109 -0
  37. data/lib/jsduck/format/shortener.rb +55 -0
  38. data/lib/jsduck/format/subproperties.rb +64 -0
  39. data/lib/jsduck/guides.rb +32 -14
  40. data/lib/jsduck/index_html.rb +3 -1
  41. data/lib/jsduck/inline/auto_link.rb +2 -2
  42. data/lib/jsduck/inline/link.rb +4 -3
  43. data/lib/jsduck/inline/link_renderer.rb +2 -2
  44. data/lib/jsduck/inline/video.rb +8 -2
  45. data/lib/jsduck/js/ast.rb +361 -0
  46. data/lib/jsduck/js/esprima.rb +39 -0
  47. data/lib/jsduck/{esprima → js/esprima}/esprima.js +0 -0
  48. data/lib/jsduck/js/evaluator.rb +70 -0
  49. data/lib/jsduck/js/ext_patterns.rb +70 -0
  50. data/lib/jsduck/js/function.rb +206 -0
  51. data/lib/jsduck/js/node.rb +194 -0
  52. data/lib/jsduck/js/node_array.rb +36 -0
  53. data/lib/jsduck/js/parser.rb +223 -0
  54. data/lib/jsduck/js/serializer.rb +263 -0
  55. data/lib/jsduck/js/utils.rb +21 -0
  56. data/lib/jsduck/logger.rb +3 -13
  57. data/lib/jsduck/members_index.rb +3 -4
  58. data/lib/jsduck/merger.rb +25 -145
  59. data/lib/jsduck/options.rb +29 -132
  60. data/lib/jsduck/parser.rb +76 -0
  61. data/lib/jsduck/process/accessors.rb +133 -0
  62. data/lib/jsduck/process/circular_deps.rb +58 -0
  63. data/lib/jsduck/process/enums.rb +91 -0
  64. data/lib/jsduck/process/ext4_events.rb +43 -0
  65. data/lib/jsduck/process/global_members.rb +36 -0
  66. data/lib/jsduck/process/ignored_classes.rb +16 -0
  67. data/lib/jsduck/process/importer.rb +58 -0
  68. data/lib/jsduck/process/inherit_doc.rb +197 -0
  69. data/lib/jsduck/process/lint.rb +135 -0
  70. data/lib/jsduck/process/overrides.rb +99 -0
  71. data/lib/jsduck/process/return_values.rb +72 -0
  72. data/lib/jsduck/process/versions.rb +102 -0
  73. data/lib/jsduck/relations.rb +5 -0
  74. data/lib/jsduck/render/class.rb +144 -0
  75. data/lib/jsduck/render/sidebar.rb +97 -0
  76. data/lib/jsduck/render/signature.rb +94 -0
  77. data/lib/jsduck/render/subproperties.rb +99 -0
  78. data/lib/jsduck/render/tags.rb +38 -0
  79. data/lib/jsduck/search_data.rb +19 -13
  80. data/lib/jsduck/source/file.rb +8 -17
  81. data/lib/jsduck/tag/abstract.rb +4 -7
  82. data/lib/jsduck/tag/accessor.rb +10 -0
  83. data/lib/jsduck/tag/alias.rb +61 -0
  84. data/lib/jsduck/tag/alternate_class_names.rb +17 -0
  85. data/lib/jsduck/tag/aside.rb +28 -31
  86. data/lib/jsduck/tag/author.rb +9 -5
  87. data/lib/jsduck/tag/boolean_tag.rb +24 -0
  88. data/lib/jsduck/tag/cfg.rb +45 -0
  89. data/lib/jsduck/tag/chainable.rb +5 -7
  90. data/lib/jsduck/tag/class.rb +28 -0
  91. data/lib/jsduck/tag/class_list_tag.rb +40 -0
  92. data/lib/jsduck/tag/constructor.rb +24 -0
  93. data/lib/jsduck/tag/css_mixin.rb +17 -0
  94. data/lib/jsduck/tag/css_var.rb +29 -0
  95. data/lib/jsduck/tag/default.rb +31 -0
  96. data/lib/jsduck/tag/deprecated.rb +13 -27
  97. data/lib/jsduck/tag/deprecated_tag.rb +58 -0
  98. data/lib/jsduck/tag/doc.rb +32 -0
  99. data/lib/jsduck/tag/docauthor.rb +4 -5
  100. data/lib/jsduck/tag/enum.rb +70 -0
  101. data/lib/jsduck/tag/event.rb +28 -0
  102. data/lib/jsduck/tag/evented.rb +10 -0
  103. data/lib/jsduck/tag/extends.rb +45 -0
  104. data/lib/jsduck/tag/ftype.rb +18 -0
  105. data/lib/jsduck/tag/hide.rb +4 -11
  106. data/lib/jsduck/tag/ignore.rb +6 -7
  107. data/lib/jsduck/tag/inheritable.rb +10 -0
  108. data/lib/jsduck/tag/inheritdoc.rb +48 -0
  109. data/lib/jsduck/tag/markdown.rb +8 -6
  110. data/lib/jsduck/tag/member.rb +24 -0
  111. data/lib/jsduck/tag/method.rb +35 -0
  112. data/lib/jsduck/tag/mixins.rb +26 -0
  113. data/lib/jsduck/tag/name.rb +36 -0
  114. data/lib/jsduck/tag/new.rb +13 -27
  115. data/lib/jsduck/tag/override.rb +37 -0
  116. data/lib/jsduck/tag/overrides.rb +29 -0
  117. data/lib/jsduck/tag/param.rb +87 -0
  118. data/lib/jsduck/tag/preventable.rb +19 -10
  119. data/lib/jsduck/tag/private.rb +28 -13
  120. data/lib/jsduck/tag/property.rb +39 -0
  121. data/lib/jsduck/tag/protected.rb +5 -7
  122. data/lib/jsduck/tag/ptype.rb +18 -0
  123. data/lib/jsduck/tag/readonly.rb +4 -7
  124. data/lib/jsduck/tag/removed.rb +21 -29
  125. data/lib/jsduck/tag/required.rb +11 -9
  126. data/lib/jsduck/tag/requires.rb +12 -0
  127. data/lib/jsduck/tag/return.rb +47 -0
  128. data/lib/jsduck/tag/since.rb +19 -11
  129. data/lib/jsduck/tag/singleton.rb +15 -0
  130. data/lib/jsduck/tag/static.rb +5 -7
  131. data/lib/jsduck/tag/subproperties.rb +23 -0
  132. data/lib/jsduck/tag/tag.rb +208 -0
  133. data/lib/jsduck/tag/template.rb +14 -9
  134. data/lib/jsduck/tag/throws.rb +38 -0
  135. data/lib/jsduck/tag/type.rb +48 -0
  136. data/lib/jsduck/tag/uses.rb +12 -0
  137. data/lib/jsduck/tag/xtype.rb +30 -0
  138. data/lib/jsduck/tag_loader.rb +39 -0
  139. data/lib/jsduck/tag_registry.rb +189 -0
  140. data/lib/jsduck/type_parser.rb +3 -3
  141. data/lib/jsduck/web_writer.rb +2 -2
  142. data/lib/jsduck/welcome.rb +1 -1
  143. metadata +578 -538
  144. data/lib/jsduck/accessors.rb +0 -136
  145. data/lib/jsduck/ast.rb +0 -524
  146. data/lib/jsduck/auto_categories.rb +0 -80
  147. data/lib/jsduck/batch_formatter.rb +0 -60
  148. data/lib/jsduck/categories.rb +0 -73
  149. data/lib/jsduck/categories_class_name.rb +0 -37
  150. data/lib/jsduck/circular_deps.rb +0 -56
  151. data/lib/jsduck/class_formatter.rb +0 -102
  152. data/lib/jsduck/columns.rb +0 -56
  153. data/lib/jsduck/css_lexer.rb +0 -201
  154. data/lib/jsduck/css_parser.rb +0 -119
  155. data/lib/jsduck/doc_ast.rb +0 -319
  156. data/lib/jsduck/doc_formatter.rb +0 -142
  157. data/lib/jsduck/doc_parser.rb +0 -611
  158. data/lib/jsduck/doc_type.rb +0 -59
  159. data/lib/jsduck/enum.rb +0 -73
  160. data/lib/jsduck/esprima.rb +0 -51
  161. data/lib/jsduck/evaluator.rb +0 -69
  162. data/lib/jsduck/ext_patterns.rb +0 -58
  163. data/lib/jsduck/file_categories.rb +0 -76
  164. data/lib/jsduck/function_ast.rb +0 -206
  165. data/lib/jsduck/guide_anchors.rb +0 -32
  166. data/lib/jsduck/guide_toc.rb +0 -49
  167. data/lib/jsduck/html_stack.rb +0 -105
  168. data/lib/jsduck/importer.rb +0 -121
  169. data/lib/jsduck/inherit_doc.rb +0 -193
  170. data/lib/jsduck/js_parser.rb +0 -221
  171. data/lib/jsduck/lint.rb +0 -133
  172. data/lib/jsduck/meta_tag.rb +0 -88
  173. data/lib/jsduck/meta_tag_loader.rb +0 -67
  174. data/lib/jsduck/meta_tag_registry.rb +0 -111
  175. data/lib/jsduck/meta_tag_renderer.rb +0 -34
  176. data/lib/jsduck/news.rb +0 -128
  177. data/lib/jsduck/override.rb +0 -87
  178. data/lib/jsduck/renderer.rb +0 -361
  179. data/lib/jsduck/return_values.rb +0 -72
  180. data/lib/jsduck/serializer.rb +0 -262
  181. data/lib/jsduck/shortener.rb +0 -58
  182. data/lib/jsduck/signature_renderer.rb +0 -91
  183. data/lib/jsduck/source/file_parser.rb +0 -72
@@ -0,0 +1,58 @@
1
+ require 'jsduck/util/json'
2
+ require 'jsduck/util/null_object'
3
+ require 'jsduck/util/parallel'
4
+ require 'jsduck/logger'
5
+
6
+ module JsDuck
7
+ module Process
8
+
9
+ # Reads in JSDuck exports of different versions of docs.
10
+ class Importer
11
+ # Reads in data for all versions, returning array of
12
+ # version/class-data pairs. We don't use a hash to preserve the
13
+ # order of versions (from oldest to newest).
14
+ def import(versions)
15
+ versions.map do |ver|
16
+ {
17
+ :version => ver[:version],
18
+ :classes => ver[:path] ? read(ver) : current_version,
19
+ }
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def current_version
26
+ Util::NullObject.new(:[] => Util::NullObject.new(:[] => true))
27
+ end
28
+
29
+ # Reads in data from all .json files in directory
30
+ def read(ver)
31
+ # Map list of files into pairs of (classname, members-hash)
32
+ pairs = Util::Parallel.map(Dir[ver[:path] + "/*.json"]) do |filename|
33
+ JsDuck::Logger.log("Importing #{ver[:version]}", filename)
34
+ json = Util::Json.read(filename)
35
+ [json["name"], members_id_index(json)]
36
+ end
37
+
38
+ # Turn key-value pairs array into hash
39
+ return Hash[ pairs ]
40
+ end
41
+
42
+ # creates index of all class members
43
+ def members_id_index(json)
44
+ index = {}
45
+ ["members", "statics"].each do |group_name|
46
+ json[group_name].each_pair do |tagname, members|
47
+ members.each do |m|
48
+ index[m["id"]] = true
49
+ end
50
+ end
51
+ end
52
+ index
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,197 @@
1
+ require 'jsduck/logger'
2
+ require 'jsduck/class'
3
+
4
+ module JsDuck
5
+ module Process
6
+
7
+ # Deals with inheriting documentation
8
+ class InheritDoc
9
+ def initialize(relations)
10
+ @relations = relations
11
+ end
12
+
13
+ # Performs all inheriting
14
+ def process_all!
15
+ @relations.each do |cls|
16
+ resolve_class(cls) if cls[:inheritdoc]
17
+
18
+ new_cfgs = []
19
+ cls.all_local_members.each do |member|
20
+ if member[:inheritdoc]
21
+ resolve(member, new_cfgs)
22
+ end
23
+ end
24
+ move_cfgs(cls, new_cfgs) if new_cfgs.length > 0
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ # Copy over doc/params/return from parent member.
31
+ def resolve(m, new_cfgs)
32
+ parent = find_parent(m)
33
+
34
+ if m[:inheritdoc] && parent
35
+ m[:doc] = (m[:doc] + "\n\n" + parent[:doc]).strip
36
+ m[:params] = parent[:params] if parent[:params]
37
+ m[:return] = parent[:return] if parent[:return]
38
+ m[:type] = parent[:type] if parent[:type]
39
+
40
+ if m[:autodetected]
41
+ m[:deprecated] = parent[:deprecated] if parent[:deprecated] && !m[:deprecated]
42
+ end
43
+
44
+ # remember properties that have changed to configs
45
+ if m[:autodetected] && m[:tagname] != parent[:tagname]
46
+ new_cfgs << m
47
+ end
48
+ end
49
+
50
+ resolve_visibility(m, parent)
51
+ end
52
+
53
+ # Changes given properties into configs within class
54
+ def move_cfgs(cls, members)
55
+ members.each do |m|
56
+ m[:tagname] = :cfg
57
+ end
58
+ # Ask class to update its internal caches for these members
59
+ cls.update_members!(members)
60
+ end
61
+
62
+ # For auto-detected members/classes (which have @private == :inherit)
63
+ # Use the visibility from parent class (defaulting to private when no parent).
64
+ def resolve_visibility(m, parent)
65
+ if m[:autodetected] && !JsDuck::Class.constructor?(m)
66
+ if !parent || parent[:private]
67
+ m[:private] = true
68
+ end
69
+
70
+ m[:protected] = true if parent && parent[:protected]
71
+ end
72
+ end
73
+
74
+ # Finds parent member of the given member. When @inheritdoc names
75
+ # a member to inherit from, finds that member instead.
76
+ #
77
+ # If the parent also has @inheritdoc, continues recursively.
78
+ def find_parent(m)
79
+
80
+ inherit = m[:inheritdoc] || {}
81
+ if inherit[:cls]
82
+ # @inheritdoc MyClass#member
83
+ parent_cls = @relations[m[:inheritdoc][:cls]]
84
+ return warn("class not found", m) unless parent_cls
85
+
86
+ parent = lookup_member(parent_cls, m)
87
+ return warn("member not found", m) unless parent
88
+
89
+ elsif inherit[:member]
90
+ # @inheritdoc #member
91
+ parent = lookup_member(@relations[m[:owner]], m)
92
+ return warn("member not found", m) unless parent
93
+
94
+ else
95
+ # @inheritdoc
96
+ parent_cls = @relations[m[:owner]].parent
97
+ mixins = @relations[m[:owner]].mixins
98
+
99
+ # Warn when no parent or mixins at all
100
+ if !parent_cls && mixins.length == 0
101
+ warn("parent class not found", m) unless m[:autodetected]
102
+ return nil
103
+ end
104
+
105
+ # First check for the member in all mixins, because members
106
+ # from mixins override those from parent class. Looking first
107
+ # from mixins is probably a bit slower, but it's the correct
108
+ # order to do things.
109
+ if mixins.length > 0
110
+ parent = mixins.map {|mix| lookup_member(mix, m) }.compact.first
111
+ end
112
+
113
+ # When not found, try looking from parent class
114
+ if !parent && parent_cls
115
+ parent = lookup_member(parent_cls, m)
116
+ end
117
+
118
+ # Only when both parent and mixins fail, throw warning
119
+ if !parent
120
+ warn("parent member not found", m) unless m[:autodetected]
121
+ return nil
122
+ end
123
+ end
124
+
125
+ return parent[:inheritdoc] ? find_parent(parent) : parent
126
+ end
127
+
128
+ def lookup_member(cls, m)
129
+ inherit = m[:inheritdoc] || {}
130
+ name = inherit[:member] || m[:name]
131
+ tagname = inherit[:type] || m[:tagname]
132
+ static = inherit[:static] || m[:static]
133
+
134
+ if m[:autodetected]
135
+ # Auto-detected properties can override either a property or a
136
+ # config. So look for both types.
137
+ if tagname == :property
138
+ cfg = cls.find_members(:name => name, :tagname => :cfg, :static => static || false)[0]
139
+ prop = cls.find_members(:name => name, :tagname => :property, :static => static || false)[0]
140
+
141
+ if cfg && prop
142
+ prop
143
+ elsif cfg
144
+ cfg
145
+ elsif prop
146
+ prop
147
+ else
148
+ nil
149
+ end
150
+
151
+ else
152
+ # Unless the auto-detected member is detected as static,
153
+ # look only at instance members.
154
+ cls.find_members(:name => name, :tagname => tagname, :static => static || false)[0]
155
+ end
156
+ else
157
+ cls.find_members(:name => name, :tagname => tagname, :static => static)[0]
158
+ end
159
+ end
160
+
161
+ # Copy over doc from parent class.
162
+ def resolve_class(cls)
163
+ parent = find_class_parent(cls)
164
+
165
+ if parent
166
+ cls[:doc] = (cls[:doc] + "\n\n" + parent[:doc]).strip
167
+ end
168
+ end
169
+
170
+ def find_class_parent(cls)
171
+ if cls[:inheritdoc][:cls]
172
+ # @inheritdoc MyClass
173
+ parent = @relations[cls[:inheritdoc][:cls]]
174
+ return warn("class not found", cls) unless parent
175
+ else
176
+ # @inheritdoc
177
+ parent = cls.parent
178
+ return warn("parent class not found", cls) unless parent
179
+ end
180
+
181
+ return parent[:inheritdoc] ? find_class_parent(parent) : parent
182
+ end
183
+
184
+ def warn(msg, item)
185
+ context = item[:files][0]
186
+ i_member = item[:inheritdoc][:member]
187
+
188
+ msg = "@inheritdoc #{item[:inheritdoc][:cls]}"+ (i_member ? "#" + i_member : "") + " - " + msg
189
+ Logger.warn(:inheritdoc, msg, context[:filename], context[:linenr])
190
+
191
+ return nil
192
+ end
193
+
194
+ end
195
+
196
+ end
197
+ end
@@ -0,0 +1,135 @@
1
+ require 'jsduck/logger'
2
+ require 'jsduck/class'
3
+
4
+ module JsDuck
5
+ module Process
6
+
7
+ # Reports bugs and problems in documentation
8
+ class Lint
9
+ attr_accessor :relations
10
+
11
+ def initialize(relations)
12
+ @relations = relations
13
+ end
14
+
15
+ # Runs the linter
16
+ def process_all!
17
+ warn_no_doc
18
+ warn_unnamed
19
+ warn_optional_params
20
+ warn_duplicate_params
21
+ warn_duplicate_members
22
+ warn_singleton_statics
23
+ warn_empty_enums
24
+ end
25
+
26
+ # print warning for each member or parameter with no name
27
+ def warn_unnamed
28
+ each_member do |member|
29
+ if !member[:name] || member[:name] == ""
30
+ warn(:name_missing, "Unnamed #{member[:tagname]}", member)
31
+ end
32
+ (member[:params] || []).each do |p|
33
+ if !p[:name] || p[:name] == ""
34
+ warn(:name_missing, "Unnamed parameter", member)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ # print warning for each class or public member with no name
41
+ def warn_no_doc
42
+ @relations.each do |cls|
43
+ if cls[:doc] == ""
44
+ warn(:no_doc, "No documentation for #{cls[:name]}", cls)
45
+ end
46
+ end
47
+ each_member do |member|
48
+ if member[:doc] == "" && !member[:private] && !member[:hide] && !JsDuck::Class.constructor?(member)
49
+ warn(:no_doc, "No documentation for #{member[:owner]}##{member[:name]}", member)
50
+ end
51
+ end
52
+ end
53
+
54
+ # print warning for each non-optional parameter that follows an optional parameter
55
+ def warn_optional_params
56
+ each_member do |member|
57
+ if member[:tagname] == :method
58
+ optional_found = false
59
+ member[:params].each do |p|
60
+ if optional_found && !p[:optional]
61
+ warn(:req_after_opt, "Optional param followed by regular param #{p[:name]}", member)
62
+ end
63
+ optional_found = optional_found || p[:optional]
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # print warnings for duplicate parameter names
70
+ def warn_duplicate_params
71
+ each_member do |member|
72
+ params = {}
73
+ (member[:params] || []).each do |p|
74
+ if params[p[:name]]
75
+ warn(:dup_param, "Duplicate parameter name #{p[:name]}", member)
76
+ end
77
+ params[p[:name]] = true
78
+ end
79
+ end
80
+ end
81
+
82
+ # print warnings for duplicate member names
83
+ def warn_duplicate_members
84
+ @relations.each do |cls|
85
+ members = {:members => {}, :statics => {}}
86
+ cls.all_local_members.each do |m|
87
+ group = m[:static] ? :statics : :members
88
+ type = m[:tagname]
89
+ name = m[:name]
90
+ hash = members[group][type] || {}
91
+ if hash[name]
92
+ warn(:dup_member, "Duplicate #{type} name #{name}", hash[name])
93
+ warn(:dup_member, "Duplicate #{type} name #{name}", m)
94
+ end
95
+ hash[name] = m
96
+ members[group][type] = hash
97
+ end
98
+ end
99
+ end
100
+
101
+ # Print warnings for static members in singleton classes
102
+ def warn_singleton_statics
103
+ @relations.each do |cls|
104
+ if cls[:singleton]
105
+ cls.find_members({:local => true, :static => true}).each do |m|
106
+ warn(:sing_static, "Static members don't make sense in singleton class #{cls[:name]}", m)
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ # print warnings for enums with no values
113
+ def warn_empty_enums
114
+ @relations.each do |cls|
115
+ if cls[:enum] && cls[:members].length == 0
116
+ warn(:enum, "Enum #{cls[:name]} defined without values in it", cls)
117
+ end
118
+ end
119
+ end
120
+
121
+ # Loops through all members of all classes
122
+ def each_member(&block)
123
+ @relations.each {|cls| cls.all_local_members.each(&block) }
124
+ end
125
+
126
+ # Prints warning + filename and linenumber from doc-context
127
+ def warn(type, msg, member)
128
+ context = member[:files][0]
129
+ Logger.warn(type, msg, context[:filename], context[:linenr])
130
+ end
131
+
132
+ end
133
+
134
+ end
135
+ end
@@ -0,0 +1,99 @@
1
+ require 'jsduck/logger'
2
+
3
+ module JsDuck
4
+ module Process
5
+
6
+ class Overrides
7
+ def initialize(classes_hash, opts = {:external_classes => []})
8
+ @classes_hash = classes_hash
9
+ @opts = opts
10
+ end
11
+
12
+ # Applies all override classes to target classes, then deletes
13
+ # the overrides themselves from classes hash and adds the names
14
+ # of all the processed overrides to external_classes list in
15
+ # options object.
16
+ def process_all!
17
+ overrides = []
18
+
19
+ @classes_hash.each_value do |cls|
20
+ if cls[:override]
21
+ process(cls)
22
+ overrides << cls
23
+ end
24
+ end
25
+
26
+ # discard each override class
27
+ overrides.each do |cls|
28
+ @classes_hash.delete(cls[:name])
29
+ end
30
+
31
+ @opts[:external_classes] += overrides.map {|c| c[:name] }
32
+ end
33
+
34
+ private
35
+
36
+ # Applies override class to target class
37
+ def process(override)
38
+ target = @classes_hash[override[:override]]
39
+ unless target
40
+ ctx = override[:files][0]
41
+ return Logger.warn(:extend, "Class #{override[:override]} not found", ctx[:filename], ctx[:linenr])
42
+ end
43
+
44
+ # Combine comments of classes
45
+ if override[:doc].length > 0
46
+ add_doc(target, "**From override #{get_name(override)}:** " + override[:doc])
47
+ end
48
+ target[:files] += override[:files]
49
+
50
+ # Build lookup table of existing members
51
+ existing = {}
52
+ each_member(target) do |m|
53
+ existing[m[:id]] = m
54
+ end
55
+
56
+ # When the same member exists in overridden class, just append
57
+ # the docs. Otherwise add the member as a whole to the class.
58
+ each_member(override) do |m|
59
+ ex = existing[m[:id]]
60
+ if ex
61
+ if m[:doc].length > 0
62
+ add_doc(ex, "**From override #{get_name(override)}:** " + m[:doc])
63
+ else
64
+ add_doc(ex, "**Overridden in #{get_name(override)}.**")
65
+ end
66
+ ex[:files] += m[:files]
67
+ else
68
+ add_member(target, m)
69
+ add_doc(m, "**Defined in override #{get_name(override)}.**")
70
+ m[:owner] = target[:name]
71
+ end
72
+ end
73
+ end
74
+
75
+ # helpers
76
+
77
+ def get_name(override)
78
+ if override[:name] != ""
79
+ override[:name]
80
+ else
81
+ override[:files][0][:filename]
82
+ end
83
+ end
84
+
85
+ def each_member(cls)
86
+ cls[:members].each {|m| yield m }
87
+ end
88
+
89
+ def add_member(cls, m)
90
+ cls[:members] << m
91
+ end
92
+
93
+ def add_doc(m, doc)
94
+ m[:doc] = (m[:doc] + "\n\n" + doc).strip
95
+ end
96
+ end
97
+
98
+ end
99
+ end