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
data/lib/jsduck/accessors.rb
DELETED
@@ -1,136 +0,0 @@
|
|
1
|
-
require 'jsduck/logger'
|
2
|
-
|
3
|
-
module JsDuck
|
4
|
-
|
5
|
-
class Accessors
|
6
|
-
# Given a class, generates accessor methods to configs with
|
7
|
-
# @accessor tag. Modifies the class by adding these methods.
|
8
|
-
# When class already contains a getter or setter, the method is
|
9
|
-
# not added.
|
10
|
-
def create(cls)
|
11
|
-
# Grab all configs tagged as @accessor
|
12
|
-
accessors = cls[:members].find_all {|m| m[:tagname] == :cfg && m[:accessor] }
|
13
|
-
|
14
|
-
# Build lookup tables of method and event names
|
15
|
-
methods = build_lookup_table(cls[:members], :method)
|
16
|
-
events = build_lookup_table(cls[:members], :event)
|
17
|
-
|
18
|
-
accessors.each do |cfg|
|
19
|
-
# add getter if no method with same name exists
|
20
|
-
get = create_getter(cfg)
|
21
|
-
if !methods[get[:name]]
|
22
|
-
cls[:members] << get
|
23
|
-
end
|
24
|
-
# add setter if no method with same name exists
|
25
|
-
set = create_setter(cfg)
|
26
|
-
if !methods[set[:name]]
|
27
|
-
cls[:members] << set
|
28
|
-
end
|
29
|
-
# for evented accessors
|
30
|
-
if cfg[:evented]
|
31
|
-
# add event if no event with same name exists
|
32
|
-
ev = create_event(cfg)
|
33
|
-
if !events[ev[:name]]
|
34
|
-
cls[:members] << ev
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def build_lookup_table(members, tagname)
|
41
|
-
map = {}
|
42
|
-
members.each do |m|
|
43
|
-
map[m[:name]] = m if m[:tagname] == tagname
|
44
|
-
end
|
45
|
-
map
|
46
|
-
end
|
47
|
-
|
48
|
-
def create_getter(cfg)
|
49
|
-
name = "get" + upcase_first(cfg[:name])
|
50
|
-
return add_shared({
|
51
|
-
:tagname => :method,
|
52
|
-
:name => name,
|
53
|
-
:doc => "Returns the value of {@link #cfg-#{cfg[:name]}}.",
|
54
|
-
:params => [],
|
55
|
-
:return => {
|
56
|
-
:type => cfg[:type],
|
57
|
-
:doc => "",
|
58
|
-
},
|
59
|
-
:id => "method-" + name,
|
60
|
-
}, cfg)
|
61
|
-
end
|
62
|
-
|
63
|
-
def create_setter(cfg)
|
64
|
-
name = "set" + upcase_first(cfg[:name]);
|
65
|
-
return add_shared({
|
66
|
-
:tagname => :method,
|
67
|
-
:name => name,
|
68
|
-
:doc => "Sets the value of {@link #cfg-#{cfg[:name]}}.",
|
69
|
-
:params => [{
|
70
|
-
:type => cfg[:type],
|
71
|
-
:name => cfg[:name],
|
72
|
-
:doc => "",
|
73
|
-
}],
|
74
|
-
:return => {
|
75
|
-
:type => "undefined",
|
76
|
-
:doc => "",
|
77
|
-
},
|
78
|
-
:id => "method-" + name,
|
79
|
-
}, cfg)
|
80
|
-
end
|
81
|
-
|
82
|
-
def create_event(cfg)
|
83
|
-
name = cfg[:name].downcase + "change"
|
84
|
-
setter_name = "set" + upcase_first(cfg[:name]);
|
85
|
-
return add_shared({
|
86
|
-
:tagname => :event,
|
87
|
-
:name => name,
|
88
|
-
:doc => "Fires when the {@link ##{cfg[:id]}} configuration is changed by {@link #method-#{setter_name}}.",
|
89
|
-
:params => [
|
90
|
-
{
|
91
|
-
:name => "this",
|
92
|
-
:type => cfg[:owner],
|
93
|
-
:doc => "The #{cfg[:owner]} instance."
|
94
|
-
},
|
95
|
-
{
|
96
|
-
:name => "value",
|
97
|
-
:type => cfg[:type],
|
98
|
-
:doc => "The new value being set."
|
99
|
-
},
|
100
|
-
{
|
101
|
-
:name => "oldValue",
|
102
|
-
:type => cfg[:type],
|
103
|
-
:doc => "The existing value."
|
104
|
-
},
|
105
|
-
],
|
106
|
-
:id => "event-" + name,
|
107
|
-
}, cfg)
|
108
|
-
end
|
109
|
-
|
110
|
-
def add_shared(hash, cfg)
|
111
|
-
hash.merge!({
|
112
|
-
:owner => cfg[:owner],
|
113
|
-
:files => cfg[:files],
|
114
|
-
:private => cfg[:private],
|
115
|
-
:autodetected => cfg[:autodetected],
|
116
|
-
:meta => clone_meta(cfg),
|
117
|
-
})
|
118
|
-
end
|
119
|
-
|
120
|
-
def upcase_first(str)
|
121
|
-
str[0,1].upcase + str[1..-1]
|
122
|
-
end
|
123
|
-
|
124
|
-
# Create copy of all meta attributes of config, except the
|
125
|
-
# :required which only applies to configs and must not be
|
126
|
-
# propagated to methods or events.
|
127
|
-
def clone_meta(cfg)
|
128
|
-
h = {}
|
129
|
-
cfg[:meta].each_pair do |key, value|
|
130
|
-
h[key] = value unless key == :required
|
131
|
-
end
|
132
|
-
h
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
data/lib/jsduck/ast.rb
DELETED
@@ -1,524 +0,0 @@
|
|
1
|
-
require "jsduck/serializer"
|
2
|
-
require "jsduck/evaluator"
|
3
|
-
require "jsduck/function_ast"
|
4
|
-
require "jsduck/ext_patterns"
|
5
|
-
|
6
|
-
module JsDuck
|
7
|
-
|
8
|
-
# Analyzes the AST produced by EsprimaParser.
|
9
|
-
class Ast
|
10
|
-
# Should be initialized with EsprimaParser#parse result.
|
11
|
-
def initialize(docs = [], options = {})
|
12
|
-
@serializer = JsDuck::Serializer.new
|
13
|
-
@evaluator = JsDuck::Evaluator.new
|
14
|
-
@ext_patterns = JsDuck::ExtPatterns.new(options[:ext_namespaces] || ["Ext"])
|
15
|
-
@docs = docs
|
16
|
-
end
|
17
|
-
|
18
|
-
# Performs the detection of code in all docsets.
|
19
|
-
#
|
20
|
-
# @returns the processed array of docsets. (But it does it
|
21
|
-
# destructively by modifying the passed-in docsets.)
|
22
|
-
#
|
23
|
-
def detect_all!
|
24
|
-
# First deal only with doc-comments
|
25
|
-
doc_comments = @docs.find_all {|d| d[:type] == :doc_comment }
|
26
|
-
|
27
|
-
# Detect code in each docset. Sometimes a docset has already
|
28
|
-
# been detected as part of detecting some previous docset (like
|
29
|
-
# Class detecting all of its configs) - in such case, skip.
|
30
|
-
doc_comments.each do |docset|
|
31
|
-
code = docset[:code]
|
32
|
-
docset[:code] = detect(code) unless code && code[:tagname]
|
33
|
-
end
|
34
|
-
|
35
|
-
# Return all doc-comments + other comments for which related
|
36
|
-
# code was detected.
|
37
|
-
@docs.find_all {|d| d[:type] == :doc_comment || d[:code] && d[:code][:tagname] }
|
38
|
-
end
|
39
|
-
|
40
|
-
# Given Esprima-produced syntax tree, detects documentation data.
|
41
|
-
#
|
42
|
-
# This method is exposed for testing purposes only, JSDuck itself
|
43
|
-
# only calls the above #detect_all method.
|
44
|
-
#
|
45
|
-
# @param ast :code from Result of EsprimaParser
|
46
|
-
# @returns Hash consisting of the detected :tagname, :name, and
|
47
|
-
# other properties relative to the tag. Like so:
|
48
|
-
#
|
49
|
-
# { :tagname => :method, :name => "foo", ... }
|
50
|
-
#
|
51
|
-
def detect(ast)
|
52
|
-
ast = ast || {}
|
53
|
-
|
54
|
-
exp = expression?(ast) ? ast["expression"] : nil
|
55
|
-
var = var?(ast) ? ast["declarations"][0] : nil
|
56
|
-
|
57
|
-
# Ext.define("Class", {})
|
58
|
-
if exp && ext_define?(exp)
|
59
|
-
make_class(to_value(exp["arguments"][0]), exp)
|
60
|
-
|
61
|
-
# Ext.override(Class, {})
|
62
|
-
elsif exp && ext_override?(exp)
|
63
|
-
make_class("", exp)
|
64
|
-
|
65
|
-
# foo = Ext.extend(Parent, {})
|
66
|
-
elsif exp && assignment?(exp) && ext_extend?(exp["right"])
|
67
|
-
make_class(to_s(exp["left"]), exp["right"])
|
68
|
-
|
69
|
-
# Foo = ...
|
70
|
-
elsif exp && assignment?(exp) && class_name?(to_s(exp["left"]))
|
71
|
-
make_class(to_s(exp["left"]), exp["right"])
|
72
|
-
|
73
|
-
# var foo = Ext.extend(Parent, {})
|
74
|
-
elsif var && var["init"] && ext_extend?(var["init"])
|
75
|
-
make_class(to_s(var["id"]), var["init"])
|
76
|
-
|
77
|
-
# var Foo = ...
|
78
|
-
elsif var && class_name?(to_s(var["id"]))
|
79
|
-
make_class(to_s(var["id"]), var["right"])
|
80
|
-
|
81
|
-
# function Foo() {}
|
82
|
-
elsif function?(ast) && ast["id"] && class_name?(to_s(ast["id"]))
|
83
|
-
make_class(to_s(ast["id"]))
|
84
|
-
|
85
|
-
# { ... }
|
86
|
-
elsif object?(ast)
|
87
|
-
make_class("", ast)
|
88
|
-
|
89
|
-
# function foo() {}
|
90
|
-
elsif function?(ast)
|
91
|
-
make_method(ast["id"] ? to_s(ast["id"]) : "", ast)
|
92
|
-
|
93
|
-
# foo = function() {}
|
94
|
-
elsif exp && assignment?(exp) && function?(exp["right"])
|
95
|
-
make_method(to_s(exp["left"]), exp["right"])
|
96
|
-
|
97
|
-
# var foo = function() {}
|
98
|
-
elsif var && var["init"] && function?(var["init"])
|
99
|
-
make_method(to_s(var["id"]), var["init"])
|
100
|
-
|
101
|
-
# (function() {})
|
102
|
-
elsif exp && function?(exp)
|
103
|
-
make_method(exp["id"] ? to_s(exp["id"]) : "", exp)
|
104
|
-
|
105
|
-
# foo: function() {}
|
106
|
-
elsif property?(ast) && function?(ast["value"])
|
107
|
-
make_method(key_value(ast["key"]), ast["value"])
|
108
|
-
|
109
|
-
# this.fireEvent("foo", ...)
|
110
|
-
elsif exp && fire_event?(exp)
|
111
|
-
make_event(to_value(exp["arguments"][0]))
|
112
|
-
|
113
|
-
# foo = ...
|
114
|
-
elsif exp && assignment?(exp)
|
115
|
-
make_property(to_s(exp["left"]), exp["right"])
|
116
|
-
|
117
|
-
# var foo = ...
|
118
|
-
elsif var
|
119
|
-
make_property(to_s(var["id"]), var["init"])
|
120
|
-
|
121
|
-
# foo: ...
|
122
|
-
elsif property?(ast)
|
123
|
-
make_property(key_value(ast["key"]), ast["value"])
|
124
|
-
|
125
|
-
# foo;
|
126
|
-
elsif exp && ident?(exp)
|
127
|
-
make_property(to_s(exp))
|
128
|
-
|
129
|
-
# "foo" (inside some expression)
|
130
|
-
elsif string?(ast)
|
131
|
-
make_property(to_value(ast))
|
132
|
-
|
133
|
-
# "foo"; (as a statement of it's own)
|
134
|
-
elsif exp && string?(exp)
|
135
|
-
make_property(to_value(exp))
|
136
|
-
|
137
|
-
else
|
138
|
-
make_property()
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
private
|
143
|
-
|
144
|
-
def expression?(ast)
|
145
|
-
ast["type"] == "ExpressionStatement"
|
146
|
-
end
|
147
|
-
|
148
|
-
def call?(ast)
|
149
|
-
ast["type"] == "CallExpression"
|
150
|
-
end
|
151
|
-
|
152
|
-
def assignment?(ast)
|
153
|
-
ast["type"] == "AssignmentExpression"
|
154
|
-
end
|
155
|
-
|
156
|
-
def ext_define?(ast)
|
157
|
-
call?(ast) && ext_pattern?("Ext.define", ast["callee"])
|
158
|
-
end
|
159
|
-
|
160
|
-
def ext_extend?(ast)
|
161
|
-
call?(ast) && ext_pattern?("Ext.extend", ast["callee"])
|
162
|
-
end
|
163
|
-
|
164
|
-
def ext_override?(ast)
|
165
|
-
call?(ast) && ext_pattern?("Ext.override", ast["callee"])
|
166
|
-
end
|
167
|
-
|
168
|
-
def function?(ast)
|
169
|
-
ast["type"] == "FunctionDeclaration" || ast["type"] == "FunctionExpression" || empty_fn?(ast)
|
170
|
-
end
|
171
|
-
|
172
|
-
def empty_fn?(ast)
|
173
|
-
ast["type"] == "MemberExpression" && ext_pattern?("Ext.emptyFn", ast)
|
174
|
-
end
|
175
|
-
|
176
|
-
def ext_pattern?(pattern, ast)
|
177
|
-
@ext_patterns.matches?(pattern, to_s(ast))
|
178
|
-
end
|
179
|
-
|
180
|
-
def fire_event?(ast)
|
181
|
-
call?(ast) && to_s(ast["callee"]) == "this.fireEvent"
|
182
|
-
end
|
183
|
-
|
184
|
-
def var?(ast)
|
185
|
-
ast["type"] == "VariableDeclaration"
|
186
|
-
end
|
187
|
-
|
188
|
-
def property?(ast)
|
189
|
-
ast["type"] == "Property"
|
190
|
-
end
|
191
|
-
|
192
|
-
def ident?(ast)
|
193
|
-
ast["type"] == "Identifier"
|
194
|
-
end
|
195
|
-
|
196
|
-
def string?(ast)
|
197
|
-
ast["type"] == "Literal" && ast["value"].is_a?(String)
|
198
|
-
end
|
199
|
-
|
200
|
-
def object?(ast)
|
201
|
-
ast["type"] == "ObjectExpression"
|
202
|
-
end
|
203
|
-
|
204
|
-
# Class name begins with upcase char
|
205
|
-
def class_name?(name)
|
206
|
-
return name.split(/\./).last =~ /\A[A-Z]/
|
207
|
-
end
|
208
|
-
|
209
|
-
def make_class(name, ast=nil)
|
210
|
-
cls = {
|
211
|
-
:tagname => :class,
|
212
|
-
:name => name,
|
213
|
-
}
|
214
|
-
|
215
|
-
# apply information from Ext.extend, Ext.define, or {}
|
216
|
-
if ast
|
217
|
-
if ext_define?(ast)
|
218
|
-
detect_ext_define(cls, ast)
|
219
|
-
elsif ext_extend?(ast)
|
220
|
-
detect_ext_something(:extends, cls, ast)
|
221
|
-
elsif ext_override?(ast)
|
222
|
-
detect_ext_something(:override, cls, ast)
|
223
|
-
elsif object?(ast)
|
224
|
-
detect_class_members_from_object(cls, ast)
|
225
|
-
elsif ast["type"] == "ArrayExpression"
|
226
|
-
detect_class_members_from_array(cls, ast)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
return cls
|
231
|
-
end
|
232
|
-
|
233
|
-
# Detection of Ext.extend() or Ext.override().
|
234
|
-
# The type parameter must be correspondingly either :extend or :override.
|
235
|
-
def detect_ext_something(type, cls, ast)
|
236
|
-
args = ast["arguments"]
|
237
|
-
cls[type] = to_s(args[0])
|
238
|
-
if args.length == 2 && object?(args[1])
|
239
|
-
detect_class_members_from_object(cls, args[1])
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
# Inspects Ext.define() and copies detected properties over to the
|
244
|
-
# given cls Hash
|
245
|
-
def detect_ext_define(cls, ast)
|
246
|
-
# defaults
|
247
|
-
cls[:extends] = "Ext.Base"
|
248
|
-
cls[:requires] = []
|
249
|
-
cls[:uses] = []
|
250
|
-
cls[:alternateClassNames] = []
|
251
|
-
cls[:mixins] = []
|
252
|
-
cls[:aliases] = []
|
253
|
-
cls[:members] = []
|
254
|
-
cls[:code_type] = :ext_define
|
255
|
-
|
256
|
-
each_pair_in_object_expression(ast["arguments"][1]) do |key, value, pair|
|
257
|
-
case key
|
258
|
-
when "extend"
|
259
|
-
cls[:extends] = make_string(value)
|
260
|
-
when "override"
|
261
|
-
cls[:override] = make_string(value)
|
262
|
-
when "requires"
|
263
|
-
cls[:requires] = make_string_list(value)
|
264
|
-
when "uses"
|
265
|
-
cls[:uses] = make_string_list(value)
|
266
|
-
when "alternateClassName"
|
267
|
-
cls[:alternateClassNames] = make_string_list(value)
|
268
|
-
when "mixins"
|
269
|
-
cls[:mixins] = make_mixins(value)
|
270
|
-
when "singleton"
|
271
|
-
cls[:singleton] = make_singleton(value)
|
272
|
-
when "alias"
|
273
|
-
cls[:aliases] += make_string_list(value)
|
274
|
-
when "xtype"
|
275
|
-
cls[:aliases] += make_string_list(value).map {|xtype| "widget."+xtype }
|
276
|
-
when "config"
|
277
|
-
cls[:members] += make_configs(value, {:accessor => true})
|
278
|
-
when "cachedConfig"
|
279
|
-
cls[:members] += make_configs(value, {:accessor => true})
|
280
|
-
when "eventedConfig"
|
281
|
-
cls[:members] += make_configs(value, {:accessor => true, :evented => true})
|
282
|
-
when "statics"
|
283
|
-
cls[:members] += make_statics(value)
|
284
|
-
when "inheritableStatics"
|
285
|
-
cls[:members] += make_statics(value, {:inheritable => true})
|
286
|
-
else
|
287
|
-
detect_method_or_property(cls, key, value, pair)
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
# Detects class members from object literal
|
293
|
-
def detect_class_members_from_object(cls, ast)
|
294
|
-
cls[:members] = []
|
295
|
-
each_pair_in_object_expression(ast) do |key, value, pair|
|
296
|
-
detect_method_or_property(cls, key, value, pair)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
# Detects class members from array literal
|
301
|
-
def detect_class_members_from_array(cls, ast)
|
302
|
-
cls[:members] = []
|
303
|
-
|
304
|
-
# This will most likely be an @enum class, in which case the
|
305
|
-
# enum will be for documentation purposes only.
|
306
|
-
cls[:enum] = {:doc_only => true}
|
307
|
-
|
308
|
-
ast["elements"].each do |el|
|
309
|
-
detect_method_or_property(cls, key_value(el), el, el)
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
# Detects item in object literal either as method or property
|
314
|
-
def detect_method_or_property(cls, key, value, pair)
|
315
|
-
if function?(value)
|
316
|
-
m = make_method(key, value)
|
317
|
-
cls[:members] << m if apply_autodetected(m, pair)
|
318
|
-
else
|
319
|
-
p = make_property(key, value)
|
320
|
-
cls[:members] << p if apply_autodetected(p, pair)
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
def make_string(cfg_value)
|
325
|
-
return nil unless cfg_value
|
326
|
-
|
327
|
-
parent = to_value(cfg_value)
|
328
|
-
|
329
|
-
return parent.is_a?(String) ? parent : nil
|
330
|
-
end
|
331
|
-
|
332
|
-
def make_string_list(cfg_value)
|
333
|
-
return [] unless cfg_value
|
334
|
-
|
335
|
-
classes = Array(to_value(cfg_value))
|
336
|
-
|
337
|
-
return classes.all? {|c| c.is_a? String } ? classes : []
|
338
|
-
end
|
339
|
-
|
340
|
-
def make_mixins(cfg_value)
|
341
|
-
return [] unless cfg_value
|
342
|
-
|
343
|
-
v = to_value(cfg_value)
|
344
|
-
classes = v.is_a?(Hash) ? v.values : Array(v)
|
345
|
-
|
346
|
-
return classes.all? {|c| c.is_a? String } ? classes : []
|
347
|
-
end
|
348
|
-
|
349
|
-
def make_singleton(cfg_value)
|
350
|
-
cfg_value && to_value(cfg_value) == true
|
351
|
-
end
|
352
|
-
|
353
|
-
def make_configs(ast, defaults={})
|
354
|
-
configs = []
|
355
|
-
|
356
|
-
each_pair_in_object_expression(ast) do |name, value, pair|
|
357
|
-
cfg = make_property(name, value, :cfg)
|
358
|
-
cfg.merge!(defaults)
|
359
|
-
configs << cfg if apply_autodetected(cfg, pair)
|
360
|
-
end
|
361
|
-
|
362
|
-
configs
|
363
|
-
end
|
364
|
-
|
365
|
-
def make_statics(ast, defaults={})
|
366
|
-
statics = []
|
367
|
-
|
368
|
-
each_pair_in_object_expression(ast) do |name, value, pair|
|
369
|
-
if function?(value)
|
370
|
-
s = make_method(name, value)
|
371
|
-
else
|
372
|
-
s = make_property(name, value)
|
373
|
-
end
|
374
|
-
|
375
|
-
s[:meta] = {:static => true}
|
376
|
-
s.merge!(defaults)
|
377
|
-
|
378
|
-
statics << s if apply_autodetected(s, pair, defaults[:inheritable])
|
379
|
-
end
|
380
|
-
|
381
|
-
statics
|
382
|
-
end
|
383
|
-
|
384
|
-
# Sets auto-detection related properties :autodetected and
|
385
|
-
# :inheritdoc on the given member Hash.
|
386
|
-
#
|
387
|
-
# When member has a comment, adds code to the related docset and
|
388
|
-
# returns false.
|
389
|
-
#
|
390
|
-
# Otherwise detects the line number of member and returns true.
|
391
|
-
def apply_autodetected(m, ast, inheritable=true)
|
392
|
-
docset = find_docset(ast)
|
393
|
-
|
394
|
-
if !docset || docset[:type] != :doc_comment
|
395
|
-
if inheritable
|
396
|
-
m[:inheritdoc] = {}
|
397
|
-
else
|
398
|
-
m[:private] = true
|
399
|
-
end
|
400
|
-
m[:autodetected] = true
|
401
|
-
end
|
402
|
-
|
403
|
-
if docset
|
404
|
-
docset[:code] = m
|
405
|
-
return false
|
406
|
-
else
|
407
|
-
# Get line number from third place at range array.
|
408
|
-
# This third item exists in forked EsprimaJS at
|
409
|
-
# https://github.com/nene/esprima/tree/linenr-in-range
|
410
|
-
m[:linenr] = ast["range"][2]
|
411
|
-
return true
|
412
|
-
end
|
413
|
-
end
|
414
|
-
|
415
|
-
# Looks up docset associated with given AST node.
|
416
|
-
# A dead-stupid and -slow implementation, but works.
|
417
|
-
def find_docset(ast)
|
418
|
-
@docs.find do |docset|
|
419
|
-
docset[:code] == ast
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
def make_method(name, ast=nil)
|
424
|
-
return {
|
425
|
-
:tagname => :method,
|
426
|
-
:name => name,
|
427
|
-
:params => make_params(ast),
|
428
|
-
:chainable => chainable?(ast) && name != "constructor",
|
429
|
-
}
|
430
|
-
end
|
431
|
-
|
432
|
-
def make_params(ast)
|
433
|
-
if ast && !empty_fn?(ast)
|
434
|
-
ast["params"].map {|p| {:name => to_s(p)} }
|
435
|
-
else
|
436
|
-
[]
|
437
|
-
end
|
438
|
-
end
|
439
|
-
|
440
|
-
def chainable?(ast)
|
441
|
-
if function?(ast) && !empty_fn?(ast)
|
442
|
-
FunctionAst.return_types(ast) == [:this]
|
443
|
-
else
|
444
|
-
false
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
|
-
def make_event(name)
|
449
|
-
return {
|
450
|
-
:tagname => :event,
|
451
|
-
:name => name,
|
452
|
-
}
|
453
|
-
end
|
454
|
-
|
455
|
-
def make_property(name=nil, ast=nil, tagname=:property)
|
456
|
-
return {
|
457
|
-
:tagname => tagname,
|
458
|
-
:name => name,
|
459
|
-
:type => make_value_type(ast),
|
460
|
-
:default => make_default(ast),
|
461
|
-
}
|
462
|
-
end
|
463
|
-
|
464
|
-
def make_default(ast)
|
465
|
-
ast && to_value(ast) != nil ? to_s(ast) : nil
|
466
|
-
end
|
467
|
-
|
468
|
-
def make_value_type(ast)
|
469
|
-
if ast
|
470
|
-
v = to_value(ast)
|
471
|
-
if v.is_a?(String)
|
472
|
-
"String"
|
473
|
-
elsif v.is_a?(Numeric)
|
474
|
-
"Number"
|
475
|
-
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
476
|
-
"Boolean"
|
477
|
-
elsif v.is_a?(Array)
|
478
|
-
"Array"
|
479
|
-
elsif v.is_a?(Hash)
|
480
|
-
"Object"
|
481
|
-
elsif v == :regexp
|
482
|
-
"RegExp"
|
483
|
-
else
|
484
|
-
nil
|
485
|
-
end
|
486
|
-
else
|
487
|
-
nil
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
|
-
# -- various helper methods --
|
492
|
-
|
493
|
-
# Iterates over keys and values in ObjectExpression. The keys
|
494
|
-
# are turned into strings, but values are left as is for further
|
495
|
-
# processing.
|
496
|
-
def each_pair_in_object_expression(ast)
|
497
|
-
return unless ast && object?(ast)
|
498
|
-
|
499
|
-
ast["properties"].each do |p|
|
500
|
-
yield(key_value(p["key"]), p["value"], p)
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
# Converts object expression property key to string value
|
505
|
-
def key_value(key)
|
506
|
-
@evaluator.key_value(key)
|
507
|
-
end
|
508
|
-
|
509
|
-
# Fully serializes the node
|
510
|
-
def to_s(ast)
|
511
|
-
@serializer.to_s(ast)
|
512
|
-
end
|
513
|
-
|
514
|
-
# Converts AST node into a value.
|
515
|
-
def to_value(ast)
|
516
|
-
begin
|
517
|
-
@evaluator.to_value(ast)
|
518
|
-
rescue
|
519
|
-
nil
|
520
|
-
end
|
521
|
-
end
|
522
|
-
end
|
523
|
-
|
524
|
-
end
|