codemodels-js 0.1.0-java
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +5 -0
- data/LICENSE +191 -0
- data/README.md +4 -0
- data/Rakefile +10 -0
- data/codemodels-js.gemspec +28 -0
- data/lib/codemodels/js/language.rb +19 -0
- data/lib/codemodels/js/metamodel.rb +586 -0
- data/lib/codemodels/js/model_building.rb +33 -0
- data/lib/codemodels/js/parser.rb +227 -0
- data/lib/codemodels/js/version.rb +6 -0
- data/lib/codemodels/js.rb +6 -0
- data/lib/jars/js.jar +0 -0
- data/test/data/app.js +66 -0
- data/test/data/app_clean.js +66 -0
- data/test/test_basic_node_properties.rb +52 -0
- data/test/test_basic_parsing.rb +150 -0
- data/test/test_example_app.rb +23 -0
- data/test/test_expression_parser.rb +28 -0
- data/test/test_helper.rb +65 -0
- data/test/test_info_extraction.rb +169 -0
- data/test/test_metamodel.rb +210 -0
- metadata +145 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'codemodels'
|
3
|
+
|
4
|
+
module CodeModels
|
5
|
+
|
6
|
+
module Js
|
7
|
+
|
8
|
+
EXTENSION = 'js'
|
9
|
+
|
10
|
+
def self.handle_models_in_dir(src,error_handler=nil,model_handler)
|
11
|
+
CodeModels::ModelBuilding.handle_models_in_dir(src,EXTENSION,error_handler,model_handler) do |src|
|
12
|
+
root = parse_file(src)
|
13
|
+
CodeModels::Serialization.rgenobject_to_model(root)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.generate_models_in_dir(src,dest,model_ext="#{EXTENSION}.lm",max_nesting=500,error_handler=nil)
|
18
|
+
CodeModels::ModelBuilding.generate_models_in_dir(src,dest,EXTENSION,model_ext,max_nesting,error_handler) do |src|
|
19
|
+
root = parse_file(src)
|
20
|
+
CodeModels::Serialization.rgenobject_to_model(root)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.generate_model_per_file(src,dest,model_ext="#{EXTENSION}.lm",max_nesting=500,error_handler=nil)
|
25
|
+
CodeModels::ModelBuilding.generate_model_per_file(src,dest,max_nesting,error_handler) do |src|
|
26
|
+
root = parse_file(src)
|
27
|
+
CodeModels::Serialization.rgenobject_to_model(root)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'codemodels'
|
3
|
+
require 'codemodels/js/metamodel'
|
4
|
+
|
5
|
+
module CodeModels
|
6
|
+
module Js
|
7
|
+
|
8
|
+
class Parser < CodeModels::Parser
|
9
|
+
|
10
|
+
attr_accessor :skip_unknown_node
|
11
|
+
|
12
|
+
def internal_parse_artifact(artifact)
|
13
|
+
code = artifact.code
|
14
|
+
name = artifact.name
|
15
|
+
java_import 'java.io.StringReader'
|
16
|
+
java_import 'org.mozilla.javascript.CompilerEnvirons'
|
17
|
+
rhino_parser = (java_import 'org.mozilla.javascript.Parser')[0]
|
18
|
+
env = CompilerEnvirons.new
|
19
|
+
parser = rhino_parser.new(env)
|
20
|
+
reader = StringReader.new(code)
|
21
|
+
tree = parser.parse(reader, name, 1)
|
22
|
+
tree_to_model(tree,code,artifact)
|
23
|
+
end
|
24
|
+
|
25
|
+
def tree_to_model(tree,code,artifact,offset=0)
|
26
|
+
node_to_model(tree,code,artifact,offset)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def adapter_specific_class(model_class,ref)
|
32
|
+
return nil unless CodeModels::Js::ParsingAdapters[model_class]
|
33
|
+
CodeModels::Js::ParsingAdapters[model_class][ref.name]
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO remove code below, moved to CodeModels
|
37
|
+
|
38
|
+
def adapter(model_class,ref)
|
39
|
+
if CodeModels::Js::ParsingAdapters[model_class] && CodeModels::Js::ParsingAdapters[model_class][ref.name]
|
40
|
+
CodeModels::Js::ParsingAdapters[model_class][ref.name]
|
41
|
+
else
|
42
|
+
if model_class.superclass!=Object
|
43
|
+
adapter(model_class.superclass,ref)
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def reference_to_method(model_class,ref)
|
51
|
+
s = ref.name
|
52
|
+
adapted = adapter(model_class,ref)
|
53
|
+
s = adapted if adapted
|
54
|
+
s.to_sym
|
55
|
+
end
|
56
|
+
|
57
|
+
def attribute_to_method(model_class,att)
|
58
|
+
s = att.name
|
59
|
+
adapted = adapter(model_class,att)
|
60
|
+
s = adapted if adapted
|
61
|
+
s.to_sym
|
62
|
+
end
|
63
|
+
|
64
|
+
def assign_ref_to_model(model,ref,value,code,artifact,offset)
|
65
|
+
return unless value!=nil # we do not need to assign a nil...
|
66
|
+
if ref.many
|
67
|
+
adder_method = :"add#{ref.name.capitalize}"
|
68
|
+
value.each {|el| model.send(adder_method,node_to_model(el,code,artifact,offset))}
|
69
|
+
else
|
70
|
+
setter_method = :"#{ref.name}="
|
71
|
+
raise "Trying to assign an array to a single property. Class #{model.class}, property #{ref.name}" if value.is_a?(::Array)
|
72
|
+
model.send(setter_method,node_to_model(value,code,artifact,offset))
|
73
|
+
end
|
74
|
+
rescue Object => e
|
75
|
+
puts "Problem while assigning ref #{ref.name} (many? #{ref.many}) to #{model.class}. Value: #{value.class}"
|
76
|
+
puts "\t<<#{e}>>"
|
77
|
+
raise e
|
78
|
+
end
|
79
|
+
|
80
|
+
def assign_att_to_model(model,att,value)
|
81
|
+
if att.many
|
82
|
+
adder_method = :"add#{att.name.capitalize}"
|
83
|
+
value.each {|el| model.send(adder_method,el)}
|
84
|
+
else
|
85
|
+
setter_method = :"#{att.name}="
|
86
|
+
raise "Trying to assign an array to a single property. Class #{model.class}, property #{att.name}" if value.is_a?(::Array)
|
87
|
+
model.send(setter_method,value)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def populate_attr(node,att,model)
|
92
|
+
raise "Error: the attribute has no name" unless att.name
|
93
|
+
value = Js.get_feature_value(node,att.name,model)
|
94
|
+
model.send(:"#{att.name}=",value) if value!=nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def populate_ref(node,ref,model,code,artifact,offset)
|
98
|
+
value = Js.get_feature_value(node,ref.name,model)
|
99
|
+
if value
|
100
|
+
if value==node
|
101
|
+
puts "avoiding loop... #{ref.name}, class #{node.class}"
|
102
|
+
return
|
103
|
+
end
|
104
|
+
if value.is_a?(Java::JavaUtil::Collection)
|
105
|
+
capitalized_name = ref.name.proper_capitalize
|
106
|
+
value.each do |el|
|
107
|
+
model.send(:"add#{capitalized_name}",node_to_model(el,code,artifact,offset))
|
108
|
+
end
|
109
|
+
else
|
110
|
+
model.send(:"#{ref.name}=",node_to_model(value,code,artifact,offset))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def assign_attr_value(model,prop_name,value)
|
116
|
+
if value.is_a?(Java::JavaUtil::Collection)
|
117
|
+
capitalized_name = prop_name.proper_capitalize
|
118
|
+
value.each do |el|
|
119
|
+
model.send(:"add#{capitalized_name}",el)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
model.send(:"#{ref.name}=",value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def assign_ref_value(model,prop_name,value,code,artifact,offset)
|
127
|
+
if value.is_a?(Java::JavaUtil::Collection)
|
128
|
+
capitalized_name = prop_name.proper_capitalize
|
129
|
+
value.each do |el|
|
130
|
+
#begin
|
131
|
+
model.send(:"add#{capitalized_name}",node_to_model(el,code,artifact,offset))
|
132
|
+
#rescue Object=>e
|
133
|
+
# raise "Assigning prop #{prop_name} to #{model}: #{e}"
|
134
|
+
#end
|
135
|
+
end
|
136
|
+
else
|
137
|
+
model.send(:"#{ref.name}=",node_to_model(value,code,artifact,offset))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def newlines(code,start_pos,end_pos)
|
142
|
+
piece = code[start_pos..end_pos]
|
143
|
+
piece.lines.count
|
144
|
+
end
|
145
|
+
|
146
|
+
def column_last_char(code,start_pos,end_pos)
|
147
|
+
piece = code[start_pos..end_pos]
|
148
|
+
last_line = nil
|
149
|
+
piece.lines.each{|l| last_line=l}
|
150
|
+
last_line.length
|
151
|
+
end
|
152
|
+
|
153
|
+
def node_to_model(node,code,artifact,offset)
|
154
|
+
metaclass = Js.get_corresponding_metaclass(node)
|
155
|
+
instance = metaclass.new
|
156
|
+
|
157
|
+
instance.language = LANGUAGE
|
158
|
+
instance.source = CodeModels::SourceInfo.new
|
159
|
+
|
160
|
+
bp = node.getAbsolutePosition
|
161
|
+
ep = node.getAbsolutePosition+node.length-1
|
162
|
+
|
163
|
+
instance.source.artifact = artifact
|
164
|
+
instance.source.position = SourcePosition.from_code_indexes(code,bp,ep)
|
165
|
+
instance.source.position.begin_point.column+=offset if instance.source.position.begin_point.line==1
|
166
|
+
instance.source.position.end_point.column+=offset if instance.source.position.end_point.line==1
|
167
|
+
|
168
|
+
metaclass.ecore.eAllAttributes.each do |attr|
|
169
|
+
unless Js.additional_property?(node.class,attr.name)
|
170
|
+
populate_attr(node,attr,instance)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
metaclass.ecore.eAllReferences.each do |ref|
|
174
|
+
unless Js.additional_property?(node.class,ref.name)
|
175
|
+
populate_ref(node,ref,instance,code,artifact,offset)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
# check for added properties
|
179
|
+
Js.additional_properties(node.class).each do |prop_name,prop_data|
|
180
|
+
value = prop_data[:getter].call(node)
|
181
|
+
if Js.get_att_type(prop_data[:prop_type])
|
182
|
+
assign_attr_value(instance,prop_name.to_s,value)
|
183
|
+
else
|
184
|
+
assign_ref_value(instance,prop_name.to_s,value,code,artifact,offset)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
instance
|
188
|
+
end
|
189
|
+
|
190
|
+
end # class Parser
|
191
|
+
|
192
|
+
DefaultParser = Parser.new
|
193
|
+
|
194
|
+
ExpressionParser = Parser.new
|
195
|
+
|
196
|
+
class << ExpressionParser
|
197
|
+
|
198
|
+
def parse_code(code,filename='<code>')
|
199
|
+
parse_artifact(FileArtifact.new(filename,code))
|
200
|
+
end
|
201
|
+
|
202
|
+
def parse_artifact(artifact)
|
203
|
+
code = "a=#{artifact.code};".encode(internal_encoding)
|
204
|
+
java_import 'java.io.StringReader'
|
205
|
+
java_import 'org.mozilla.javascript.CompilerEnvirons'
|
206
|
+
rhino_parser = (java_import 'org.mozilla.javascript.Parser')[0]
|
207
|
+
env = CompilerEnvirons.new
|
208
|
+
parser = rhino_parser.new(env)
|
209
|
+
reader = StringReader.new(code)
|
210
|
+
filename = '<code>'
|
211
|
+
filename = artifact.filename if artifact.respond_to?(:filename)
|
212
|
+
tree = parser.parse(reader, filename, 1)
|
213
|
+
tree_to_model(tree.statements[0].expression.right,code,artifact,-2)
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
def self.parse_code(code)
|
219
|
+
DefaultParser.parse_code(code)
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.parse_file(path,encoding=nil)
|
223
|
+
DefaultParser.parse_file(path,encoding)
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
end
|
data/lib/jars/js.jar
ADDED
Binary file
|
data/test/data/app.js
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
(function(angular) {
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
var app = angular.module('puzzleApp', ['slidingPuzzle', 'wordSearchPuzzle']);
|
5
|
+
|
6
|
+
// puzzle types
|
7
|
+
var types = [
|
8
|
+
{ id: 'sliding-puzzle', title: 'Sliding puzzle' },
|
9
|
+
{ id: 'word-search-puzzle', title: 'Word search puzzle' }
|
10
|
+
];
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Config
|
14
|
+
*/
|
15
|
+
app.config(function($routeProvider) {
|
16
|
+
$routeProvider.when('/:type');
|
17
|
+
});
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Startup
|
21
|
+
*/
|
22
|
+
app.run(function($rootScope, $route, $filter) {
|
23
|
+
$rootScope.types = types;
|
24
|
+
$rootScope.type = types[0].id;
|
25
|
+
|
26
|
+
// set type on route change
|
27
|
+
$rootScope.$on('$routeChangeSuccess', function(event, route) {
|
28
|
+
$rootScope.type = ($filter('filter')(types, { id: route.params.type }).length ? route.params.type : types[0].id);
|
29
|
+
});
|
30
|
+
});
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Advanced sliding puzzle controller
|
34
|
+
*/
|
35
|
+
app.controller('slidingAdvancedCtrl', function($scope) {
|
36
|
+
$scope.puzzles = [
|
37
|
+
{ src: './img/misko.jpg', title: 'Miško Hevery', rows: 4, cols: 4 },
|
38
|
+
{ src: './img/igor.jpg', title: 'Igor Minár', rows: 3, cols: 3 },
|
39
|
+
{ src: './img/vojta.jpg', title: 'Vojta Jína', rows: 4, cols: 3 }
|
40
|
+
];
|
41
|
+
});
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Word search puzzle controller
|
45
|
+
*/
|
46
|
+
app.controller('wordSearchCtrl', function($scope) {
|
47
|
+
$scope.matrix = [
|
48
|
+
['N', 'I', 'G', 'O', 'R', 'Y', 'G', 'S', 'T', 'T', 'A', 'N'],
|
49
|
+
['O', 'G', 'G', 'U', 'L', 'C', 'O', 'E', 'P', 'E', 'A', 'S'],
|
50
|
+
['I', 'N', 'N', 'R', 'M', 'N', 'O', 'R', 'I', 'M', 'E', 'C'],
|
51
|
+
['T', 'I', 'A', 'I', 'O', 'E', 'G', 'V', 'R', 'P', 'V', 'E'],
|
52
|
+
['C', 'T', 'T', 'E', 'D', 'D', 'L', 'I', 'C', 'L', 'I', 'N'],
|
53
|
+
['E', 'S', 'J', 'P', 'U', 'N', 'E', 'C', 'S', 'A', 'T', 'A'],
|
54
|
+
['J', 'E', 'O', 'O', 'L', 'E', 'I', 'E', 'A', 'T', 'C', 'R'],
|
55
|
+
['N', 'T', 'V', 'C', 'E', 'P', 'J', 'B', 'V', 'E', 'E', 'I'],
|
56
|
+
['I', 'S', 'I', 'S', 'S', 'E', 'S', 'A', 'A', 'W', 'R', 'O'],
|
57
|
+
['O', 'K', 'S', 'I', 'M', 'D', 'E', 'S', 'J', 'O', 'I', 'M'],
|
58
|
+
['R', 'E', 'L', 'L', 'O', 'R', 'T', 'N', 'O', 'C', 'D', 'E']
|
59
|
+
];
|
60
|
+
$scope.words = [
|
61
|
+
'BINDING', 'CONTROLLER', 'DEPENDENCY', 'DIRECTIVE', 'GOOGLE', 'IGOR', 'INJECTION', 'JAVASCRIPT',
|
62
|
+
'MISKO', 'MODULES', 'SCENARIO', 'SCOPE', 'SERVICE', 'TEMPLATE', 'TESTING', 'VOJTA'
|
63
|
+
];
|
64
|
+
});
|
65
|
+
|
66
|
+
})(window.angular);
|
@@ -0,0 +1,66 @@
|
|
1
|
+
(function(angular) {
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
var app = angular.module('puzzleApp', ['slidingPuzzle', 'wordSearchPuzzle']);
|
5
|
+
|
6
|
+
// puzzle types
|
7
|
+
var types = [
|
8
|
+
{ id: 'sliding-puzzle', title: 'Sliding puzzle' },
|
9
|
+
{ id: 'word-search-puzzle', title: 'Word search puzzle' }
|
10
|
+
];
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Config
|
14
|
+
*/
|
15
|
+
app.config(function($routeProvider) {
|
16
|
+
$routeProvider.when('/:type');
|
17
|
+
});
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Startup
|
21
|
+
*/
|
22
|
+
app.run(function($rootScope, $route, $filter) {
|
23
|
+
$rootScope.types = types;
|
24
|
+
$rootScope.type = types[0].id;
|
25
|
+
|
26
|
+
// set type on route change
|
27
|
+
$rootScope.$on('$routeChangeSuccess', function(event, route) {
|
28
|
+
$rootScope.type = ($filter('filter')(types, { id: route.params.type }).length ? route.params.type : types[0].id);
|
29
|
+
});
|
30
|
+
});
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Advanced sliding puzzle controller
|
34
|
+
*/
|
35
|
+
app.controller('slidingAdvancedCtrl', function($scope) {
|
36
|
+
$scope.puzzles = [
|
37
|
+
{ src: './img/misko.jpg', title: 'Misko Hevery', rows: 4, cols: 4 },
|
38
|
+
{ src: './img/igor.jpg', title: 'Igor Minar', rows: 3, cols: 3 },
|
39
|
+
{ src: './img/vojta.jpg', title: 'Vojta Jina', rows: 4, cols: 3 }
|
40
|
+
];
|
41
|
+
});
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Word search puzzle controller
|
45
|
+
*/
|
46
|
+
app.controller('wordSearchCtrl', function($scope) {
|
47
|
+
$scope.matrix = [
|
48
|
+
['N', 'I', 'G', 'O', 'R', 'Y', 'G', 'S', 'T', 'T', 'A', 'N'],
|
49
|
+
['O', 'G', 'G', 'U', 'L', 'C', 'O', 'E', 'P', 'E', 'A', 'S'],
|
50
|
+
['I', 'N', 'N', 'R', 'M', 'N', 'O', 'R', 'I', 'M', 'E', 'C'],
|
51
|
+
['T', 'I', 'A', 'I', 'O', 'E', 'G', 'V', 'R', 'P', 'V', 'E'],
|
52
|
+
['C', 'T', 'T', 'E', 'D', 'D', 'L', 'I', 'C', 'L', 'I', 'N'],
|
53
|
+
['E', 'S', 'J', 'P', 'U', 'N', 'E', 'C', 'S', 'A', 'T', 'A'],
|
54
|
+
['J', 'E', 'O', 'O', 'L', 'E', 'I', 'E', 'A', 'T', 'C', 'R'],
|
55
|
+
['N', 'T', 'V', 'C', 'E', 'P', 'J', 'B', 'V', 'E', 'E', 'I'],
|
56
|
+
['I', 'S', 'I', 'S', 'S', 'E', 'S', 'A', 'A', 'W', 'R', 'O'],
|
57
|
+
['O', 'K', 'S', 'I', 'M', 'D', 'E', 'S', 'J', 'O', 'I', 'M'],
|
58
|
+
['R', 'E', 'L', 'L', 'O', 'R', 'T', 'N', 'O', 'C', 'D', 'E']
|
59
|
+
];
|
60
|
+
$scope.words = [
|
61
|
+
'BINDING', 'CONTROLLER', 'DEPENDENCY', 'DIRECTIVE', 'GOOGLE', 'IGOR', 'INJECTION', 'JAVASCRIPT',
|
62
|
+
'MISKO', 'MODULES', 'SCENARIO', 'SCOPE', 'SERVICE', 'TEMPLATE', 'TESTING', 'VOJTA'
|
63
|
+
];
|
64
|
+
});
|
65
|
+
|
66
|
+
})(window.angular);
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestBasicNodeProperties < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include TestHelper
|
6
|
+
include CodeModels
|
7
|
+
include CodeModels::Js
|
8
|
+
|
9
|
+
def test_node_has_expected_basic_properties
|
10
|
+
r = parse_code("i < 10;")
|
11
|
+
assert r.respond_to?(:source)
|
12
|
+
assert r.respond_to?(:language)
|
13
|
+
assert_equal CodeModels::Js::LANGUAGE,r.language
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_node_has_expected_basic_position
|
17
|
+
r = parse_code("i < 10;")
|
18
|
+
assert_not_nil r.source
|
19
|
+
assert_not_nil r.source.position,"Source of #{r.class} has not the position"
|
20
|
+
assert_not_nil r.source.position.begin_point
|
21
|
+
assert_not_nil r.source.position.end_point
|
22
|
+
assert_equal 1,r.source.position.begin_point.line
|
23
|
+
assert_equal 1,r.source.position.begin_point.column
|
24
|
+
assert_equal 1,r.source.position.end_point.line
|
25
|
+
assert_equal 7,r.source.position.end_point.column
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_node_has_expected_multiline_position
|
29
|
+
r = parse_code("{\ni < 10;\n}")
|
30
|
+
assert_not_nil r.source
|
31
|
+
assert_not_nil r.source.position
|
32
|
+
assert_not_nil r.source.position.begin_point
|
33
|
+
assert_not_nil r.source.position.end_point
|
34
|
+
assert_equal 1,r.source.position.begin_point.line
|
35
|
+
assert_equal 1,r.source.position.begin_point.column
|
36
|
+
assert_equal 3,r.source.position.end_point.line
|
37
|
+
assert_equal 1,r.source.position.end_point.column
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_node_code
|
41
|
+
r = parse_code("{\ni < 10;\n}")
|
42
|
+
assert_equal "{\ni < 10;\n}",r.source.code
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_artifact_final_host_is_set_correctly_for_all
|
46
|
+
r = Js.parse_file('test/data/app.js')
|
47
|
+
r.traverse(:also_foreign) do |n|
|
48
|
+
assert_equal 'test/data/app.js',n.source.artifact.final_host.filename, "Node with wrong final_host: #{n}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|