jsduck 4.0.1 → 4.1.1
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/Rakefile +14 -0
- data/esprima/esprima.js +210 -85
- data/jsduck.gemspec +3 -3
- data/lib/jsduck/accessors.rb +10 -8
- data/lib/jsduck/aggregator.rb +7 -7
- data/lib/jsduck/app.rb +24 -164
- data/lib/jsduck/app_data.rb +2 -4
- data/lib/jsduck/assets.rb +5 -2
- data/lib/jsduck/ast.rb +9 -4
- data/lib/jsduck/batch_formatter.rb +54 -0
- data/lib/jsduck/batch_parser.rb +106 -0
- data/lib/jsduck/categories.rb +5 -6
- data/lib/jsduck/class.rb +77 -239
- data/lib/jsduck/class_doc_expander.rb +0 -5
- data/lib/jsduck/class_formatter.rb +14 -10
- data/lib/jsduck/class_name.rb +23 -0
- data/lib/jsduck/class_writer.rb +9 -8
- data/lib/jsduck/doc_ast.rb +5 -6
- data/lib/jsduck/doc_formatter.rb +61 -272
- data/lib/jsduck/enum.rb +4 -4
- data/lib/jsduck/esprima.rb +10 -4
- data/lib/jsduck/examples.rb +5 -5
- data/lib/jsduck/export_writer.rb +62 -0
- data/lib/jsduck/exporter/app.rb +62 -0
- data/lib/jsduck/exporter/examples.rb +58 -0
- data/lib/jsduck/exporter/full.rb +60 -0
- data/lib/jsduck/file_categories.rb +7 -4
- data/lib/jsduck/function_ast.rb +99 -0
- data/lib/jsduck/grouped_asset.rb +27 -16
- data/lib/jsduck/guide_writer.rb +8 -7
- data/lib/jsduck/guides.rb +31 -29
- data/lib/jsduck/icons.rb +12 -1
- data/lib/jsduck/images.rb +3 -3
- data/lib/jsduck/importer.rb +7 -7
- data/lib/jsduck/index_html.rb +20 -6
- data/lib/jsduck/inherit_doc.rb +9 -12
- data/lib/jsduck/inline/example.rb +42 -0
- data/lib/jsduck/inline/img.rb +55 -0
- data/lib/jsduck/inline/link.rb +227 -0
- data/lib/jsduck/inline/video.rb +67 -0
- data/lib/jsduck/inline_examples.rb +7 -7
- data/lib/jsduck/js_parser.rb +5 -4
- data/lib/jsduck/lint.rb +14 -2
- data/lib/jsduck/logger.rb +5 -6
- data/lib/jsduck/members_index.rb +132 -0
- data/lib/jsduck/merger.rb +3 -9
- data/lib/jsduck/options.rb +39 -41
- data/lib/jsduck/override.rb +3 -7
- data/lib/jsduck/relations.rb +9 -9
- data/lib/jsduck/renderer.rb +3 -3
- data/lib/jsduck/return_values.rb +72 -0
- data/lib/jsduck/search_data.rb +16 -20
- data/lib/jsduck/shortener.rb +58 -0
- data/lib/jsduck/signature_renderer.rb +1 -2
- data/lib/jsduck/source/file.rb +98 -0
- data/lib/jsduck/source/file_parser.rb +72 -0
- data/lib/jsduck/source/writer.rb +89 -0
- data/lib/jsduck/tag/aside.rb +1 -1
- data/lib/jsduck/tag/since.rb +1 -1
- data/lib/jsduck/template_dir.rb +2 -2
- data/lib/jsduck/util/html.rb +27 -0
- data/lib/jsduck/util/io.rb +32 -0
- data/lib/jsduck/util/json.rb +60 -0
- data/lib/jsduck/util/null_object.rb +23 -0
- data/lib/jsduck/util/os.rb +14 -0
- data/lib/jsduck/util/parallel.rb +34 -0
- data/lib/jsduck/util/singleton.rb +35 -0
- data/lib/jsduck/util/stdout.rb +33 -0
- data/lib/jsduck/videos.rb +5 -5
- data/lib/jsduck/web_writer.rb +79 -0
- data/lib/jsduck/welcome.rb +6 -6
- data/spec/class_factory.rb +20 -0
- metadata +32 -20
- data/lib/jsduck/api_exporter.rb +0 -48
- data/lib/jsduck/app_exporter.rb +0 -60
- data/lib/jsduck/examples_exporter.rb +0 -56
- data/lib/jsduck/full_exporter.rb +0 -35
- data/lib/jsduck/html.rb +0 -25
- data/lib/jsduck/inline_img.rb +0 -53
- data/lib/jsduck/inline_video.rb +0 -58
- data/lib/jsduck/io.rb +0 -30
- data/lib/jsduck/json_duck.rb +0 -52
- data/lib/jsduck/lexer.rb +0 -251
- data/lib/jsduck/null_object.rb +0 -19
- data/lib/jsduck/os.rb +0 -11
- data/lib/jsduck/parallel_wrap.rb +0 -32
- data/lib/jsduck/source_file.rb +0 -97
- data/lib/jsduck/source_file_parser.rb +0 -70
- data/lib/jsduck/source_writer.rb +0 -87
- data/lib/jsduck/stats.rb +0 -103
- data/lib/jsduck/stdout.rb +0 -31
data/lib/jsduck/enum.rb
CHANGED
@@ -25,8 +25,8 @@ module JsDuck
|
|
25
25
|
|
26
26
|
# Given an enum class, returns the type infered from its values.
|
27
27
|
def infer_type(cls)
|
28
|
-
if cls[:members]
|
29
|
-
types = cls[:members]
|
28
|
+
if cls[:members].length > 0
|
29
|
+
types = cls[:members].map {|p| p[:type] }
|
30
30
|
types.sort.uniq.join("/")
|
31
31
|
else
|
32
32
|
"Object"
|
@@ -37,7 +37,7 @@ module JsDuck
|
|
37
37
|
def expand_default(cls)
|
38
38
|
if cls[:enum][:default] =~ /\A(.*)\.\*\Z/
|
39
39
|
each_alias($1) do |name, owner|
|
40
|
-
cls[:members]
|
40
|
+
cls[:members] << {
|
41
41
|
:tagname => :property,
|
42
42
|
:id => 'property-' + name,
|
43
43
|
:name => name,
|
@@ -64,7 +64,7 @@ module JsDuck
|
|
64
64
|
# Remove the auto-inserted inheritdoc tag so the auto-detected enum
|
65
65
|
# values default to being public.
|
66
66
|
def strip_inheritdoc(cls)
|
67
|
-
cls[:members]
|
67
|
+
cls[:members].each do |p|
|
68
68
|
p[:inheritdoc] = nil if p[:autodetected]
|
69
69
|
end
|
70
70
|
end
|
data/lib/jsduck/esprima.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'v8'
|
2
|
-
require 'json'
|
3
|
-
require 'singleton'
|
2
|
+
require 'jsduck/util/json'
|
3
|
+
require 'jsduck/util/singleton'
|
4
4
|
|
5
5
|
module JsDuck
|
6
6
|
|
@@ -9,12 +9,18 @@ module JsDuck
|
|
9
9
|
# Initialized as singleton to avoid loading the esprima.js more
|
10
10
|
# than once - otherwise performace will severely suffer.
|
11
11
|
class Esprima
|
12
|
-
include Singleton
|
12
|
+
include Util::Singleton
|
13
13
|
|
14
14
|
def initialize
|
15
15
|
@v8 = V8::Context.new
|
16
16
|
esprima = File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))+"/esprima/esprima.js";
|
17
|
+
|
18
|
+
# Esprima attempts to assign to window.esprima, but our v8
|
19
|
+
# engine has no global window variable defined. So define our
|
20
|
+
# own and then grab esprima out from it again.
|
21
|
+
@v8.eval("var window = {};")
|
17
22
|
@v8.load(esprima)
|
23
|
+
@v8.eval("var esprima = window.esprima;")
|
18
24
|
end
|
19
25
|
|
20
26
|
# Parses JavaScript source code using Esprima.js
|
@@ -23,7 +29,7 @@ module JsDuck
|
|
23
29
|
def parse(input)
|
24
30
|
@v8['js'] = input
|
25
31
|
json = @v8.eval("JSON.stringify(esprima.parse(js, {comment: true, range: true, raw: true}))")
|
26
|
-
return
|
32
|
+
return Util::Json.parse(json, :max_nesting => false)
|
27
33
|
end
|
28
34
|
|
29
35
|
end
|
data/lib/jsduck/examples.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'jsduck/
|
2
|
-
require 'jsduck/null_object'
|
1
|
+
require 'jsduck/util/json'
|
2
|
+
require 'jsduck/util/null_object'
|
3
3
|
require 'jsduck/grouped_asset'
|
4
4
|
|
5
5
|
module JsDuck
|
@@ -11,16 +11,16 @@ module JsDuck
|
|
11
11
|
if filename
|
12
12
|
Examples.new(filename, opts)
|
13
13
|
else
|
14
|
-
NullObject.new(:to_array => [], :[] => nil)
|
14
|
+
Util::NullObject.new(:to_array => [], :[] => nil)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
# Parses examples config file
|
19
19
|
def initialize(filename, opts)
|
20
|
-
@groups =
|
20
|
+
@groups = Util::Json.read(filename)
|
21
21
|
@opts = opts
|
22
22
|
fix_examples_data
|
23
|
-
build_map_by_name
|
23
|
+
build_map_by_name
|
24
24
|
end
|
25
25
|
|
26
26
|
# Prefix all relative URL-s in examples list with path given in --examples-base-url
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'jsduck/util/stdout'
|
2
|
+
require 'jsduck/exporter/full'
|
3
|
+
require 'jsduck/exporter/examples'
|
4
|
+
require 'jsduck/batch_formatter'
|
5
|
+
require 'jsduck/class_writer'
|
6
|
+
require 'jsduck/guide_writer'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
module JsDuck
|
10
|
+
|
11
|
+
# Performs the export in one of the export formats.
|
12
|
+
class ExportWriter
|
13
|
+
def initialize(relations, assets, opts)
|
14
|
+
@relations = relations
|
15
|
+
@assets = assets
|
16
|
+
@opts = opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def write
|
20
|
+
format_classes
|
21
|
+
|
22
|
+
clean_output_dir unless @opts.output_dir == :stdout
|
23
|
+
|
24
|
+
export_classes
|
25
|
+
export_examples_in_guides if @opts.export == :examples
|
26
|
+
|
27
|
+
Util::Stdout.flush if @opts.output_dir == :stdout
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def export_classes
|
33
|
+
cw = ClassWriter.new(get_exporter, @relations, @opts)
|
34
|
+
cw.write(@opts.output_dir, ".json")
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_exporter
|
38
|
+
exporters = {
|
39
|
+
:full => Exporter::Full,
|
40
|
+
:examples => Exporter::Examples,
|
41
|
+
}
|
42
|
+
exporters[@opts.export]
|
43
|
+
end
|
44
|
+
|
45
|
+
def export_examples_in_guides
|
46
|
+
gw = GuideWriter.new(Exporter::Examples, @assets.guides, @opts)
|
47
|
+
gw.write(@opts.output_dir, ".json")
|
48
|
+
end
|
49
|
+
|
50
|
+
# -- util routines --
|
51
|
+
|
52
|
+
def clean_output_dir
|
53
|
+
FileUtils.rm_rf(@opts.output_dir)
|
54
|
+
end
|
55
|
+
|
56
|
+
def format_classes
|
57
|
+
BatchFormatter.format_all!(@relations, @assets, @opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'jsduck/renderer'
|
2
|
+
require 'jsduck/doc_formatter'
|
3
|
+
require 'jsduck/exporter/full'
|
4
|
+
|
5
|
+
module JsDuck
|
6
|
+
module Exporter
|
7
|
+
|
8
|
+
# Exports data for Docs app.
|
9
|
+
class App < Full
|
10
|
+
def initialize(relations, opts)
|
11
|
+
super(relations, opts)
|
12
|
+
@renderer = Renderer.new(opts)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns compacted class data hash which contains an additional
|
16
|
+
# :html field with full HTML to show on class overview page.
|
17
|
+
def export(cls)
|
18
|
+
data = super(cls)
|
19
|
+
data[:html] = @renderer.render(data)
|
20
|
+
return compact(data)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# removes extra data from export
|
26
|
+
def compact(cls)
|
27
|
+
cls.delete(:doc)
|
28
|
+
cls[:members] = compact_members_group(cls[:members])
|
29
|
+
cls[:statics] = compact_members_group(cls[:statics])
|
30
|
+
cls[:files] = compact_files(cls[:files])
|
31
|
+
cls
|
32
|
+
end
|
33
|
+
|
34
|
+
def compact_members_group(group)
|
35
|
+
c_group = {}
|
36
|
+
group.each_pair do |type, members|
|
37
|
+
c_group[type] = members.map {|m| compact_member(m) }
|
38
|
+
end
|
39
|
+
c_group
|
40
|
+
end
|
41
|
+
|
42
|
+
def compact_member(m)
|
43
|
+
m_copy = {}
|
44
|
+
[:name, :tagname, :owner, :meta, :id].each do |key|
|
45
|
+
m_copy[key] = m[key]
|
46
|
+
end
|
47
|
+
m_copy
|
48
|
+
end
|
49
|
+
|
50
|
+
# Remove full path from filename for privacy considerations as the
|
51
|
+
# path can reveal information about the system where JSDuck was
|
52
|
+
# run. The docs app doesn't need to have this information.
|
53
|
+
def compact_files(files)
|
54
|
+
files.map do |f|
|
55
|
+
{:filename => File.basename(f[:filename]), :href => f[:href]}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'jsduck/inline_examples'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Exporter
|
5
|
+
|
6
|
+
# Exporter for inline examples.
|
7
|
+
#
|
8
|
+
# It produces the following structure:
|
9
|
+
#
|
10
|
+
# {
|
11
|
+
# :type => :class, # can also be :guide
|
12
|
+
# :name => "Panel",
|
13
|
+
# :examples => [
|
14
|
+
# {:code => "bla bla", :options => {}},
|
15
|
+
# {:code => "bla bla", :options => {"raw" => true}},
|
16
|
+
# ...
|
17
|
+
# ]
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
class Examples
|
21
|
+
def initialize(relations, opts)
|
22
|
+
# All params ignored, they're present to be compatible with
|
23
|
+
# other exporters.
|
24
|
+
@inline_examples = InlineExamples.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns hash of class name and inline examples
|
28
|
+
def export(cls)
|
29
|
+
examples = @inline_examples.extract(cls[:doc])
|
30
|
+
if examples.length > 0
|
31
|
+
{
|
32
|
+
:type => :class,
|
33
|
+
:name => cls[:name],
|
34
|
+
:examples => examples,
|
35
|
+
}
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns hash of guide name and inline examples
|
42
|
+
def export_guide(guide)
|
43
|
+
examples = @inline_examples.extract(guide[:html] || "")
|
44
|
+
if examples.length > 0
|
45
|
+
{
|
46
|
+
:type => :guide,
|
47
|
+
:name => guide["name"],
|
48
|
+
:examples => examples,
|
49
|
+
}
|
50
|
+
else
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'jsduck/class'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Exporter
|
5
|
+
|
6
|
+
# Exporter for all the class docs.
|
7
|
+
class Full
|
8
|
+
def initialize(relations, opts={})
|
9
|
+
@relations = relations
|
10
|
+
# opts parameter is here just for compatibility with other exporters
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns all data in Class object as hash.
|
14
|
+
def export(cls)
|
15
|
+
# Make copy of the internal data structure of a class
|
16
|
+
# so our modifications on it will be safe.
|
17
|
+
h = cls.internal_doc.clone
|
18
|
+
|
19
|
+
h[:members] = {}
|
20
|
+
h[:statics] = {}
|
21
|
+
Class.each_member_type do |tagname|
|
22
|
+
h[:members][tagname] = export_members(cls, {:tagname => tagname, :static => false})
|
23
|
+
h[:statics][tagname] = export_members(cls, {:tagname => tagname, :static => true})
|
24
|
+
end
|
25
|
+
h[:component] = cls.inherits_from?("Ext.Component")
|
26
|
+
h[:superclasses] = cls.superclasses.collect {|c| c[:name] }
|
27
|
+
h[:subclasses] = @relations.subclasses(cls).collect {|c| c[:name] }
|
28
|
+
h[:mixedInto] = @relations.mixed_into(cls).collect {|c| c[:name] }
|
29
|
+
|
30
|
+
h[:mixins] = cls.deps(:mixins).collect {|c| c[:name] }
|
31
|
+
h[:parentMixins] = cls.parent_deps(:mixins).collect {|c| c[:name] }
|
32
|
+
h[:requires] = cls.deps(:requires).collect {|c| c[:name] }
|
33
|
+
h[:uses] = cls.deps(:uses).collect {|c| c[:name] }
|
34
|
+
|
35
|
+
h
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Looks up members, and sorts them so that constructor method is first
|
41
|
+
def export_members(cls, cfg)
|
42
|
+
ms = cls.find_members(cfg)
|
43
|
+
ms.sort! {|a,b| a[:name] <=> b[:name] }
|
44
|
+
cfg[:tagname] == :method ? constructor_first(ms) : ms
|
45
|
+
end
|
46
|
+
|
47
|
+
# If methods list contains constructor, move it into the beginning.
|
48
|
+
def constructor_first(ms)
|
49
|
+
constr = ms.find {|m| m[:name] == "constructor" }
|
50
|
+
if constr
|
51
|
+
ms.delete(constr)
|
52
|
+
ms.unshift(constr)
|
53
|
+
end
|
54
|
+
ms
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
require 'jsduck/util/json'
|
3
|
+
|
1
4
|
module JsDuck
|
2
5
|
|
3
6
|
# Reads categories info from config file
|
@@ -9,11 +12,11 @@ module JsDuck
|
|
9
12
|
|
10
13
|
# Parses categories in JSON file
|
11
14
|
def generate
|
12
|
-
@categories =
|
15
|
+
@categories = Util::Json.read(@filename)
|
13
16
|
|
14
17
|
# Don't crash if old syntax is used.
|
15
18
|
if @categories.is_a?(Hash) && @categories["categories"]
|
16
|
-
Logger.
|
19
|
+
Logger.warn(nil, 'Update categories file to contain just the array inside {"categories": [...]}', @filename)
|
17
20
|
@categories = @categories["categories"]
|
18
21
|
end
|
19
22
|
|
@@ -36,7 +39,7 @@ module JsDuck
|
|
36
39
|
re = Regexp.new("^" + name.split(/\*/, -1).map {|part| Regexp.escape(part) }.join('.*') + "$")
|
37
40
|
classes = @relations.to_a.find_all {|cls| re =~ cls[:name] && !cls[:private] }.map {|cls| cls[:name] }.sort
|
38
41
|
if classes.length == 0
|
39
|
-
Logger.
|
42
|
+
Logger.warn(:cat_no_match, "No class found matching a pattern '#{name} in categories file'", @filename)
|
40
43
|
end
|
41
44
|
classes
|
42
45
|
end
|
@@ -56,7 +59,7 @@ module JsDuck
|
|
56
59
|
# Check that each existing non-private class is listed
|
57
60
|
@relations.each do |cls|
|
58
61
|
unless listed_classes[cls[:name]] || cls[:private]
|
59
|
-
Logger.
|
62
|
+
Logger.warn(:cat_class_missing, "Class '#{cls[:name]}' not found in categories file", @filename)
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require "jsduck/util/singleton"
|
2
|
+
require "jsduck/serializer"
|
3
|
+
require "jsduck/evaluator"
|
4
|
+
|
5
|
+
module JsDuck
|
6
|
+
|
7
|
+
# Analyzes the AST of a FunctionDeclaration or FunctionExpression.
|
8
|
+
class FunctionAst
|
9
|
+
include Util::Singleton
|
10
|
+
|
11
|
+
# True when function always finishes by returning this. False
|
12
|
+
# doesn't neccessarily mean that the function doesn't return this
|
13
|
+
# - rather it means our static analyzes wasn't able to determine
|
14
|
+
# what the function returns.
|
15
|
+
def chainable?(ast)
|
16
|
+
if ast && function?(ast)
|
17
|
+
body_returns(ast["body"]["body"])
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def function?(ast)
|
26
|
+
ast["type"] == "FunctionDeclaration" || ast["type"] == "FunctionExpression"
|
27
|
+
end
|
28
|
+
|
29
|
+
def body_returns(body)
|
30
|
+
body = skip_returnless_statements(body)
|
31
|
+
|
32
|
+
return body.length > 0 && return_this?(body[0])
|
33
|
+
end
|
34
|
+
|
35
|
+
def return_this?(ast)
|
36
|
+
return?(ast) && !!ast["argument"] && this?(ast["argument"])
|
37
|
+
end
|
38
|
+
|
39
|
+
def return?(ast)
|
40
|
+
ast["type"] == "ReturnStatement"
|
41
|
+
end
|
42
|
+
|
43
|
+
def this?(ast)
|
44
|
+
ast["type"] == "ThisExpression"
|
45
|
+
end
|
46
|
+
|
47
|
+
def skip_returnless_statements(statements)
|
48
|
+
i = statements.find_index {|s| contains_return?(s) }
|
49
|
+
if i
|
50
|
+
statements.slice(i, statements.length)
|
51
|
+
else
|
52
|
+
[]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def contains_return?(ast)
|
57
|
+
if return?(ast)
|
58
|
+
true
|
59
|
+
elsif control_flow?(ast)
|
60
|
+
extract_body(ast).any? {|s| contains_return?(s) }
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def control_flow?(ast)
|
67
|
+
CONTROL_FLOW[ast["type"]]
|
68
|
+
end
|
69
|
+
|
70
|
+
def extract_body(ast)
|
71
|
+
body = []
|
72
|
+
CONTROL_FLOW[ast["type"]].each do |name|
|
73
|
+
statements = ast[name]
|
74
|
+
if statements.is_a?(Hash)
|
75
|
+
body << statements
|
76
|
+
else
|
77
|
+
body += Array(statements)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
body
|
81
|
+
end
|
82
|
+
|
83
|
+
CONTROL_FLOW = {
|
84
|
+
"IfStatement" => ["consequent", "alternate"],
|
85
|
+
"SwitchStatement" => ["cases"],
|
86
|
+
"SwitchCase" => ["consequent"],
|
87
|
+
"ForStatement" => ["body"],
|
88
|
+
"ForInStatement" => ["body"],
|
89
|
+
"WhileStatement" => ["body"],
|
90
|
+
"DoWhileStatement" => ["body"],
|
91
|
+
"TryStatement" => ["block", "handlers", "finalizer"],
|
92
|
+
"CatchClause" => ["body"],
|
93
|
+
"WithStatement" => ["body"],
|
94
|
+
"LabeledStatement" => ["body"],
|
95
|
+
"BlockStatement" => ["body"],
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|