jsduck 3.11.2 → 4.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- 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
|