jsduck 4.0.1 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|