jsduck 5.0.0.beta01 → 5.0.0.beta2
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/.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
|