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/.gitignore
CHANGED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
jsduck (3.11.0)
|
5
|
+
execjs
|
6
|
+
json
|
7
|
+
parallel
|
8
|
+
rdiscount
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
chunky_png (1.2.5)
|
14
|
+
compass (0.12.2)
|
15
|
+
chunky_png (~> 1.2)
|
16
|
+
fssm (>= 0.2.7)
|
17
|
+
sass (~> 3.1)
|
18
|
+
diff-lcs (1.1.3)
|
19
|
+
execjs (1.4.0)
|
20
|
+
multi_json (~> 1.0)
|
21
|
+
fssm (0.2.9)
|
22
|
+
json (1.7.3)
|
23
|
+
multi_json (1.3.6)
|
24
|
+
parallel (0.5.17)
|
25
|
+
rake (0.9.2.2)
|
26
|
+
rdiscount (1.6.8)
|
27
|
+
rspec (2.10.0)
|
28
|
+
rspec-core (~> 2.10.0)
|
29
|
+
rspec-expectations (~> 2.10.0)
|
30
|
+
rspec-mocks (~> 2.10.0)
|
31
|
+
rspec-core (2.10.1)
|
32
|
+
rspec-expectations (2.10.0)
|
33
|
+
diff-lcs (~> 1.1.3)
|
34
|
+
rspec-mocks (2.10.1)
|
35
|
+
sass (3.1.19)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
x86-mingw32
|
40
|
+
|
41
|
+
DEPENDENCIES
|
42
|
+
compass
|
43
|
+
jsduck!
|
44
|
+
rake
|
45
|
+
rspec
|
data/README.md
CHANGED
@@ -41,10 +41,7 @@ For **Windows** users out there, you can download the binary version,
|
|
41
41
|
which includes Ruby interpreter and all dependencies bundled in a
|
42
42
|
single .exe file. Grab it from the [download page][].
|
43
43
|
|
44
|
-
If you are brave enough: [try out JSDuck 4.0 beta.][beta]
|
45
|
-
|
46
44
|
[download page]: https://github.com/senchalabs/jsduck/downloads
|
47
|
-
[beta]: https://github.com/senchalabs/jsduck/wiki/4.0-beta
|
48
45
|
|
49
46
|
Usage
|
50
47
|
-----
|
data/Rakefile
CHANGED
@@ -220,6 +220,7 @@ task :ext4 => :sass do
|
|
220
220
|
runner = JsDuckRunner.new
|
221
221
|
runner.add_ext4
|
222
222
|
runner.add_debug
|
223
|
+
runner.add_options("--tests")
|
223
224
|
runner.run
|
224
225
|
|
225
226
|
system("cp -r #{EXT_BUILD} #{OUT_DIR}/extjs-build")
|
@@ -232,7 +233,8 @@ task :sdk => :sass do
|
|
232
233
|
"--output", OUT_DIR,
|
233
234
|
"--config", "#{SDK_DIR}/extjs/docs/config.json",
|
234
235
|
"--examples-base-url", "extjs-build/examples/",
|
235
|
-
"--seo"
|
236
|
+
"--seo",
|
237
|
+
"--tests"
|
236
238
|
)
|
237
239
|
runner.add_debug
|
238
240
|
runner.add_comments('ext-js', '4')
|
@@ -248,7 +250,8 @@ task :touch2 => :sass do
|
|
248
250
|
"--output", OUT_DIR,
|
249
251
|
"--config", "#{SDK_DIR}/touch/docs/config.json",
|
250
252
|
"--examples-base-url", "touch-build/examples/production/",
|
251
|
-
"--seo"
|
253
|
+
"--seo",
|
254
|
+
"--tests"
|
252
255
|
)
|
253
256
|
|
254
257
|
runner.add_debug
|
data/js-classes/String.js
CHANGED
@@ -949,7 +949,7 @@
|
|
949
949
|
*
|
950
950
|
* The following example displays the string "sencha":
|
951
951
|
*
|
952
|
-
* var upperText="
|
952
|
+
* var upperText="sencha";
|
953
953
|
* document.write(upperText.toLocaleLowerCase());
|
954
954
|
*
|
955
955
|
* @return {String} Returns value of the string in lowercase.
|
data/jsduck.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.required_rubygems_version = ">= 1.3.5"
|
3
3
|
|
4
4
|
s.name = 'jsduck'
|
5
|
-
s.version = '
|
6
|
-
s.date = '2012-
|
5
|
+
s.version = '4.0.beta'
|
6
|
+
s.date = '2012-06-27'
|
7
7
|
s.summary = "Simple JavaScript Duckumentation generator"
|
8
8
|
s.description = "Documentation generator for Sencha JS frameworks"
|
9
9
|
s.homepage = "https://github.com/senchalabs/jsduck"
|
@@ -16,12 +16,15 @@ Gem::Specification.new do |s|
|
|
16
16
|
end
|
17
17
|
# Add files not in git
|
18
18
|
s.files += Dir['template-min/**/*']
|
19
|
+
# Add Esprima
|
20
|
+
s.files += Dir['esprima/esprima.js']
|
19
21
|
|
20
22
|
s.executables = ["jsduck"]
|
21
23
|
|
22
24
|
s.add_dependency 'rdiscount'
|
23
25
|
s.add_dependency 'json'
|
24
26
|
s.add_dependency 'parallel'
|
27
|
+
s.add_dependency 'execjs'
|
25
28
|
|
26
29
|
s.add_development_dependency 'rspec'
|
27
30
|
s.add_development_dependency 'rake'
|
data/lib/jsduck/accessors.rb
CHANGED
data/lib/jsduck/aggregator.rb
CHANGED
@@ -205,7 +205,10 @@ module JsDuck
|
|
205
205
|
end
|
206
206
|
|
207
207
|
# Appends Ext4 options parameter to each event parameter list.
|
208
|
+
# But only when we are dealing with Ext4 codebase.
|
208
209
|
def append_ext4_event_options
|
210
|
+
return unless ext4?
|
211
|
+
|
209
212
|
options = {
|
210
213
|
:tagname => :param,
|
211
214
|
:name => "eOpts",
|
data/lib/jsduck/app.rb
CHANGED
@@ -124,9 +124,7 @@ module JsDuck
|
|
124
124
|
agr.create_global_class
|
125
125
|
agr.remove_ignored_classes
|
126
126
|
agr.create_accessors
|
127
|
-
|
128
|
-
agr.append_ext4_event_options
|
129
|
-
end
|
127
|
+
agr.append_ext4_event_options
|
130
128
|
agr.result
|
131
129
|
end
|
132
130
|
|
@@ -165,15 +163,14 @@ module JsDuck
|
|
165
163
|
class_formatter.include_types = !@opts.export
|
166
164
|
# Format all doc-objects in parallel
|
167
165
|
formatted_classes = @parallel.map(@relations.classes) do |cls|
|
168
|
-
|
169
|
-
Logger.instance.log("Markdown formatting #{cls[:name]}", files)
|
166
|
+
Logger.instance.log("Markdown formatting #{cls[:name]}")
|
170
167
|
begin
|
171
168
|
{
|
172
169
|
:doc => class_formatter.format(cls.internal_doc),
|
173
170
|
:images => doc_formatter.images
|
174
171
|
}
|
175
172
|
rescue
|
176
|
-
Logger.instance.fatal("Error while formatting #{cls[:name]}
|
173
|
+
Logger.instance.fatal("Error while formatting #{cls[:name]}", $!)
|
177
174
|
exit(1)
|
178
175
|
end
|
179
176
|
end
|
data/lib/jsduck/ast.rb
ADDED
@@ -0,0 +1,446 @@
|
|
1
|
+
require "jsduck/serializer"
|
2
|
+
require "jsduck/evaluator"
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
|
6
|
+
# Analyzes the AST produced by EsprimaParser.
|
7
|
+
class Ast
|
8
|
+
# Should be initialized with EsprimaParser#parse result.
|
9
|
+
def initialize(docs = [], options = {})
|
10
|
+
@serializer = JsDuck::Serializer.new
|
11
|
+
@evaluator = JsDuck::Evaluator.new
|
12
|
+
@ext_define_patterns = build_ext_define_patterns(options[:ext_namespaces] || ["Ext"])
|
13
|
+
@docs = docs
|
14
|
+
end
|
15
|
+
|
16
|
+
# Given Array of alternate Ext namespaces builds list of patterns
|
17
|
+
# for detecting Ext.define:
|
18
|
+
#
|
19
|
+
# ["Ext","Foo"] --> ["Ext.define", "Ext.ClassManager.create", "Foo.define", "Foo.ClassManager.create"]
|
20
|
+
#
|
21
|
+
def build_ext_define_patterns(namespaces)
|
22
|
+
namespaces.map do |ns|
|
23
|
+
[ns + ".define", ns + ".ClassManager.create"]
|
24
|
+
end.flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
# Performs the detection of code in all docsets.
|
28
|
+
#
|
29
|
+
# @returns the processed array of docsets. (But it does it
|
30
|
+
# destructively by modifying the passed-in docsets.)
|
31
|
+
#
|
32
|
+
def detect_all!
|
33
|
+
# First deal only with doc-comments
|
34
|
+
doc_comments = @docs.find_all {|d| d[:type] == :doc_comment }
|
35
|
+
|
36
|
+
# Detect code in each docset. Sometimes a docset has already
|
37
|
+
# been detected as part of detecting some previous docset (like
|
38
|
+
# Class detecting all of its configs) - in such case, skip.
|
39
|
+
doc_comments.each do |docset|
|
40
|
+
code = docset[:code]
|
41
|
+
docset[:code] = detect(code) unless code && code[:tagname]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return all doc-comments + other comments for which related
|
45
|
+
# code was detected.
|
46
|
+
@docs.find_all {|d| d[:type] == :doc_comment || d[:code] && d[:code][:tagname] }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Given Esprima-produced syntax tree, detects documentation data.
|
50
|
+
#
|
51
|
+
# This method is exposed for testing purposes only, JSDuck itself
|
52
|
+
# only calls the above #detect_all method.
|
53
|
+
#
|
54
|
+
# @param ast :code from Result of EsprimaParser
|
55
|
+
# @returns Hash consisting of the detected :tagname, :name, and
|
56
|
+
# other properties relative to the tag. Like so:
|
57
|
+
#
|
58
|
+
# { :tagname => :method, :name => "foo", ... }
|
59
|
+
#
|
60
|
+
def detect(ast)
|
61
|
+
ast = ast || {}
|
62
|
+
|
63
|
+
exp = expression?(ast) ? ast["expression"] : nil
|
64
|
+
var = var?(ast) ? ast["declarations"][0] : nil
|
65
|
+
|
66
|
+
# Ext.define("Class", {})
|
67
|
+
if exp && ext_define?(exp)
|
68
|
+
make_class(to_value(exp["arguments"][0]), exp)
|
69
|
+
|
70
|
+
# foo = Ext.extend("Parent", {})
|
71
|
+
elsif exp && assignment?(exp) && ext_extend?(exp["right"])
|
72
|
+
make_class(to_s(exp["left"]), exp["right"])
|
73
|
+
|
74
|
+
# Foo = ...
|
75
|
+
elsif exp && assignment?(exp) && class_name?(to_s(exp["left"]))
|
76
|
+
make_class(to_s(exp["left"]))
|
77
|
+
|
78
|
+
# var foo = Ext.extend("Parent", {})
|
79
|
+
elsif var && var["init"] && ext_extend?(var["init"])
|
80
|
+
make_class(to_s(var["id"]), var["init"])
|
81
|
+
|
82
|
+
# var Foo = ...
|
83
|
+
elsif var && class_name?(to_s(var["id"]))
|
84
|
+
make_class(to_s(var["id"]))
|
85
|
+
|
86
|
+
# function Foo() {}
|
87
|
+
elsif function?(ast) && class_name?(to_s(ast["id"]))
|
88
|
+
make_class(to_s(ast["id"]))
|
89
|
+
|
90
|
+
# function foo() {}
|
91
|
+
elsif function?(ast)
|
92
|
+
make_method(to_s(ast["id"]), ast)
|
93
|
+
|
94
|
+
# foo = function() {}
|
95
|
+
elsif exp && assignment?(exp) && function?(exp["right"])
|
96
|
+
make_method(to_s(exp["left"]), exp["right"])
|
97
|
+
|
98
|
+
# var foo = function() {}
|
99
|
+
elsif var && var["init"] && function?(var["init"])
|
100
|
+
make_method(to_s(var["id"]), var["init"])
|
101
|
+
|
102
|
+
# (function() {})
|
103
|
+
elsif exp && function?(exp)
|
104
|
+
make_method(exp["id"] ? to_s(exp["id"]) : "", exp)
|
105
|
+
|
106
|
+
# foo: function() {}
|
107
|
+
elsif property?(ast) && function?(ast["value"])
|
108
|
+
make_method(key_value(ast["key"]), ast["value"])
|
109
|
+
|
110
|
+
# foo = ...
|
111
|
+
elsif exp && assignment?(exp)
|
112
|
+
make_property(to_s(exp["left"]), exp["right"])
|
113
|
+
|
114
|
+
# var foo = ...
|
115
|
+
elsif var
|
116
|
+
make_property(to_s(var["id"]), var["init"])
|
117
|
+
|
118
|
+
# foo: ...
|
119
|
+
elsif property?(ast)
|
120
|
+
make_property(key_value(ast["key"]), ast["value"])
|
121
|
+
|
122
|
+
# foo;
|
123
|
+
elsif exp && ident?(exp)
|
124
|
+
make_property(to_s(exp))
|
125
|
+
|
126
|
+
# "foo" (inside some expression)
|
127
|
+
elsif string?(ast)
|
128
|
+
make_property(to_value(ast))
|
129
|
+
|
130
|
+
# "foo"; (as a statement of it's own)
|
131
|
+
elsif exp && string?(exp)
|
132
|
+
make_property(to_value(exp))
|
133
|
+
|
134
|
+
else
|
135
|
+
make_property()
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def expression?(ast)
|
142
|
+
ast["type"] == "ExpressionStatement"
|
143
|
+
end
|
144
|
+
|
145
|
+
def call?(ast)
|
146
|
+
ast["type"] == "CallExpression"
|
147
|
+
end
|
148
|
+
|
149
|
+
def assignment?(ast)
|
150
|
+
ast["type"] == "AssignmentExpression"
|
151
|
+
end
|
152
|
+
|
153
|
+
def ext_define?(ast)
|
154
|
+
call?(ast) && @ext_define_patterns.include?(to_s(ast["callee"]))
|
155
|
+
end
|
156
|
+
|
157
|
+
def ext_extend?(ast)
|
158
|
+
call?(ast) && to_s(ast["callee"]) == "Ext.extend"
|
159
|
+
end
|
160
|
+
|
161
|
+
def function?(ast)
|
162
|
+
ast["type"] == "FunctionDeclaration" || ast["type"] == "FunctionExpression" || empty_fn?(ast)
|
163
|
+
end
|
164
|
+
|
165
|
+
def empty_fn?(ast)
|
166
|
+
ast["type"] == "MemberExpression" && to_s(ast) == "Ext.emptyFn"
|
167
|
+
end
|
168
|
+
|
169
|
+
def var?(ast)
|
170
|
+
ast["type"] == "VariableDeclaration"
|
171
|
+
end
|
172
|
+
|
173
|
+
def property?(ast)
|
174
|
+
ast["type"] == "Property"
|
175
|
+
end
|
176
|
+
|
177
|
+
def ident?(ast)
|
178
|
+
ast["type"] == "Identifier"
|
179
|
+
end
|
180
|
+
|
181
|
+
def string?(ast)
|
182
|
+
ast["type"] == "Literal" && ast["value"].is_a?(String)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Class name begins with upcase char
|
186
|
+
def class_name?(name)
|
187
|
+
return name.split(/\./).last =~ /\A[A-Z]/
|
188
|
+
end
|
189
|
+
|
190
|
+
def make_class(name, ast=nil)
|
191
|
+
cls = {
|
192
|
+
:tagname => :class,
|
193
|
+
:name => name,
|
194
|
+
}
|
195
|
+
|
196
|
+
# apply information from Ext.extend or Ext.define
|
197
|
+
if ast
|
198
|
+
if ext_extend?(ast)
|
199
|
+
cls[:extends] = to_s(ast["arguments"][0])
|
200
|
+
elsif ext_define?(ast)
|
201
|
+
detect_ext_define(cls, ast)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
return cls
|
206
|
+
end
|
207
|
+
|
208
|
+
# Inspects Ext.define() and copies detected properties over to the
|
209
|
+
# given cls Hash
|
210
|
+
def detect_ext_define(cls, ast)
|
211
|
+
# defaults
|
212
|
+
cls[:extends] = "Ext.Base"
|
213
|
+
cls[:requires] = []
|
214
|
+
cls[:uses] = []
|
215
|
+
cls[:alternateClassNames] = []
|
216
|
+
cls[:mixins] = []
|
217
|
+
cls[:aliases] = []
|
218
|
+
cls[:members] = []
|
219
|
+
cls[:statics] = []
|
220
|
+
|
221
|
+
each_pair_in_object_expression(ast["arguments"][1]) do |key, value, pair|
|
222
|
+
case key
|
223
|
+
when "extend"
|
224
|
+
cls[:extends] = make_extends(value)
|
225
|
+
when "requires"
|
226
|
+
cls[:requires] = make_string_list(value)
|
227
|
+
when "uses"
|
228
|
+
cls[:uses] = make_string_list(value)
|
229
|
+
when "alternateClassName"
|
230
|
+
cls[:alternateClassNames] = make_string_list(value)
|
231
|
+
when "mixins"
|
232
|
+
cls[:mixins] = make_mixins(value)
|
233
|
+
when "singleton"
|
234
|
+
cls[:singleton] = make_singleton(value)
|
235
|
+
when "alias"
|
236
|
+
cls[:aliases] += make_string_list(value)
|
237
|
+
when "xtype"
|
238
|
+
cls[:aliases] += make_string_list(value).map {|xtype| "widget."+xtype }
|
239
|
+
when "config"
|
240
|
+
cls[:members] += make_configs(value, {:accessor => true})
|
241
|
+
when "cachedConfig"
|
242
|
+
cls[:members] += make_configs(value, {:accessor => true})
|
243
|
+
when "eventedConfig"
|
244
|
+
cls[:members] += make_configs(value, {:accessor => true, :evented => true})
|
245
|
+
when "statics"
|
246
|
+
cls[:statics] += make_statics(value)
|
247
|
+
when "inheritableStatics"
|
248
|
+
cls[:statics] += make_statics(value, {:inheritable => true})
|
249
|
+
else
|
250
|
+
if function?(value)
|
251
|
+
m = make_method(key, value)
|
252
|
+
cls[:members] << m if apply_autodetected(m, pair)
|
253
|
+
else
|
254
|
+
p = make_property(key, value)
|
255
|
+
cls[:members] << p if apply_autodetected(p, pair)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def make_extends(cfg_value)
|
262
|
+
return nil unless cfg_value
|
263
|
+
|
264
|
+
parent = to_value(cfg_value)
|
265
|
+
|
266
|
+
return parent.is_a?(String) ? parent : nil
|
267
|
+
end
|
268
|
+
|
269
|
+
def make_string_list(cfg_value)
|
270
|
+
return [] unless cfg_value
|
271
|
+
|
272
|
+
classes = Array(to_value(cfg_value))
|
273
|
+
|
274
|
+
return classes.all? {|c| c.is_a? String } ? classes : []
|
275
|
+
end
|
276
|
+
|
277
|
+
def make_mixins(cfg_value)
|
278
|
+
return [] unless cfg_value
|
279
|
+
|
280
|
+
v = to_value(cfg_value)
|
281
|
+
classes = v.is_a?(Hash) ? v.values : Array(v)
|
282
|
+
|
283
|
+
return classes.all? {|c| c.is_a? String } ? classes : []
|
284
|
+
end
|
285
|
+
|
286
|
+
def make_singleton(cfg_value)
|
287
|
+
cfg_value && to_value(cfg_value) == true
|
288
|
+
end
|
289
|
+
|
290
|
+
def make_configs(ast, defaults={})
|
291
|
+
configs = []
|
292
|
+
|
293
|
+
each_pair_in_object_expression(ast) do |name, value, pair|
|
294
|
+
cfg = make_property(name, value, :cfg)
|
295
|
+
cfg.merge!(defaults)
|
296
|
+
configs << cfg if apply_autodetected(cfg, pair)
|
297
|
+
end
|
298
|
+
|
299
|
+
configs
|
300
|
+
end
|
301
|
+
|
302
|
+
def make_statics(ast, defaults={})
|
303
|
+
statics = []
|
304
|
+
|
305
|
+
each_pair_in_object_expression(ast) do |name, value, pair|
|
306
|
+
if function?(value)
|
307
|
+
s = make_method(name, value)
|
308
|
+
else
|
309
|
+
s = make_property(name, value)
|
310
|
+
end
|
311
|
+
|
312
|
+
s[:meta] = {:static => true}
|
313
|
+
s.merge!(defaults)
|
314
|
+
|
315
|
+
statics << s if apply_autodetected(s, pair, defaults[:inheritable])
|
316
|
+
end
|
317
|
+
|
318
|
+
statics
|
319
|
+
end
|
320
|
+
|
321
|
+
# Sets auto-detection related properties :autodetected and
|
322
|
+
# :inheritdoc on the given member Hash.
|
323
|
+
#
|
324
|
+
# When member has a comment, adds code to the related docset and
|
325
|
+
# returns false.
|
326
|
+
#
|
327
|
+
# Otherwise detects the line number of member and returns true.
|
328
|
+
def apply_autodetected(m, pair, inheritable=true)
|
329
|
+
docset = find_docset(pair)
|
330
|
+
|
331
|
+
if !docset || docset[:type] != :doc_comment
|
332
|
+
if inheritable
|
333
|
+
m[:inheritdoc] = {}
|
334
|
+
else
|
335
|
+
m[:private] = true
|
336
|
+
end
|
337
|
+
m[:autodetected] = true
|
338
|
+
end
|
339
|
+
|
340
|
+
if docset
|
341
|
+
docset[:code] = m
|
342
|
+
return false
|
343
|
+
else
|
344
|
+
# Get line number from third place at range array.
|
345
|
+
# This third item exists in forked EsprimaJS at
|
346
|
+
# https://github.com/nene/esprima/tree/linenr-in-range
|
347
|
+
m[:linenr] = pair["range"][2]
|
348
|
+
return true
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# Looks up docset associated with given AST node.
|
353
|
+
# A dead-stupid and -slow implementation, but works.
|
354
|
+
def find_docset(ast)
|
355
|
+
@docs.find do |docset|
|
356
|
+
docset[:code] == ast
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def make_method(name, ast=nil)
|
361
|
+
return {
|
362
|
+
:tagname => :method,
|
363
|
+
:name => name,
|
364
|
+
:params => make_params(ast)
|
365
|
+
}
|
366
|
+
end
|
367
|
+
|
368
|
+
def make_params(ast)
|
369
|
+
if ast && !empty_fn?(ast)
|
370
|
+
ast["params"].map {|p| {:name => to_s(p)} }
|
371
|
+
else
|
372
|
+
[]
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def make_property(name=nil, ast=nil, tagname=:property)
|
377
|
+
return {
|
378
|
+
:tagname => tagname,
|
379
|
+
:name => name,
|
380
|
+
:type => make_value_type(ast),
|
381
|
+
:default => make_default(ast),
|
382
|
+
}
|
383
|
+
end
|
384
|
+
|
385
|
+
def make_default(ast)
|
386
|
+
ast && to_value(ast) != nil ? to_s(ast) : nil
|
387
|
+
end
|
388
|
+
|
389
|
+
def make_value_type(ast)
|
390
|
+
if ast
|
391
|
+
v = to_value(ast)
|
392
|
+
if v.is_a?(String)
|
393
|
+
"String"
|
394
|
+
elsif v.is_a?(Numeric)
|
395
|
+
"Number"
|
396
|
+
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
397
|
+
"Boolean"
|
398
|
+
elsif v.is_a?(Array)
|
399
|
+
"Array"
|
400
|
+
elsif v.is_a?(Hash)
|
401
|
+
"Object"
|
402
|
+
elsif v == :regexp
|
403
|
+
"RegExp"
|
404
|
+
else
|
405
|
+
nil
|
406
|
+
end
|
407
|
+
else
|
408
|
+
nil
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
# -- various helper methods --
|
413
|
+
|
414
|
+
# Iterates over keys and values in ObjectExpression. The keys
|
415
|
+
# are turned into strings, but values are left as is for further
|
416
|
+
# processing.
|
417
|
+
def each_pair_in_object_expression(ast)
|
418
|
+
return unless ast && ast["type"] == "ObjectExpression"
|
419
|
+
|
420
|
+
ast["properties"].each do |p|
|
421
|
+
yield(key_value(p["key"]), p["value"], p)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# Converts object expression property key to string value
|
426
|
+
def key_value(key)
|
427
|
+
@evaluator.key_value(key)
|
428
|
+
end
|
429
|
+
|
430
|
+
# Fully serializes the node
|
431
|
+
def to_s(ast)
|
432
|
+
@serializer.to_s(ast)
|
433
|
+
end
|
434
|
+
|
435
|
+
# Converts AST node into a value.
|
436
|
+
def to_value(ast)
|
437
|
+
begin
|
438
|
+
@evaluator.to_value(ast)
|
439
|
+
rescue
|
440
|
+
nil
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
end
|
446
|
+
|