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.
- data/.travis.yml +0 -1
- data/README.md +32 -6
- data/Rakefile +10 -18
- data/bin/compare +5 -5
- data/bin/jsduck +2 -3
- data/jsduck.gemspec +3 -4
- data/lib/jsduck/aggregator.rb +21 -80
- data/lib/jsduck/app.rb +7 -14
- data/lib/jsduck/app_data.rb +4 -5
- data/lib/jsduck/assets.rb +4 -7
- data/lib/jsduck/base_type.rb +53 -0
- data/lib/jsduck/batch_parser.rb +8 -87
- data/lib/jsduck/batch_processor.rb +77 -0
- data/lib/jsduck/categories/auto.rb +83 -0
- data/lib/jsduck/categories/class_name.rb +63 -0
- data/lib/jsduck/categories/factory.rb +113 -0
- data/lib/jsduck/categories/file.rb +75 -0
- data/lib/jsduck/class.rb +3 -9
- data/lib/jsduck/class_doc_expander.rb +1 -1
- data/lib/jsduck/css/lexer.rb +203 -0
- data/lib/jsduck/css/parser.rb +121 -0
- data/lib/jsduck/doc/comment.rb +40 -0
- data/lib/jsduck/doc/map.rb +23 -0
- data/lib/jsduck/doc/parser.rb +128 -0
- data/lib/jsduck/doc/processor.rb +52 -0
- data/lib/jsduck/doc/scanner.rb +76 -0
- data/lib/jsduck/doc/standard_tag_parser.rb +154 -0
- data/lib/jsduck/doc/subproperties.rb +64 -0
- data/lib/jsduck/docs_code_comparer.rb +31 -0
- data/lib/jsduck/export_writer.rb +2 -2
- data/lib/jsduck/exporter/app.rb +16 -4
- data/lib/jsduck/exporter/full.rb +2 -2
- data/lib/jsduck/format/batch.rb +58 -0
- data/lib/jsduck/format/class.rb +62 -0
- data/lib/jsduck/format/doc.rb +172 -0
- data/lib/jsduck/format/html_stack.rb +109 -0
- data/lib/jsduck/format/shortener.rb +55 -0
- data/lib/jsduck/format/subproperties.rb +64 -0
- data/lib/jsduck/guides.rb +32 -14
- data/lib/jsduck/index_html.rb +3 -1
- data/lib/jsduck/inline/auto_link.rb +2 -2
- data/lib/jsduck/inline/link.rb +4 -3
- data/lib/jsduck/inline/link_renderer.rb +2 -2
- data/lib/jsduck/inline/video.rb +8 -2
- data/lib/jsduck/js/ast.rb +361 -0
- data/lib/jsduck/js/esprima.rb +39 -0
- data/lib/jsduck/{esprima → js/esprima}/esprima.js +0 -0
- data/lib/jsduck/js/evaluator.rb +70 -0
- data/lib/jsduck/js/ext_patterns.rb +70 -0
- data/lib/jsduck/js/function.rb +206 -0
- data/lib/jsduck/js/node.rb +194 -0
- data/lib/jsduck/js/node_array.rb +36 -0
- data/lib/jsduck/js/parser.rb +223 -0
- data/lib/jsduck/js/serializer.rb +263 -0
- data/lib/jsduck/js/utils.rb +21 -0
- data/lib/jsduck/logger.rb +3 -13
- data/lib/jsduck/members_index.rb +3 -4
- data/lib/jsduck/merger.rb +25 -145
- data/lib/jsduck/options.rb +29 -132
- data/lib/jsduck/parser.rb +76 -0
- data/lib/jsduck/process/accessors.rb +133 -0
- data/lib/jsduck/process/circular_deps.rb +58 -0
- data/lib/jsduck/process/enums.rb +91 -0
- data/lib/jsduck/process/ext4_events.rb +43 -0
- data/lib/jsduck/process/global_members.rb +36 -0
- data/lib/jsduck/process/ignored_classes.rb +16 -0
- data/lib/jsduck/process/importer.rb +58 -0
- data/lib/jsduck/process/inherit_doc.rb +197 -0
- data/lib/jsduck/process/lint.rb +135 -0
- data/lib/jsduck/process/overrides.rb +99 -0
- data/lib/jsduck/process/return_values.rb +72 -0
- data/lib/jsduck/process/versions.rb +102 -0
- data/lib/jsduck/relations.rb +5 -0
- data/lib/jsduck/render/class.rb +144 -0
- data/lib/jsduck/render/sidebar.rb +97 -0
- data/lib/jsduck/render/signature.rb +94 -0
- data/lib/jsduck/render/subproperties.rb +99 -0
- data/lib/jsduck/render/tags.rb +38 -0
- data/lib/jsduck/search_data.rb +19 -13
- data/lib/jsduck/source/file.rb +8 -17
- data/lib/jsduck/tag/abstract.rb +4 -7
- data/lib/jsduck/tag/accessor.rb +10 -0
- data/lib/jsduck/tag/alias.rb +61 -0
- data/lib/jsduck/tag/alternate_class_names.rb +17 -0
- data/lib/jsduck/tag/aside.rb +28 -31
- data/lib/jsduck/tag/author.rb +9 -5
- data/lib/jsduck/tag/boolean_tag.rb +24 -0
- data/lib/jsduck/tag/cfg.rb +45 -0
- data/lib/jsduck/tag/chainable.rb +5 -7
- data/lib/jsduck/tag/class.rb +28 -0
- data/lib/jsduck/tag/class_list_tag.rb +40 -0
- data/lib/jsduck/tag/constructor.rb +24 -0
- data/lib/jsduck/tag/css_mixin.rb +17 -0
- data/lib/jsduck/tag/css_var.rb +29 -0
- data/lib/jsduck/tag/default.rb +31 -0
- data/lib/jsduck/tag/deprecated.rb +13 -27
- data/lib/jsduck/tag/deprecated_tag.rb +58 -0
- data/lib/jsduck/tag/doc.rb +32 -0
- data/lib/jsduck/tag/docauthor.rb +4 -5
- data/lib/jsduck/tag/enum.rb +70 -0
- data/lib/jsduck/tag/event.rb +28 -0
- data/lib/jsduck/tag/evented.rb +10 -0
- data/lib/jsduck/tag/extends.rb +45 -0
- data/lib/jsduck/tag/ftype.rb +18 -0
- data/lib/jsduck/tag/hide.rb +4 -11
- data/lib/jsduck/tag/ignore.rb +6 -7
- data/lib/jsduck/tag/inheritable.rb +10 -0
- data/lib/jsduck/tag/inheritdoc.rb +48 -0
- data/lib/jsduck/tag/markdown.rb +8 -6
- data/lib/jsduck/tag/member.rb +24 -0
- data/lib/jsduck/tag/method.rb +35 -0
- data/lib/jsduck/tag/mixins.rb +26 -0
- data/lib/jsduck/tag/name.rb +36 -0
- data/lib/jsduck/tag/new.rb +13 -27
- data/lib/jsduck/tag/override.rb +37 -0
- data/lib/jsduck/tag/overrides.rb +29 -0
- data/lib/jsduck/tag/param.rb +87 -0
- data/lib/jsduck/tag/preventable.rb +19 -10
- data/lib/jsduck/tag/private.rb +28 -13
- data/lib/jsduck/tag/property.rb +39 -0
- data/lib/jsduck/tag/protected.rb +5 -7
- data/lib/jsduck/tag/ptype.rb +18 -0
- data/lib/jsduck/tag/readonly.rb +4 -7
- data/lib/jsduck/tag/removed.rb +21 -29
- data/lib/jsduck/tag/required.rb +11 -9
- data/lib/jsduck/tag/requires.rb +12 -0
- data/lib/jsduck/tag/return.rb +47 -0
- data/lib/jsduck/tag/since.rb +19 -11
- data/lib/jsduck/tag/singleton.rb +15 -0
- data/lib/jsduck/tag/static.rb +5 -7
- data/lib/jsduck/tag/subproperties.rb +23 -0
- data/lib/jsduck/tag/tag.rb +208 -0
- data/lib/jsduck/tag/template.rb +14 -9
- data/lib/jsduck/tag/throws.rb +38 -0
- data/lib/jsduck/tag/type.rb +48 -0
- data/lib/jsduck/tag/uses.rb +12 -0
- data/lib/jsduck/tag/xtype.rb +30 -0
- data/lib/jsduck/tag_loader.rb +39 -0
- data/lib/jsduck/tag_registry.rb +189 -0
- data/lib/jsduck/type_parser.rb +3 -3
- data/lib/jsduck/web_writer.rb +2 -2
- data/lib/jsduck/welcome.rb +1 -1
- metadata +578 -538
- data/lib/jsduck/accessors.rb +0 -136
- data/lib/jsduck/ast.rb +0 -524
- data/lib/jsduck/auto_categories.rb +0 -80
- data/lib/jsduck/batch_formatter.rb +0 -60
- data/lib/jsduck/categories.rb +0 -73
- data/lib/jsduck/categories_class_name.rb +0 -37
- data/lib/jsduck/circular_deps.rb +0 -56
- data/lib/jsduck/class_formatter.rb +0 -102
- data/lib/jsduck/columns.rb +0 -56
- data/lib/jsduck/css_lexer.rb +0 -201
- data/lib/jsduck/css_parser.rb +0 -119
- data/lib/jsduck/doc_ast.rb +0 -319
- data/lib/jsduck/doc_formatter.rb +0 -142
- data/lib/jsduck/doc_parser.rb +0 -611
- data/lib/jsduck/doc_type.rb +0 -59
- data/lib/jsduck/enum.rb +0 -73
- data/lib/jsduck/esprima.rb +0 -51
- data/lib/jsduck/evaluator.rb +0 -69
- data/lib/jsduck/ext_patterns.rb +0 -58
- data/lib/jsduck/file_categories.rb +0 -76
- data/lib/jsduck/function_ast.rb +0 -206
- data/lib/jsduck/guide_anchors.rb +0 -32
- data/lib/jsduck/guide_toc.rb +0 -49
- data/lib/jsduck/html_stack.rb +0 -105
- data/lib/jsduck/importer.rb +0 -121
- data/lib/jsduck/inherit_doc.rb +0 -193
- data/lib/jsduck/js_parser.rb +0 -221
- data/lib/jsduck/lint.rb +0 -133
- data/lib/jsduck/meta_tag.rb +0 -88
- data/lib/jsduck/meta_tag_loader.rb +0 -67
- data/lib/jsduck/meta_tag_registry.rb +0 -111
- data/lib/jsduck/meta_tag_renderer.rb +0 -34
- data/lib/jsduck/news.rb +0 -128
- data/lib/jsduck/override.rb +0 -87
- data/lib/jsduck/renderer.rb +0 -361
- data/lib/jsduck/return_values.rb +0 -72
- data/lib/jsduck/serializer.rb +0 -262
- data/lib/jsduck/shortener.rb +0 -58
- data/lib/jsduck/signature_renderer.rb +0 -91
- 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
|