jsduck 5.0.0.beta01 → 5.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -0
- data/README.md +6 -32
- data/Rakefile +5 -5
- data/bin/jsduck +0 -1
- data/js-classes/String.js +3 -5
- data/jsduck.gemspec +3 -2
- data/lib/jsduck/aggregator.rb +1 -3
- data/lib/jsduck/app.rb +2 -2
- data/lib/jsduck/categories/file.rb +0 -6
- data/lib/jsduck/class.rb +1 -2
- data/lib/jsduck/doc/parser.rb +12 -5
- data/lib/jsduck/doc/scanner.rb +6 -0
- data/lib/jsduck/doc/standard_tag_parser.rb +10 -5
- data/lib/jsduck/doc/subproperties.rb +9 -2
- data/lib/jsduck/docs_code_comparer.rb +20 -7
- data/lib/jsduck/exporter/app.rb +18 -13
- data/lib/jsduck/exporter/full.rb +18 -21
- data/lib/jsduck/format/doc.rb +0 -1
- data/lib/jsduck/format/html_stack.rb +1 -2
- data/lib/jsduck/format/subproperties.rb +2 -2
- data/lib/jsduck/inline/auto_link.rb +1 -1
- data/lib/jsduck/inline/img.rb +1 -1
- data/lib/jsduck/inline/link.rb +4 -6
- data/lib/jsduck/inline/video.rb +1 -2
- data/lib/jsduck/js/ast.rb +1 -1
- data/lib/jsduck/js/esprima.rb +24 -9
- data/lib/jsduck/logger.rb +50 -12
- data/lib/jsduck/members_index.rb +1 -2
- data/lib/jsduck/merger.rb +20 -2
- data/lib/jsduck/options.rb +125 -24
- data/lib/jsduck/process/accessors.rb +21 -8
- data/lib/jsduck/process/enums.rb +2 -3
- data/lib/jsduck/process/ext4_events.rb +2 -1
- data/lib/jsduck/process/global_members.rb +1 -2
- data/lib/jsduck/process/importer.rb +2 -6
- data/lib/jsduck/process/inherit_class.rb +58 -0
- data/lib/jsduck/process/inherit_doc.rb +6 -175
- data/lib/jsduck/process/inherit_members.rb +257 -0
- data/lib/jsduck/process/lint.rb +18 -7
- data/lib/jsduck/process/overrides.rb +1 -2
- data/lib/jsduck/render/class.rb +1 -1
- data/lib/jsduck/tag/alias.rb +2 -1
- data/lib/jsduck/tag/alternate_class_names.rb +1 -0
- data/lib/jsduck/tag/aside.rb +3 -3
- data/lib/jsduck/tag/author.rb +18 -3
- data/lib/jsduck/tag/autodetected.rb +21 -0
- data/lib/jsduck/tag/boolean_tag.rb +1 -1
- data/lib/jsduck/tag/cfg.rb +7 -3
- data/lib/jsduck/tag/class.rb +1 -1
- data/lib/jsduck/tag/class_list_tag.rb +1 -1
- data/lib/jsduck/tag/constructor.rb +1 -1
- data/lib/jsduck/tag/css_var.rb +1 -1
- data/lib/jsduck/tag/default.rb +1 -1
- data/lib/jsduck/tag/deprecated_tag.rb +1 -1
- data/lib/jsduck/tag/docauthor.rb +2 -0
- data/lib/jsduck/tag/enum.rb +2 -2
- data/lib/jsduck/tag/event.rb +1 -1
- data/lib/jsduck/tag/extends.rb +1 -1
- data/lib/jsduck/tag/ftype.rb +2 -1
- data/lib/jsduck/tag/inheritdoc.rb +1 -1
- data/lib/jsduck/tag/localdoc.rb +33 -0
- data/lib/jsduck/tag/markdown.rb +1 -1
- data/lib/jsduck/tag/member.rb +1 -1
- data/lib/jsduck/tag/method.rb +1 -1
- data/lib/jsduck/tag/mixins.rb +1 -0
- data/lib/jsduck/tag/override.rb +1 -1
- data/lib/jsduck/tag/param.rb +16 -5
- data/lib/jsduck/tag/preventable.rb +1 -1
- data/lib/jsduck/tag/property.rb +7 -3
- data/lib/jsduck/tag/ptype.rb +2 -1
- data/lib/jsduck/tag/requires.rb +1 -0
- data/lib/jsduck/tag/return.rb +2 -1
- data/lib/jsduck/tag/since.rb +1 -5
- data/lib/jsduck/tag/tag.rb +21 -12
- data/lib/jsduck/tag/throws.rb +2 -1
- data/lib/jsduck/tag/type.rb +2 -2
- data/lib/jsduck/tag/uses.rb +1 -0
- data/lib/jsduck/tag/xtype.rb +2 -1
- data/lib/jsduck/tag_loader.rb +26 -15
- data/lib/jsduck/tag_registry.rb +20 -11
- data/lib/jsduck/web/css.rb +22 -0
- data/lib/jsduck/web/data.rb +50 -0
- data/lib/jsduck/web/icons.rb +31 -0
- data/lib/jsduck/web/index_html.rb +88 -0
- data/lib/jsduck/web/search.rb +148 -0
- data/lib/jsduck/{source/writer.rb → web/source.rb} +2 -2
- data/lib/jsduck/web/template.rb +52 -0
- data/lib/jsduck/web/writer.rb +84 -0
- metadata +513 -488
- data/lib/jsduck/app_data.rb +0 -41
- data/lib/jsduck/icons.rb +0 -29
- data/lib/jsduck/index_html.rb +0 -84
- data/lib/jsduck/search_data.rb +0 -146
- data/lib/jsduck/template_dir.rb +0 -50
- data/lib/jsduck/web_writer.rb +0 -87
@@ -3,6 +3,17 @@ require 'jsduck/logger'
|
|
3
3
|
module JsDuck
|
4
4
|
module Process
|
5
5
|
|
6
|
+
# Expands accessors.
|
7
|
+
#
|
8
|
+
# Looks up configs with @accessor tag (or configs defined inside
|
9
|
+
# config: {} or eventedConfig: {} block).
|
10
|
+
#
|
11
|
+
# For such config "foo" it generates:
|
12
|
+
#
|
13
|
+
# - getter "getFoo"
|
14
|
+
# - setter "setFoo"
|
15
|
+
# - event "foochange" (when tagged with @evented)
|
16
|
+
#
|
6
17
|
class Accessors
|
7
18
|
def initialize(classes)
|
8
19
|
@classes = classes
|
@@ -13,6 +24,8 @@ module JsDuck
|
|
13
24
|
@classes.each_value {|cls| process(cls) }
|
14
25
|
end
|
15
26
|
|
27
|
+
private
|
28
|
+
|
16
29
|
# Given a class, generates accessor methods to configs with
|
17
30
|
# @accessor tag. Modifies the class by adding these methods.
|
18
31
|
# When class already contains a getter or setter, the method is
|
@@ -113,15 +126,15 @@ module JsDuck
|
|
113
126
|
}, cfg)
|
114
127
|
end
|
115
128
|
|
129
|
+
# Copy over from @cfg all the fields that aren't already present.
|
130
|
+
# Except :type and :default which don't make sense for methods and events.
|
116
131
|
def add_shared(hash, cfg)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
:hide => cfg[:hide],
|
124
|
-
})
|
132
|
+
ignored_fields = [:type, :default, :accessor, :evented]
|
133
|
+
|
134
|
+
cfg.each_pair do |key, value|
|
135
|
+
hash[key] = value unless ignored_fields.include?(key) || hash[key]
|
136
|
+
end
|
137
|
+
hash
|
125
138
|
end
|
126
139
|
|
127
140
|
def upcase_first(str)
|
data/lib/jsduck/process/enums.rb
CHANGED
@@ -60,8 +60,7 @@ module JsDuck
|
|
60
60
|
if m[:tagname] == :property
|
61
61
|
false
|
62
62
|
else
|
63
|
-
|
64
|
-
Logger.warn(:enum, "Enums can only contain properties, #{m[:tagname]} found instead.", f[:filename], f[:linenr])
|
63
|
+
Logger.warn(:enum, "Enums can only contain properties, #{m[:tagname]} found instead.", m[:files][0])
|
65
64
|
true
|
66
65
|
end
|
67
66
|
end
|
@@ -71,7 +70,7 @@ module JsDuck
|
|
71
70
|
# values default to being public.
|
72
71
|
def strip_inheritdoc(cls)
|
73
72
|
cls[:members].each do |p|
|
74
|
-
p[:inheritdoc] = nil if p[:autodetected]
|
73
|
+
p[:inheritdoc] = nil if p[:autodetected] && p[:autodetected][:tagname]
|
75
74
|
end
|
76
75
|
end
|
77
76
|
|
@@ -34,7 +34,8 @@ module JsDuck
|
|
34
34
|
:tagname => :params,
|
35
35
|
:name => "eOpts",
|
36
36
|
:type => "Object",
|
37
|
-
:doc => "The options object passed to {@link Ext.util.Observable#addListener}."
|
37
|
+
:doc => "The options object passed to {@link Ext.util.Observable#addListener}.",
|
38
|
+
:ext4_auto_param => true,
|
38
39
|
}
|
39
40
|
|
40
41
|
end
|
@@ -21,8 +21,7 @@ module JsDuck
|
|
21
21
|
@classes_hash["global"][:members].each do |m|
|
22
22
|
type = m[:tagname].to_s
|
23
23
|
name = m[:name]
|
24
|
-
|
25
|
-
Logger.warn(:global, "Global #{type}: #{name}", file[:filename], file[:linenr])
|
24
|
+
Logger.warn(:global, "Global #{type}: #{name}", m[:files][0])
|
26
25
|
end
|
27
26
|
|
28
27
|
# Throw away the "global" class when --ignore-global option used
|
@@ -42,12 +42,8 @@ module JsDuck
|
|
42
42
|
# creates index of all class members
|
43
43
|
def members_id_index(json)
|
44
44
|
index = {}
|
45
|
-
["members"
|
46
|
-
|
47
|
-
members.each do |m|
|
48
|
-
index[m["id"]] = true
|
49
|
-
end
|
50
|
-
end
|
45
|
+
json["members"].each do |m|
|
46
|
+
index[m["id"]] = true
|
51
47
|
end
|
52
48
|
index
|
53
49
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Process
|
5
|
+
|
6
|
+
# Deals with inheriting class documentation.
|
7
|
+
class InheritClass
|
8
|
+
def initialize(relations)
|
9
|
+
@relations = relations
|
10
|
+
end
|
11
|
+
|
12
|
+
# Inherits docs for class.
|
13
|
+
#
|
14
|
+
# For class we only inherit the value of :doc field.
|
15
|
+
#
|
16
|
+
# When the class we're inheriting from also has @inheritdoc tag,
|
17
|
+
# we first recursively resolve the inheritance of that class and
|
18
|
+
# only afterwards inherit to the current class.
|
19
|
+
def resolve(cls)
|
20
|
+
return unless cls[:inheritdoc]
|
21
|
+
|
22
|
+
parent = find_parent(cls)
|
23
|
+
if parent && parent[:inheritdoc]
|
24
|
+
resolve(parent)
|
25
|
+
end
|
26
|
+
|
27
|
+
if parent
|
28
|
+
cls[:doc] = parent[:doc] if cls[:doc].empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
cls[:inheritdoc] = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def find_parent(cls)
|
37
|
+
if cls[:inheritdoc][:cls]
|
38
|
+
# @inheritdoc MyClass
|
39
|
+
parent = @relations[cls[:inheritdoc][:cls]]
|
40
|
+
return warn("class not found", cls) unless parent
|
41
|
+
else
|
42
|
+
# @inheritdoc
|
43
|
+
parent = cls.parent
|
44
|
+
return warn("parent class not found", cls) unless parent
|
45
|
+
end
|
46
|
+
|
47
|
+
return parent
|
48
|
+
end
|
49
|
+
|
50
|
+
def warn(msg, cls)
|
51
|
+
Logger.warn(:inheritdoc, "@inheritdoc #{cls[:inheritdoc][:cls]} - #{msg}", cls[:files][0])
|
52
|
+
return nil
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'jsduck/logger'
|
2
2
|
require 'jsduck/class'
|
3
|
+
require 'jsduck/process/inherit_class'
|
4
|
+
require 'jsduck/process/inherit_members'
|
3
5
|
|
4
6
|
module JsDuck
|
5
7
|
module Process
|
@@ -8,189 +10,18 @@ module JsDuck
|
|
8
10
|
class InheritDoc
|
9
11
|
def initialize(relations)
|
10
12
|
@relations = relations
|
13
|
+
@inherit_class = InheritClass.new(@relations)
|
14
|
+
@inherit_members = InheritMembers.new(@relations)
|
11
15
|
end
|
12
16
|
|
13
17
|
# Performs all inheriting
|
14
18
|
def process_all!
|
15
19
|
@relations.each do |cls|
|
16
|
-
|
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]
|
20
|
+
@inherit_class.resolve(cls)
|
21
|
+
@inherit_members.resolve(cls)
|
158
22
|
end
|
159
23
|
end
|
160
24
|
|
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
25
|
end
|
195
26
|
|
196
27
|
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
require 'jsduck/class'
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
module Process
|
6
|
+
|
7
|
+
# Deals with inheriting member documentation.
|
8
|
+
class InheritMembers
|
9
|
+
def initialize(relations)
|
10
|
+
@relations = relations
|
11
|
+
end
|
12
|
+
|
13
|
+
# Inherits docs for all members in class.
|
14
|
+
#
|
15
|
+
# In case of members with explicit @inheritdoc tags we inherit
|
16
|
+
# the following fields when they're not empty in current member:
|
17
|
+
#
|
18
|
+
# - :doc
|
19
|
+
# - :params
|
20
|
+
# - :return
|
21
|
+
# - :throws
|
22
|
+
#
|
23
|
+
# In case of auto-detected members that inherit from a public
|
24
|
+
# member in parent class, we inherit all fields that aren't
|
25
|
+
# present in current member, plus the :type field.
|
26
|
+
#
|
27
|
+
# Auto-detected members inheriting from other private
|
28
|
+
# auto-detected members follow the same rules of inheritance as
|
29
|
+
# members with explicit @inheritdoc.
|
30
|
+
#
|
31
|
+
# Additionally auto-detected properties get turned into configs
|
32
|
+
# when a public configs with same name is detected in parent
|
33
|
+
# class.
|
34
|
+
#
|
35
|
+
def resolve(cls)
|
36
|
+
new_cfgs = []
|
37
|
+
|
38
|
+
cls.all_local_members.each do |member|
|
39
|
+
if member[:inheritdoc]
|
40
|
+
resolve_member(cls, member, new_cfgs)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
move_cfgs(cls, new_cfgs) if new_cfgs.length > 0
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def resolve_member(cls, m, new_cfgs)
|
50
|
+
parent = find_parent(m)
|
51
|
+
if parent && parent[:inheritdoc]
|
52
|
+
resolve_parent(cls, parent)
|
53
|
+
end
|
54
|
+
|
55
|
+
if m[:inheritdoc] && parent
|
56
|
+
if autodetected?(m) && !parent[:private]
|
57
|
+
auto_inherit(m, parent)
|
58
|
+
else
|
59
|
+
inherit(m, parent)
|
60
|
+
end
|
61
|
+
|
62
|
+
# remember properties that have changed to configs
|
63
|
+
if autodetected?(m) && m[:tagname] != parent[:tagname]
|
64
|
+
new_cfgs << m
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
resolve_visibility(m, parent)
|
69
|
+
|
70
|
+
m[:inheritdoc] = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def resolve_parent(cls, parent)
|
74
|
+
new_cfgs = []
|
75
|
+
resolve_member(cls, parent, new_cfgs)
|
76
|
+
move_cfgs(cls, new_cfgs) if new_cfgs.length > 0
|
77
|
+
end
|
78
|
+
|
79
|
+
def inherit(m, parent)
|
80
|
+
m[:doc] = parent[:doc] if m[:doc].empty?
|
81
|
+
|
82
|
+
m[:params] = parent[:params] if inherit_params?(m, parent)
|
83
|
+
m[:return] = parent[:return] unless m[:return]
|
84
|
+
m[:throws] = parent[:throws] unless m[:throws] && m[:throws].length > 0
|
85
|
+
|
86
|
+
# Don't inherit type from parent when:
|
87
|
+
# - member itself has type and it's not auto-detected
|
88
|
+
# - or the type in parent is auto-detected.
|
89
|
+
unless m[:type] && m[:type] != "Object" && !auto?(m, :type) || auto?(parent, :type)
|
90
|
+
m[:type] = parent[:type]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def inherit_params?(m, parent)
|
95
|
+
# ignore the auto-inserted param of Ext4-style events
|
96
|
+
params = (m[:params] || []).reject {|p| p[:ext4_auto_param] }
|
97
|
+
|
98
|
+
if params.length > 0 && !auto?(m, :params)
|
99
|
+
# member itself has params and these are not auto-detected
|
100
|
+
false
|
101
|
+
elsif auto?(parent, :params)
|
102
|
+
# Params in parent are auto-detected.
|
103
|
+
false
|
104
|
+
else
|
105
|
+
true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def auto_inherit(m, parent)
|
110
|
+
m[:doc] = parent[:doc] if m[:doc].empty?
|
111
|
+
|
112
|
+
parent.each_pair do |key, value|
|
113
|
+
if key == :type || !m[key]
|
114
|
+
m[key] = value
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# True when specific field of member has been auto-detected
|
120
|
+
def auto?(m, key)
|
121
|
+
m[:autodetected] && m[:autodetected][key]
|
122
|
+
end
|
123
|
+
|
124
|
+
# Changes given properties into configs within class
|
125
|
+
def move_cfgs(cls, members)
|
126
|
+
members.each do |m|
|
127
|
+
m[:tagname] = :cfg
|
128
|
+
end
|
129
|
+
# Ask class to update its internal caches for these members
|
130
|
+
cls.update_members!(members)
|
131
|
+
end
|
132
|
+
|
133
|
+
# For auto-detected members/classes (which have @private == :inherit)
|
134
|
+
# Use the visibility from parent class (defaulting to private when no parent).
|
135
|
+
def resolve_visibility(m, parent)
|
136
|
+
if autodetected?(m) && !JsDuck::Class.constructor?(m)
|
137
|
+
if !parent || parent[:private]
|
138
|
+
m[:private] = true
|
139
|
+
end
|
140
|
+
|
141
|
+
m[:protected] = true if parent && parent[:protected]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Finds parent member of the given member. When @inheritdoc names
|
146
|
+
# a member to inherit from, finds that member instead.
|
147
|
+
#
|
148
|
+
# If the parent also has @inheritdoc, continues recursively.
|
149
|
+
def find_parent(m)
|
150
|
+
|
151
|
+
inherit = m[:inheritdoc] || {}
|
152
|
+
if inherit[:cls]
|
153
|
+
# @inheritdoc MyClass#member
|
154
|
+
parent_cls = @relations[m[:inheritdoc][:cls]]
|
155
|
+
return warn("class not found", m) unless parent_cls
|
156
|
+
|
157
|
+
parent = lookup_member(parent_cls, m)
|
158
|
+
return warn("member not found", m) unless parent
|
159
|
+
|
160
|
+
elsif inherit[:member]
|
161
|
+
# @inheritdoc #member
|
162
|
+
parent = lookup_member(@relations[m[:owner]], m)
|
163
|
+
return warn("member not found", m) unless parent
|
164
|
+
|
165
|
+
else
|
166
|
+
# @inheritdoc
|
167
|
+
parent_cls = @relations[m[:owner]].parent
|
168
|
+
mixins = @relations[m[:owner]].mixins
|
169
|
+
|
170
|
+
# Warn when no parent or mixins at all
|
171
|
+
if !parent_cls && mixins.length == 0
|
172
|
+
warn("parent class not found", m) unless autodetected?(m)
|
173
|
+
return nil
|
174
|
+
end
|
175
|
+
|
176
|
+
# First check for the member in all mixins, because members
|
177
|
+
# from mixins override those from parent class. Looking first
|
178
|
+
# from mixins is probably a bit slower, but it's the correct
|
179
|
+
# order to do things.
|
180
|
+
if mixins.length > 0
|
181
|
+
parent = mixins.map {|mix| lookup_member(mix, m) }.compact.first
|
182
|
+
end
|
183
|
+
|
184
|
+
# When not found, try looking from parent class
|
185
|
+
if !parent && parent_cls
|
186
|
+
parent = lookup_member(parent_cls, m)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Only when both parent and mixins fail, throw warning
|
190
|
+
if !parent
|
191
|
+
warn("parent member not found", m) unless autodetected?(m)
|
192
|
+
return nil
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
return parent
|
197
|
+
end
|
198
|
+
|
199
|
+
def lookup_member(cls, m)
|
200
|
+
inherit = m[:inheritdoc] || {}
|
201
|
+
name = inherit[:member] || m[:name]
|
202
|
+
tagname = inherit[:type] || m[:tagname]
|
203
|
+
# When not explicitly inheriting from static member
|
204
|
+
# and the member itself is not static,
|
205
|
+
# inherit from instance member.
|
206
|
+
static = inherit[:static] || m[:static] || false
|
207
|
+
|
208
|
+
if autodetected?(m)
|
209
|
+
# Auto-detected properties can override either a property or a
|
210
|
+
# config. So look for both types.
|
211
|
+
if tagname == :property
|
212
|
+
cfg = cls.find_members(:name => name, :tagname => :cfg, :static => static)[0]
|
213
|
+
prop = cls.find_members(:name => name, :tagname => :property, :static => static)[0]
|
214
|
+
|
215
|
+
if cfg && prop
|
216
|
+
prop
|
217
|
+
elsif cfg
|
218
|
+
cfg
|
219
|
+
elsif prop
|
220
|
+
prop
|
221
|
+
else
|
222
|
+
nil
|
223
|
+
end
|
224
|
+
|
225
|
+
else
|
226
|
+
cls.find_members(:name => name, :tagname => tagname, :static => static)[0]
|
227
|
+
end
|
228
|
+
else
|
229
|
+
m = cls.find_members(:name => name, :tagname => tagname, :static => static)[0]
|
230
|
+
# When member was not found with explicit staticality and
|
231
|
+
# the @inheritdoc tag contained no explicit "static", then
|
232
|
+
# look for both static and instance members.
|
233
|
+
if !m && !inherit[:static]
|
234
|
+
m = cls.find_members(:name => name, :tagname => tagname, :static => nil)[0]
|
235
|
+
end
|
236
|
+
m
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# True when the entire member was auto-detected
|
241
|
+
def autodetected?(m)
|
242
|
+
m[:autodetected] && m[:autodetected][:tagname]
|
243
|
+
end
|
244
|
+
|
245
|
+
def warn(msg, m)
|
246
|
+
inh_member = m[:inheritdoc][:member]
|
247
|
+
inh_target = (m[:inheritdoc][:cls] || "") + (inh_member ? "#" + inh_member : "")
|
248
|
+
|
249
|
+
Logger.warn(:inheritdoc, "@inheritdoc #{inh_target} - #{msg}", m[:files][0])
|
250
|
+
|
251
|
+
return nil
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|