jsduck 3.11.2 → 4.0.beta
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.
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +45 -0
- data/README.md +0 -3
- data/Rakefile +5 -2
- data/js-classes/String.js +1 -1
- data/jsduck.gemspec +5 -2
- data/lib/jsduck/accessors.rb +1 -0
- data/lib/jsduck/aggregator.rb +3 -0
- data/lib/jsduck/app.rb +3 -6
- data/lib/jsduck/ast.rb +446 -0
- data/lib/jsduck/class_doc_expander.rb +135 -0
- data/lib/jsduck/css_lexer.rb +1 -1
- data/lib/jsduck/css_parser.rb +8 -11
- data/lib/jsduck/doc_ast.rb +305 -0
- data/lib/jsduck/doc_parser.rb +33 -28
- data/lib/jsduck/doc_type.rb +58 -0
- data/lib/jsduck/esprima.rb +32 -0
- data/lib/jsduck/evaluator.rb +69 -0
- data/lib/jsduck/guides.rb +12 -11
- data/lib/jsduck/inherit_doc.rb +80 -14
- data/lib/jsduck/js_parser.rb +162 -373
- data/lib/jsduck/lexer.rb +1 -1
- data/lib/jsduck/logger.rb +0 -2
- data/lib/jsduck/merger.rb +89 -435
- data/lib/jsduck/options.rb +4 -14
- data/lib/jsduck/serializer.rb +262 -0
- data/lib/jsduck/source_file.rb +5 -18
- data/lib/jsduck/source_file_parser.rb +72 -0
- metadata +33 -9
- data/lib/jsduck/js_literal_builder.rb +0 -21
- data/lib/jsduck/js_literal_parser.rb +0 -106
- data/lib/jsduck/tag/chainable.rb +0 -14
data/lib/jsduck/lexer.rb
CHANGED
@@ -145,7 +145,7 @@ module JsDuck
|
|
145
145
|
:type => :doc_comment,
|
146
146
|
# Calculate current line number, starting with 1
|
147
147
|
:linenr => @input.string[0...@input.pos].count("\n") + 1,
|
148
|
-
:value => @input.scan_until(/\*\/|\Z/)
|
148
|
+
:value => @input.scan_until(/\*\/|\Z/).sub(/\A\/\*\*/, "").sub(/\*\/\Z/, "")
|
149
149
|
}
|
150
150
|
elsif @input.check(/\/\*/)
|
151
151
|
# skip multiline comment
|
data/lib/jsduck/logger.rb
CHANGED
data/lib/jsduck/merger.rb
CHANGED
@@ -1,246 +1,97 @@
|
|
1
|
-
require 'jsduck/
|
2
|
-
require 'jsduck/meta_tag_registry'
|
1
|
+
require 'jsduck/class'
|
3
2
|
|
4
3
|
module JsDuck
|
5
4
|
|
6
|
-
# Takes data from
|
7
|
-
# these
|
8
|
-
# JsDuck::
|
5
|
+
# Takes data from comment and code that follows it and combines
|
6
|
+
# these two pieces of information into one. The code comes from
|
7
|
+
# JsDuck::Ast and comment from JsDuck::DocAst.
|
9
8
|
#
|
10
9
|
# The main method merge() produces a hash as a result.
|
11
10
|
class Merger
|
12
|
-
# Allow passing in filename and line for error reporting
|
13
|
-
attr_accessor :filename
|
14
|
-
attr_accessor :linenr
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
# Takes a docset and merges the :comment and :code inside it,
|
13
|
+
# producing hash as a result.
|
14
|
+
def merge(docset)
|
15
|
+
docs = docset[:comment]
|
16
|
+
code = docset[:code]
|
21
17
|
|
22
|
-
|
23
|
-
case detect_doc_type(docs, code)
|
18
|
+
case docset[:tagname]
|
24
19
|
when :class
|
25
|
-
|
26
|
-
when :event
|
27
|
-
|
28
|
-
when :
|
29
|
-
|
30
|
-
when :cfg
|
31
|
-
create_cfg(docs, code)
|
32
|
-
when :property
|
33
|
-
create_property(docs, code)
|
34
|
-
when :css_var
|
35
|
-
create_css_var(docs, code)
|
36
|
-
when :css_mixin
|
37
|
-
create_css_mixin(docs, code)
|
20
|
+
result = merge_class(docs, code)
|
21
|
+
when :method, :event, :css_mixin
|
22
|
+
result = merge_like_method(docs, code)
|
23
|
+
when :cfg, :property, :css_var
|
24
|
+
result = merge_like_property(docs, code)
|
38
25
|
end
|
39
|
-
end
|
40
26
|
|
41
|
-
|
42
|
-
def detect_doc_type(docs, code)
|
43
|
-
doc_map = build_doc_map(docs)
|
27
|
+
result[:linenr] = docset[:linenr]
|
44
28
|
|
45
|
-
|
46
|
-
:class
|
47
|
-
elsif doc_map[:event]
|
48
|
-
:event
|
49
|
-
elsif doc_map[:method]
|
50
|
-
:method
|
51
|
-
elsif doc_map[:property] || doc_map[:type]
|
52
|
-
:property
|
53
|
-
elsif doc_map[:css_var]
|
54
|
-
:css_var
|
55
|
-
elsif doc_map[:cfg] && doc_map[:cfg].length == 1
|
56
|
-
# When just one @cfg, avoid treating it as @class
|
57
|
-
:cfg
|
58
|
-
elsif code[:type] == :ext_define
|
59
|
-
:class
|
60
|
-
elsif code[:type] == :assignment && class_name?(*code[:left])
|
61
|
-
:class
|
62
|
-
elsif code[:type] == :function && class_name?(code[:name])
|
63
|
-
:class
|
64
|
-
elsif code[:type] == :css_mixin
|
65
|
-
:css_mixin
|
66
|
-
elsif code[:type] == :css_var
|
67
|
-
:css_var
|
68
|
-
elsif doc_map[:cfg]
|
69
|
-
:cfg
|
70
|
-
elsif code[:type] == :function
|
71
|
-
:method
|
72
|
-
elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :function
|
73
|
-
:method
|
74
|
-
elsif doc_map[:return] || doc_map[:param]
|
75
|
-
:method
|
76
|
-
else
|
77
|
-
:property
|
78
|
-
end
|
29
|
+
result
|
79
30
|
end
|
80
31
|
|
81
|
-
|
82
|
-
def class_name?(*name_chain)
|
83
|
-
return name_chain.last =~ /\A[A-Z]/
|
84
|
-
end
|
32
|
+
private
|
85
33
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
34
|
+
def merge_class(docs, code)
|
35
|
+
h = do_merge(docs, code, {
|
36
|
+
:mixins => [],
|
37
|
+
:alternateClassNames => [],
|
38
|
+
:requires => [],
|
39
|
+
:uses => [],
|
40
|
+
:singleton => false,
|
41
|
+
})
|
93
42
|
|
94
|
-
|
95
|
-
|
96
|
-
# ExtJS comments often appears after @constructor - so we
|
97
|
-
# explicitly place it into :class group.
|
98
|
-
#
|
99
|
-
# Then gathers each @cfg and tags following it into :cfg group, so
|
100
|
-
# that it becomes array of arrays of tags. This is to allow some
|
101
|
-
# configs to be marked with @private or whatever else.
|
102
|
-
#
|
103
|
-
# Finally gathers tags after @constructor into its group.
|
104
|
-
def group_class_docs(docs)
|
105
|
-
groups = {:class => [], :cfg => [], :constructor => []}
|
106
|
-
group_name = :class
|
107
|
-
docs.each do |tag|
|
108
|
-
if tag[:tagname] == :cfg || tag[:tagname] == :constructor
|
109
|
-
group_name = tag[:tagname]
|
110
|
-
if tag[:tagname] == :cfg
|
111
|
-
groups[:cfg] << []
|
112
|
-
end
|
113
|
-
end
|
43
|
+
# Ignore extending of the Object class
|
44
|
+
h[:extends] = nil if h[:extends] == "Object"
|
114
45
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
groups[group_name] << tag
|
121
|
-
end
|
122
|
-
end
|
123
|
-
groups
|
124
|
-
end
|
46
|
+
h[:aliases] = build_aliases_hash(h[:aliases] || [])
|
47
|
+
# Used by Aggregator to determine if we're dealing with Ext4 code
|
48
|
+
h[:code_type] = code[:tagname]
|
49
|
+
h[:members] = Class.default_members_hash
|
50
|
+
h[:statics] = Class.default_members_hash
|
125
51
|
|
126
|
-
|
127
|
-
doc_map = build_doc_map(docs)
|
128
|
-
return add_shared({
|
129
|
-
:tagname => :class,
|
130
|
-
:name => detect_name(:class, doc_map, code, :full_name),
|
131
|
-
:doc => detect_doc(docs),
|
132
|
-
:extends => detect_extends(doc_map, code),
|
133
|
-
:mixins => detect_list(:mixins, doc_map, code),
|
134
|
-
:alternateClassNames => detect_list(:alternateClassNames, doc_map, code),
|
135
|
-
:aliases => detect_aliases(doc_map, code),
|
136
|
-
:singleton => detect_singleton(doc_map, code),
|
137
|
-
:requires => detect_list(:requires, doc_map, code),
|
138
|
-
:uses => detect_list(:uses, doc_map, code),
|
139
|
-
# Used by Aggregator to determine if we're dealing with Ext4 code
|
140
|
-
:code_type => code[:type],
|
141
|
-
}, doc_map)
|
52
|
+
h
|
142
53
|
end
|
143
54
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
constr = create_method(groups[:constructor], {})
|
149
|
-
constr[:owner] = owner
|
150
|
-
members[:method] << constr
|
151
|
-
end
|
152
|
-
members
|
55
|
+
def merge_like_method(docs, code)
|
56
|
+
h = do_merge(docs, code)
|
57
|
+
h[:params] = merge_params(docs, code)
|
58
|
+
h
|
153
59
|
end
|
154
60
|
|
155
|
-
def
|
156
|
-
|
157
|
-
name = detect_name(:method, doc_map, code)
|
158
|
-
return add_shared({
|
159
|
-
:tagname => :method,
|
160
|
-
:name => name,
|
161
|
-
:owner => detect_owner(doc_map),
|
162
|
-
:doc => detect_doc(docs),
|
163
|
-
:params => detect_params(:method, doc_map, code),
|
164
|
-
:return => detect_return(doc_map, name == "constructor" ? "Object" : "undefined"),
|
165
|
-
:throws => detect_throws(doc_map),
|
166
|
-
}, doc_map)
|
167
|
-
end
|
61
|
+
def merge_like_property(docs, code)
|
62
|
+
h = do_merge(docs, code)
|
168
63
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
:name => detect_name(:event, doc_map, code),
|
174
|
-
:owner => detect_owner(doc_map),
|
175
|
-
:doc => detect_doc(docs),
|
176
|
-
:params => detect_params(:event, doc_map, code),
|
177
|
-
}, doc_map)
|
178
|
-
end
|
64
|
+
h[:type] = merge_if_code_matches(:type, docs, code)
|
65
|
+
if h[:type] == nil
|
66
|
+
h[:type] = code[:tagname] == :method ? "Function" : "Object"
|
67
|
+
end
|
179
68
|
|
180
|
-
|
181
|
-
|
182
|
-
return add_shared({
|
183
|
-
:tagname => :cfg,
|
184
|
-
:name => detect_name(:cfg, doc_map, code),
|
185
|
-
:owner => detect_owner(doc_map) || owner,
|
186
|
-
:type => detect_type(:cfg, doc_map, code),
|
187
|
-
:doc => detect_doc(docs),
|
188
|
-
:default => detect_default(:cfg, doc_map, code),
|
189
|
-
:properties => detect_subproperties(docs, :cfg),
|
190
|
-
:accessor => !!doc_map[:accessor],
|
191
|
-
:evented => !!doc_map[:evented],
|
192
|
-
}, doc_map)
|
69
|
+
h[:default] = merge_if_code_matches(:default, docs, code)
|
70
|
+
h
|
193
71
|
end
|
194
72
|
|
195
|
-
|
196
|
-
doc_map = build_doc_map(docs)
|
197
|
-
return add_shared({
|
198
|
-
:tagname => :property,
|
199
|
-
:name => detect_name(:property, doc_map, code),
|
200
|
-
:owner => detect_owner(doc_map),
|
201
|
-
:type => detect_type(:property, doc_map, code),
|
202
|
-
:doc => detect_doc(docs),
|
203
|
-
:default => detect_default(:property, doc_map, code),
|
204
|
-
:properties => detect_subproperties(docs, :property),
|
205
|
-
}, doc_map)
|
206
|
-
end
|
73
|
+
# --- helpers ---
|
207
74
|
|
208
|
-
def
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
:owner => detect_owner(doc_map),
|
214
|
-
:type => detect_type(:css_var, doc_map, code),
|
215
|
-
:default => detect_default(:css_var, doc_map, code),
|
216
|
-
:doc => detect_doc(docs),
|
217
|
-
}, doc_map)
|
218
|
-
end
|
75
|
+
def do_merge(docs, code, defaults={})
|
76
|
+
h = {}
|
77
|
+
docs.each_pair do |key, value|
|
78
|
+
h[key] = docs[key] || code[key] || defaults[key]
|
79
|
+
end
|
219
80
|
|
220
|
-
|
221
|
-
|
222
|
-
return add_shared({
|
223
|
-
:tagname => :css_mixin,
|
224
|
-
:name => detect_name(:css_mixin, doc_map, code),
|
225
|
-
:owner => detect_owner(doc_map),
|
226
|
-
:doc => detect_doc(docs),
|
227
|
-
:params => detect_params(:css_mixin, doc_map, code),
|
228
|
-
}, doc_map)
|
229
|
-
end
|
81
|
+
h[:name] = merge_name(docs, code)
|
82
|
+
h[:id] = create_member_id(h)
|
230
83
|
|
231
|
-
|
232
|
-
|
233
|
-
hash.merge!({
|
234
|
-
:inheritable => !!doc_map[:inheritable],
|
235
|
-
:inheritdoc => doc_map[:inheritdoc] ? doc_map[:inheritdoc].first : nil,
|
236
|
-
:meta => detect_meta(doc_map),
|
237
|
-
})
|
238
|
-
# copy :private also to main hash
|
239
|
-
hash[:private] = true if hash[:meta][:private]
|
84
|
+
# Copy private to meta
|
85
|
+
h[:meta][:private] = h[:private] if h[:private]
|
240
86
|
|
241
|
-
|
87
|
+
# Copy :static and :inheritable flags from code if present
|
88
|
+
h[:meta][:static] = true if code[:meta] && code[:meta][:static]
|
89
|
+
h[:inheritable] = true if code[:inheritable]
|
242
90
|
|
243
|
-
|
91
|
+
# Remember auto-detection info
|
92
|
+
h[:autodetected] = code[:autodetected] if code[:autodetected]
|
93
|
+
|
94
|
+
h
|
244
95
|
end
|
245
96
|
|
246
97
|
def create_member_id(m)
|
@@ -249,117 +100,10 @@ module JsDuck
|
|
249
100
|
"#{m[:meta][:static] ? 'static-' : ''}#{m[:tagname]}-#{name}"
|
250
101
|
end
|
251
102
|
|
252
|
-
def detect_name(tagname, doc_map, code, name_type = :last_name)
|
253
|
-
main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
|
254
|
-
if main_tag[:name]
|
255
|
-
main_tag[:name]
|
256
|
-
elsif doc_map[:constructor]
|
257
|
-
"constructor"
|
258
|
-
elsif code[:type] == :function || code[:type] == :css_mixin || code[:type] == :css_var
|
259
|
-
code[:name]
|
260
|
-
elsif code[:type] == :assignment
|
261
|
-
name_type == :full_name ? code[:left].join(".") : code[:left].last
|
262
|
-
elsif code[:type] == :ext_define
|
263
|
-
name_type == :full_name ? code[:name] : code[:name].split(/\./).last
|
264
|
-
else
|
265
|
-
""
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
def detect_owner(doc_map)
|
270
|
-
if doc_map[:member]
|
271
|
-
doc_map[:member].first[:member]
|
272
|
-
else
|
273
|
-
nil
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def detect_type(tagname, doc_map, code)
|
278
|
-
main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
|
279
|
-
if main_tag[:type]
|
280
|
-
return main_tag[:type]
|
281
|
-
elsif doc_map[:type]
|
282
|
-
return doc_map[:type].first[:type]
|
283
|
-
elsif code_matches_doc?(tagname, doc_map, code)
|
284
|
-
if code[:type] == :function
|
285
|
-
return "Function"
|
286
|
-
elsif code[:type] == :assignment && code[:right]
|
287
|
-
if code[:right][:type] == :function
|
288
|
-
return "Function"
|
289
|
-
elsif code[:right][:type] == :literal && code[:right][:class] != nil
|
290
|
-
return code[:right][:class]
|
291
|
-
end
|
292
|
-
elsif code[:type] == :css_var && code[:value][:type] != nil
|
293
|
-
return code[:value][:type]
|
294
|
-
end
|
295
|
-
end
|
296
|
-
return "Object"
|
297
|
-
end
|
298
|
-
|
299
|
-
def detect_extends(doc_map, code)
|
300
|
-
if doc_map[:extends]
|
301
|
-
cls = doc_map[:extends].first[:extends]
|
302
|
-
elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :ext_extend
|
303
|
-
cls = code[:right][:extend].join(".")
|
304
|
-
elsif code[:type] == :ext_define
|
305
|
-
# Classes defined with Ext.define will automatically inherit from Ext.Base
|
306
|
-
cls = code[:extend] || "Ext.Base"
|
307
|
-
else
|
308
|
-
cls = nil
|
309
|
-
end
|
310
|
-
# Ignore extending of the Object class
|
311
|
-
cls == "Object" ? nil : cls
|
312
|
-
end
|
313
|
-
|
314
|
-
def detect_default(tagname, doc_map, code)
|
315
|
-
main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
|
316
|
-
if main_tag[:default]
|
317
|
-
main_tag[:default]
|
318
|
-
elsif code_matches_doc?(tagname, doc_map, code) && code[:type] == :assignment && code[:right]
|
319
|
-
code[:right][:value]
|
320
|
-
elsif code_matches_doc?(tagname, doc_map, code) && code[:type] == :css_var && code[:value][:default]
|
321
|
-
code[:value][:default]
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
# True if the name detected from code matches with explicitly documented name.
|
326
|
-
# Also true when no explicit name documented.
|
327
|
-
def code_matches_doc?(tagname, doc_map, code)
|
328
|
-
explicit_name = detect_name(tagname, doc_map, {})
|
329
|
-
implicit_name = detect_name(tagname, {}, code)
|
330
|
-
return explicit_name == "" || explicit_name == implicit_name
|
331
|
-
end
|
332
|
-
|
333
|
-
# for detecting mixins and alternateClassNames
|
334
|
-
def detect_list(type, doc_map, code)
|
335
|
-
if doc_map[type]
|
336
|
-
doc_map[type].map {|d| d[type] }.flatten
|
337
|
-
elsif code[:type] == :ext_define && code[type]
|
338
|
-
code[type]
|
339
|
-
else
|
340
|
-
[]
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
def detect_aliases(doc_map, code)
|
345
|
-
if doc_map[:alias]
|
346
|
-
build_aliases_hash(doc_map[:alias].map {|tag| tag[:name] })
|
347
|
-
elsif code[:xtype] || code[:alias]
|
348
|
-
hash = {}
|
349
|
-
build_aliases_hash(code[:xtype].map {|xtype| "widget."+xtype }, hash) if code[:xtype]
|
350
|
-
build_aliases_hash(code[:alias], hash) if code[:alias]
|
351
|
-
hash
|
352
|
-
else
|
353
|
-
{}
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
103
|
# Given array of full alias names like "foo.bar", "foo.baz"
|
358
104
|
# build hash like {"foo" => ["bar", "baz"]}
|
359
|
-
|
360
|
-
|
361
|
-
# it instead of creating a new hash.
|
362
|
-
def build_aliases_hash(aliases, hash={})
|
105
|
+
def build_aliases_hash(aliases)
|
106
|
+
hash={}
|
363
107
|
aliases.each do |a|
|
364
108
|
if a =~ /^([^.]+)\.(.+)$/
|
365
109
|
if hash[$1]
|
@@ -372,44 +116,19 @@ module JsDuck
|
|
372
116
|
hash
|
373
117
|
end
|
374
118
|
|
375
|
-
def
|
376
|
-
|
377
|
-
(
|
378
|
-
meta[tag[:name]] = [] unless meta[tag[:name]]
|
379
|
-
meta[tag[:name]] << tag[:doc]
|
380
|
-
end
|
381
|
-
|
382
|
-
meta.each_pair do |key, value|
|
383
|
-
tag = @meta_tags[key]
|
384
|
-
meta[key] = tag.to_value(tag.boolean ? true : value)
|
385
|
-
end
|
386
|
-
|
387
|
-
meta[:required] = true if detect_required(doc_map)
|
388
|
-
meta
|
389
|
-
end
|
390
|
-
|
391
|
-
def detect_singleton(doc_map, code)
|
392
|
-
!!(doc_map[:singleton] || code[:type] == :ext_define && code[:singleton])
|
393
|
-
end
|
394
|
-
|
395
|
-
def detect_required(doc_map)
|
396
|
-
doc_map[:cfg] && doc_map[:cfg].first[:optional] == false
|
397
|
-
end
|
398
|
-
|
399
|
-
def detect_params(tagname, doc_map, code)
|
400
|
-
implicit = code_matches_doc?(tagname, doc_map, code) ? detect_implicit_params(code) : []
|
401
|
-
explicit = detect_explicit_params(doc_map)
|
119
|
+
def merge_params(docs, code)
|
120
|
+
explicit = docs[:params] || []
|
121
|
+
implicit = code_matches_doc?(docs, code) ? (code[:params] || []) : []
|
402
122
|
# Override implicit parameters with explicit ones
|
403
123
|
# But if explicit ones exist, don't append the implicit ones.
|
404
124
|
params = []
|
405
125
|
(explicit.length > 0 ? explicit.length : implicit.length).times do |i|
|
406
126
|
im = implicit[i] || {}
|
407
127
|
ex = explicit[i] || {}
|
408
|
-
doc = ex[:doc] || im[:doc] || ""
|
409
128
|
params << {
|
410
129
|
:type => ex[:type] || im[:type] || "Object",
|
411
130
|
:name => ex[:name] || im[:name] || "",
|
412
|
-
:doc => doc,
|
131
|
+
:doc => ex[:doc] || im[:doc] || "",
|
413
132
|
:optional => ex[:optional] || false,
|
414
133
|
:default => ex[:default],
|
415
134
|
:properties => ex[:properties] || [],
|
@@ -418,101 +137,36 @@ module JsDuck
|
|
418
137
|
params
|
419
138
|
end
|
420
139
|
|
421
|
-
def
|
422
|
-
if
|
423
|
-
|
424
|
-
elsif code[:
|
425
|
-
|
426
|
-
|
427
|
-
[]
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
def detect_explicit_params(doc_map)
|
432
|
-
combine_properties(doc_map[:param] || [])
|
433
|
-
end
|
434
|
-
|
435
|
-
def detect_subproperties(docs, tagname)
|
436
|
-
prop_docs = docs.find_all {|tag| tag[:tagname] == tagname}
|
437
|
-
prop_docs.length > 0 ? combine_properties(prop_docs)[0][:properties] : []
|
438
|
-
end
|
439
|
-
|
440
|
-
def combine_properties(raw_items)
|
441
|
-
# First item can't be namespaced, if it is ignore the rest.
|
442
|
-
if raw_items[0] && raw_items[0][:name] =~ /\./
|
443
|
-
return [raw_items[0]]
|
444
|
-
end
|
445
|
-
|
446
|
-
# build name-index of all items
|
447
|
-
index = {}
|
448
|
-
raw_items.each {|it| index[it[:name]] = it }
|
449
|
-
|
450
|
-
# If item name has no dots, add it directly to items array.
|
451
|
-
# Otherwise look up the parent of item and add it as the
|
452
|
-
# property of that parent.
|
453
|
-
items = []
|
454
|
-
raw_items.each do |it|
|
455
|
-
if it[:name] =~ /^(.+)\.([^.]+)$/
|
456
|
-
it[:name] = $2
|
457
|
-
parent = index[$1]
|
458
|
-
if parent
|
459
|
-
parent[:properties] = [] unless parent[:properties]
|
460
|
-
parent[:properties] << it
|
461
|
-
else
|
462
|
-
Logger.instance.warn(:subproperty, "Ignoring subproperty #{$1}.#{$2}, no parent found with name '#{$1}'.", @filename, @linenr)
|
463
|
-
end
|
140
|
+
def merge_name(docs, code)
|
141
|
+
if docs[:name]
|
142
|
+
docs[:name]
|
143
|
+
elsif code[:name]
|
144
|
+
if docs[:tagname] == :class
|
145
|
+
code[:name]
|
464
146
|
else
|
465
|
-
|
147
|
+
code[:name].split(/\./).last
|
466
148
|
end
|
149
|
+
else
|
150
|
+
""
|
467
151
|
end
|
468
|
-
items
|
469
|
-
end
|
470
|
-
|
471
|
-
def detect_return(doc_map, default_type="undefined")
|
472
|
-
ret = doc_map[:return] ? doc_map[:return].first : {}
|
473
|
-
return {
|
474
|
-
:type => ret[:type] || default_type,
|
475
|
-
:name => ret[:name] || "return",
|
476
|
-
:doc => ret[:doc] || "",
|
477
|
-
:properties => doc_map[:return] ? detect_subproperties(doc_map[:return], :return) : []
|
478
|
-
}
|
479
152
|
end
|
480
153
|
|
481
|
-
def
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
}
|
154
|
+
def merge_if_code_matches(key, docs, code, default=nil)
|
155
|
+
if docs[key]
|
156
|
+
docs[key]
|
157
|
+
elsif code[key] && code_matches_doc?(docs, code)
|
158
|
+
code[key]
|
159
|
+
else
|
160
|
+
default
|
489
161
|
end
|
490
162
|
end
|
491
163
|
|
492
|
-
#
|
493
|
-
#
|
494
|
-
def
|
495
|
-
|
496
|
-
doc_tags = docs.find_all { |tag| !ignore_tags.include?(tag[:tagname]) && !subproperty?(tag) }
|
497
|
-
doc_tags.map { |tag| tag[:doc] }.compact.join(" ")
|
498
|
-
end
|
499
|
-
|
500
|
-
def subproperty?(tag)
|
501
|
-
(tag[:tagname] == :cfg || tag[:tagname] == :property) && tag[:name] =~ /\./
|
164
|
+
# True if the name detected from code matches with explicitly documented name.
|
165
|
+
# Also true when no explicit name documented.
|
166
|
+
def code_matches_doc?(docs, code)
|
167
|
+
return docs[:name] == nil || docs[:name] == code[:name]
|
502
168
|
end
|
503
169
|
|
504
|
-
# Build map of at-tags for quick lookup
|
505
|
-
def build_doc_map(docs)
|
506
|
-
map = {}
|
507
|
-
docs.each do |tag|
|
508
|
-
if map[tag[:tagname]]
|
509
|
-
map[tag[:tagname]] << tag
|
510
|
-
else
|
511
|
-
map[tag[:tagname]] = [tag]
|
512
|
-
end
|
513
|
-
end
|
514
|
-
map
|
515
|
-
end
|
516
170
|
end
|
517
171
|
|
518
172
|
end
|