opal 0.9.4 → 0.10.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.gitignore +2 -3
  4. data/.gitmodules +5 -2
  5. data/.jshintrc +1 -8
  6. data/.rspec +1 -1
  7. data/.travis.yml +15 -23
  8. data/CHANGELOG.md +511 -326
  9. data/CODE_OF_CONDUCT.md +13 -15
  10. data/CONTRIBUTING.md +26 -216
  11. data/Gemfile +20 -12
  12. data/Guardfile +2 -2
  13. data/HACKING.md +230 -0
  14. data/README.md +6 -7
  15. data/bin/opal-mspec +1 -1
  16. data/config.ru +2 -2
  17. data/docs/faq.md +1 -1
  18. data/docs/source_maps.md +1 -1
  19. data/lib/opal.rb +1 -0
  20. data/lib/opal/builder.rb +1 -1
  21. data/lib/opal/cli.rb +30 -28
  22. data/lib/opal/cli_options.rb +3 -0
  23. data/lib/opal/cli_runners.rb +14 -1
  24. data/lib/opal/cli_runners/{apple_script.rb → applescript.rb} +3 -3
  25. data/lib/opal/cli_runners/nashorn.rb +2 -2
  26. data/lib/opal/cli_runners/nodejs.rb +2 -2
  27. data/lib/opal/cli_runners/phantom.js +24 -0
  28. data/lib/opal/cli_runners/phantomjs.rb +10 -10
  29. data/lib/opal/cli_runners/server.rb +3 -3
  30. data/lib/opal/compiler.rb +43 -4
  31. data/lib/opal/config.rb +3 -1
  32. data/lib/opal/errors.rb +13 -0
  33. data/lib/opal/fragment.rb +0 -13
  34. data/lib/opal/nodes.rb +10 -0
  35. data/lib/opal/nodes/args/initialize_kwargs.rb +28 -0
  36. data/lib/opal/nodes/args/kwarg.rb +29 -0
  37. data/lib/opal/nodes/args/kwoptarg.rb +29 -0
  38. data/lib/opal/nodes/args/kwrestarg.rb +39 -0
  39. data/lib/opal/nodes/args/mlhsarg.rb +79 -0
  40. data/lib/opal/nodes/args/normarg.rb +26 -0
  41. data/lib/opal/nodes/args/optarg.rb +27 -0
  42. data/lib/opal/nodes/args/post_args.rb +200 -0
  43. data/lib/opal/nodes/args/post_kwargs.rb +31 -0
  44. data/lib/opal/nodes/args/restarg.rb +33 -0
  45. data/lib/opal/nodes/base.rb +12 -0
  46. data/lib/opal/nodes/call.rb +92 -33
  47. data/lib/opal/nodes/def.rb +26 -169
  48. data/lib/opal/nodes/hash.rb +10 -4
  49. data/lib/opal/nodes/helpers.rb +6 -3
  50. data/lib/opal/nodes/inline_args.rb +61 -0
  51. data/lib/opal/nodes/iter.rb +73 -82
  52. data/lib/opal/nodes/logic.rb +12 -2
  53. data/lib/opal/nodes/masgn.rb +1 -2
  54. data/lib/opal/nodes/node_with_args.rb +141 -0
  55. data/lib/opal/nodes/rescue.rb +121 -43
  56. data/lib/opal/nodes/scope.rb +24 -5
  57. data/lib/opal/nodes/super.rb +122 -54
  58. data/lib/opal/nodes/top.rb +0 -12
  59. data/lib/opal/nodes/yield.rb +2 -13
  60. data/lib/opal/parser.rb +67 -39
  61. data/lib/opal/parser/grammar.rb +3319 -2961
  62. data/lib/opal/parser/grammar.y +234 -46
  63. data/lib/opal/parser/lexer.rb +105 -17
  64. data/lib/opal/parser/sexp.rb +4 -0
  65. data/lib/opal/paths.rb +4 -0
  66. data/lib/opal/regexp_anchors.rb +19 -1
  67. data/lib/opal/sprockets.rb +21 -18
  68. data/lib/opal/sprockets/environment.rb +0 -8
  69. data/lib/opal/sprockets/processor.rb +13 -16
  70. data/lib/opal/sprockets/server.rb +6 -12
  71. data/lib/opal/version.rb +1 -1
  72. data/opal.gemspec +1 -0
  73. data/opal/corelib/array.rb +209 -131
  74. data/opal/corelib/basic_object.rb +7 -3
  75. data/opal/corelib/class.rb +11 -17
  76. data/opal/corelib/constants.rb +2 -2
  77. data/opal/corelib/enumerable.rb +178 -355
  78. data/opal/corelib/enumerator.rb +3 -46
  79. data/opal/corelib/error.rb +2 -2
  80. data/opal/corelib/file.rb +13 -1
  81. data/opal/corelib/hash.rb +26 -56
  82. data/opal/corelib/helpers.rb +10 -0
  83. data/opal/corelib/kernel.rb +6 -3
  84. data/opal/corelib/module.rb +62 -31
  85. data/opal/corelib/number.rb +7 -16
  86. data/opal/corelib/proc.rb +24 -9
  87. data/opal/corelib/range.rb +4 -13
  88. data/opal/corelib/runtime.js +515 -378
  89. data/opal/corelib/string.rb +21 -49
  90. data/opal/corelib/struct.rb +50 -35
  91. data/opal/corelib/unsupported.rb +18 -30
  92. data/opal/opal.rb +0 -1
  93. data/opal/opal/mini.rb +1 -0
  94. data/spec/README.md +6 -4
  95. data/spec/filters/bugs/array.rb +0 -42
  96. data/spec/filters/bugs/basicobject.rb +0 -2
  97. data/spec/filters/bugs/bigdecimal.rb +160 -0
  98. data/spec/filters/bugs/class.rb +0 -5
  99. data/spec/filters/bugs/date.rb +1 -48
  100. data/spec/filters/bugs/enumerable.rb +4 -12
  101. data/spec/filters/bugs/enumerator.rb +0 -1
  102. data/spec/filters/bugs/exception.rb +4 -3
  103. data/spec/filters/bugs/float.rb +4 -2
  104. data/spec/filters/bugs/kernel.rb +25 -10
  105. data/spec/filters/bugs/language.rb +119 -68
  106. data/spec/filters/bugs/method.rb +135 -0
  107. data/spec/filters/bugs/module.rb +13 -28
  108. data/spec/filters/bugs/proc.rb +18 -8
  109. data/spec/filters/bugs/range.rb +0 -3
  110. data/spec/filters/bugs/rational.rb +4 -0
  111. data/spec/filters/bugs/regexp.rb +68 -36
  112. data/spec/filters/bugs/string.rb +1 -1
  113. data/spec/filters/bugs/struct.rb +0 -12
  114. data/spec/filters/bugs/time.rb +1 -0
  115. data/spec/filters/bugs/unboundmethod.rb +2 -1
  116. data/spec/filters/unsupported/freeze.rb +3 -1
  117. data/spec/filters/unsupported/language.rb +0 -7
  118. data/spec/filters/unsupported/privacy.rb +7 -6
  119. data/spec/filters/unsupported/string.rb +10 -0
  120. data/spec/filters/unsupported/struct.rb +3 -0
  121. data/spec/filters/unsupported/symbol.rb +9 -0
  122. data/spec/filters/unsupported/taint.rb +0 -3
  123. data/spec/filters/unsupported/thread.rb +1 -0
  124. data/spec/lib/cli_runners/phantomjs_spec.rb +39 -0
  125. data/spec/lib/cli_spec.rb +42 -1
  126. data/spec/lib/compiler/call_spec.rb +700 -0
  127. data/spec/lib/compiler_spec.rb +46 -28
  128. data/spec/lib/config_spec.rb +13 -0
  129. data/spec/lib/parser/call_spec.rb +18 -0
  130. data/spec/lib/parser/def_spec.rb +29 -0
  131. data/spec/lib/parser/iter_spec.rb +15 -15
  132. data/spec/lib/parser/lambda_spec.rb +153 -12
  133. data/spec/lib/parser/string_spec.rb +5 -0
  134. data/spec/lib/parser/undef_spec.rb +1 -1
  135. data/spec/lib/parser/variables_spec.rb +24 -0
  136. data/spec/lib/paths_spec.rb +12 -5
  137. data/spec/lib/spec_helper.rb +5 -0
  138. data/spec/lib/sprockets/processor_spec.rb +6 -5
  139. data/spec/lib/sprockets_spec.rb +8 -0
  140. data/spec/mspec-opal/formatters.rb +188 -0
  141. data/spec/mspec-opal/runner.rb +193 -0
  142. data/spec/opal/core/enumerator/with_index_spec.rb +6 -0
  143. data/spec/opal/core/kernel/define_singleton_method_spec.rb +1 -1
  144. data/spec/opal/core/kernel/instance_variables_spec.rb +14 -0
  145. data/spec/opal/core/kernel/loop_spec.rb +1 -1
  146. data/spec/opal/core/kernel/raise_spec.rb +1 -1
  147. data/spec/opal/core/language/heredoc_spec.rb +42 -0
  148. data/spec/opal/core/language/rescue_spec.rb +18 -0
  149. data/spec/opal/core/language_spec.rb +22 -0
  150. data/spec/opal/core/module/const_defined_spec.rb +1 -2
  151. data/spec/opal/core/module/name_spec.rb +6 -0
  152. data/spec/opal/core/runtime/bridged_classes_spec.rb +14 -2
  153. data/spec/opal/core/runtime/rescue_spec.rb +12 -2
  154. data/spec/opal/core/runtime/super_spec.rb +1 -0
  155. data/spec/opal/core/string_spec.rb +21 -0
  156. data/spec/opal/stdlib/js_spec.rb +1 -1
  157. data/spec/opal/stdlib/native/hash_spec.rb +7 -0
  158. data/spec/opal/stdlib/promise/always_spec.rb +24 -5
  159. data/spec/opal/stdlib/promise/rescue_spec.rb +15 -6
  160. data/spec/opal/stdlib/promise/then_spec.rb +13 -5
  161. data/spec/opal/stdlib/promise/trace_spec.rb +5 -6
  162. data/spec/opal/stdlib/strscan/scan_spec.rb +1 -1
  163. data/spec/ruby_specs +122 -0
  164. data/spec/spec_helper.rb +3 -15
  165. data/stdlib/base64.rb +51 -121
  166. data/stdlib/bigdecimal.rb +231 -0
  167. data/stdlib/bigdecimal/bignumber.js.rb +11 -0
  168. data/stdlib/bigdecimal/kernel.rb +5 -0
  169. data/stdlib/date.rb +252 -10
  170. data/stdlib/native.rb +38 -38
  171. data/stdlib/nodejs/dir.rb +8 -6
  172. data/stdlib/nodejs/file.rb +28 -3
  173. data/stdlib/nodejs/node_modules/.bin/js-yaml +1 -0
  174. data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esparse +1 -0
  175. data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esvalidate +1 -0
  176. data/stdlib/nodejs/require.rb +1 -1
  177. data/stdlib/nodejs/yaml.rb +3 -2
  178. data/stdlib/opal-parser.rb +7 -2
  179. data/stdlib/pathname.rb +23 -1
  180. data/stdlib/phantomjs.rb +10 -0
  181. data/stdlib/promise.rb +38 -23
  182. data/tasks/building.rake +3 -3
  183. data/tasks/testing.rake +27 -14
  184. data/tasks/testing/mspec_special_calls.rb +1 -1
  185. data/tasks/testing/sprockets-phantomjs.js +4 -0
  186. data/test/opal/test_keyword.rb +110 -110
  187. data/test/opal/unsupported_and_bugs.rb +30 -0
  188. data/vendored-minitest/minitest/assertions.rb +1 -1
  189. metadata +65 -15
  190. data/.spectator +0 -2
  191. data/.spectator-mspec +0 -3
  192. data/opal/corelib/array/inheritance.rb +0 -127
  193. data/spec/rubyspecs +0 -139
@@ -38,20 +38,20 @@ describe Opal::Compiler do
38
38
  expect_compiled("self.inspect").to include("$inspect()")
39
39
  expect_compiled("self.map { |a| a + 10 }").to include("$map")
40
40
  end
41
-
41
+
42
42
  it "adds method missing stubs" do
43
43
  expect_compiled("self.puts 'hello'").to include("Opal.add_stubs(['$puts'])")
44
44
  end
45
-
45
+
46
46
  it 'adds method missing stubs with operators' do
47
47
  expect_compiled("class Foo; end; Foo.new > 5").to include("Opal.add_stubs(['$>', '$new'])")
48
48
  end
49
-
49
+
50
50
  it "should compile constant lookups" do
51
51
  expect_compiled("Object").to include("Object")
52
52
  expect_compiled("Array").to include("Array")
53
53
  end
54
-
54
+
55
55
  it "should compile undef calls" do
56
56
  expect_compiled("undef a").to include("Opal.udef(self, '$a')")
57
57
  expect_compiled("undef a,b").to match(/Opal.udef\(self, '\$a'\);.*return Opal.udef\(self, '\$b'\);/m)
@@ -63,6 +63,24 @@ describe Opal::Compiler do
63
63
  end
64
64
  end
65
65
 
66
+ describe "method names" do
67
+ it "generates a named function for method" do
68
+ expect_compiled("def test_method; end").to include("function ːtest_method()")
69
+ end
70
+
71
+ context "when function name is reserved" do
72
+ it "generates a valid named function for method" do
73
+ expect_compiled("def Array; end").to include("function ːArray()")
74
+ end
75
+ end
76
+
77
+ context "when function name is not valid" do
78
+ it "skips generating a name" do
79
+ expect_compiled("def test_method?; end").to include("function()")
80
+ end
81
+ end
82
+ end
83
+
66
84
  describe "debugger special method" do
67
85
  it "generates debugger keyword in javascript" do
68
86
  expect_compiled("debugger").to include("debugger")
@@ -133,7 +151,7 @@ describe Opal::Compiler do
133
151
  end
134
152
  end
135
153
  end
136
-
154
+
137
155
  describe 'truthy check' do
138
156
  context 'no parentheses' do
139
157
  context 'with operators' do
@@ -141,113 +159,113 @@ describe Opal::Compiler do
141
159
  expect_compiled('foo = 42 if 2 > 3').to include('if ($rb_gt(2, 3))')
142
160
  expect_compiled('foo = 42 if 2.5 > 3.5').to include('if ($rb_gt(2.5, 3.5))')
143
161
  expect_compiled('foo = 42 if true > false').to include('if ($rb_gt(true, false))')
144
-
162
+
145
163
  expect_compiled('foo = 42 if 2 == 3').to include("if ((2)['$=='](3))")
146
164
  expect_compiled('foo = 42 if 2.5 == 3.5').to include("if ((2.5)['$=='](3.5))")
147
165
  expect_compiled('foo = 42 if true == false').to include("if (true['$=='](false))")
148
166
  end
149
-
167
+
150
168
  it 'adds nil check for strings' do
151
169
  expect_compiled('foo = 42 if "test" > "bar"').to include('if ((($a = $rb_gt("test", "bar")) !== nil && (!$a.$$is_boolean || $a == true)))')
152
170
  end
153
-
171
+
154
172
  it 'specifically == excludes nil check for strings' do
155
173
  expect_compiled('foo = 42 if "test" == "bar"').to include("if (\"test\"['$=='](\"bar\"))")
156
174
  end
157
-
175
+
158
176
  it 'adds nil check for lvars' do
159
177
  expect_compiled("bar = 4\nfoo = 42 if bar > 5").to include('if ((($a = $rb_gt(bar, 5)) !== nil && (!$a.$$is_boolean || $a == true)))')
160
178
  end
161
-
179
+
162
180
  it 'specifically == excludes nil check for lvars' do
163
181
  expect_compiled("bar = 4\nfoo = 42 if bar == 5").to include("if (bar['$=='](5))")
164
182
  end
165
-
183
+
166
184
  it 'adds nil check for constants' do
167
185
  expect_compiled("foo = 42 if Test > 4").to include("if ((($a = $rb_gt($scope.get('Test'), 4)) !== nil && (!$a.$$is_boolean || $a == true))) ")
168
186
  end
169
-
187
+
170
188
  it 'specifically == excludes nil check for constants' do
171
189
  expect_compiled("foo = 42 if Test == 4").to include("if ($scope.get('Test')['$=='](4))")
172
190
  end
173
191
  end
174
-
192
+
175
193
  context 'without operators' do
176
194
  it 'adds nil check for primitives' do
177
195
  expect_compiled('foo = 42 if 2').to include('if ((($a = 2) !== nil && (!$a.$$is_boolean || $a == true)))')
178
196
  expect_compiled('foo = 42 if 2.5').to include('if ((($a = 2.5) !== nil && (!$a.$$is_boolean || $a == true)))')
179
197
  expect_compiled('foo = 42 if true').to include('if ((($a = true) !== nil && (!$a.$$is_boolean || $a == true)))')
180
198
  end
181
-
199
+
182
200
  it 'adds nil check for boolean method calls' do
183
201
  expect_compiled('foo = 42 if true.something').to include('if ((($a = true.$something()) !== nil && (!$a.$$is_boolean || $a == true)))')
184
202
  end
185
-
203
+
186
204
  it 'adds nil check for strings' do
187
205
  expect_compiled('foo = 42 if "test"').to include('if ((($a = "test") !== nil && (!$a.$$is_boolean || $a == true)))')
188
206
  end
189
-
207
+
190
208
  it 'adds nil check for lvars' do
191
209
  expect_compiled("bar = 4\nfoo = 42 if bar").to include('if (bar !== false && bar !== nil)')
192
210
  end
193
-
211
+
194
212
  it 'adds nil check for constants' do
195
213
  expect_compiled("foo = 42 if Test").to include("if ((($a = $scope.get('Test')) !== nil && (!$a.$$is_boolean || $a == true)))")
196
214
  end
197
215
  end
198
216
  end
199
-
217
+
200
218
  context 'parentheses' do
201
219
  context 'with operators' do
202
220
  it 'adds nil check for primitives' do
203
221
  expect_compiled('foo = 42 if (2 > 3)').to include('if ((($a = ($rb_gt(2, 3))) !== nil && (!$a.$$is_boolean || $a == true)))')
204
222
  expect_compiled('foo = 42 if (2.5 > 3.5)').to include('if ((($a = ($rb_gt(2.5, 3.5))) !== nil && (!$a.$$is_boolean || $a == true)))')
205
223
  expect_compiled('foo = 42 if (true > false)').to include('if ((($a = ($rb_gt(true, false))) !== nil && (!$a.$$is_boolean || $a == true)))')
206
-
224
+
207
225
  expect_compiled('foo = 42 if (2 == 3)').to include("if ((($a = ((2)['$=='](3))) !== nil && (!$a.$$is_boolean || $a == true)))")
208
226
  expect_compiled('foo = 42 if (2.5 == 3.5)').to include("if ((($a = ((2.5)['$=='](3.5))) !== nil && (!$a.$$is_boolean || $a == true)))")
209
227
  expect_compiled('foo = 42 if (true == false)').to include("if ((($a = (true['$=='](false))) !== nil && (!$a.$$is_boolean || $a == true)))")
210
228
  end
211
-
229
+
212
230
  it 'adds nil check for strings' do
213
231
  expect_compiled('foo = 42 if ("test" > "bar")').to include('if ((($a = ($rb_gt("test", "bar"))) !== nil && (!$a.$$is_boolean || $a == true)))')
214
232
  expect_compiled('foo = 42 if ("test" == "bar")').to include("if ((($a = (\"test\"['$=='](\"bar\"))) !== nil && (!$a.$$is_boolean || $a == true)))")
215
233
  end
216
-
234
+
217
235
  it 'adds nil check for lvars' do
218
236
  expect_compiled("bar = 4\nfoo = 42 if (bar > 5)").to include('if ((($a = ($rb_gt(bar, 5))) !== nil && (!$a.$$is_boolean || $a == true)))')
219
237
  expect_compiled("bar = 4\nfoo = 42 if (bar == 5)").to include("if ((($a = (bar['$=='](5))) !== nil && (!$a.$$is_boolean || $a == true))) ")
220
238
  end
221
-
239
+
222
240
  it 'adds nil check for constants' do
223
241
  expect_compiled("foo = 42 if (Test > 4)").to include("if ((($a = ($rb_gt($scope.get('Test'), 4))) !== nil && (!$a.$$is_boolean || $a == true)))")
224
242
  expect_compiled("foo = 42 if (Test == 4)").to include("if ((($a = ($scope.get('Test')['$=='](4))) !== nil && (!$a.$$is_boolean || $a == true)))")
225
243
  end
226
244
  end
227
-
245
+
228
246
  context 'without operators' do
229
247
  it 'adds nil check for primitives' do
230
248
  expect_compiled('foo = 42 if (2)').to include('if ((($a = (2)) !== nil && (!$a.$$is_boolean || $a == true)))')
231
249
  expect_compiled('foo = 42 if (2.5)').to include('if ((($a = (2.5)) !== nil && (!$a.$$is_boolean || $a == true)))')
232
250
  expect_compiled('foo = 42 if (true)').to include('if ((($a = (true)) !== nil && (!$a.$$is_boolean || $a == true)))')
233
251
  end
234
-
252
+
235
253
  it 'adds nil check for boolean method calls' do
236
254
  expect_compiled('foo = 42 if (true.something)').to include('if ((($a = (true.$something())) !== nil && (!$a.$$is_boolean || $a == true)))')
237
255
  end
238
-
256
+
239
257
  it 'adds nil check for strings' do
240
258
  expect_compiled('foo = 42 if ("test")').to include('if ((($a = ("test")) !== nil && (!$a.$$is_boolean || $a == true)))')
241
259
  end
242
-
260
+
243
261
  it 'adds nil check for lvars' do
244
262
  expect_compiled("bar = 4\nfoo = 42 if (bar)").to include('if ((($a = (bar)) !== nil && (!$a.$$is_boolean || $a == true)))')
245
263
  end
246
-
264
+
247
265
  it 'adds nil check for constants' do
248
266
  expect_compiled("foo = 42 if (Test)").to include("if ((($a = ($scope.get('Test'))) !== nil && (!$a.$$is_boolean || $a == true)))")
249
267
  end
250
- end
268
+ end
251
269
  end
252
270
  end
253
271
 
@@ -0,0 +1,13 @@
1
+ require 'lib/spec_helper'
2
+ require 'opal/config'
3
+
4
+ describe Opal::Config do
5
+ describe '.default_config' do
6
+ it 'is new each time' do
7
+ default_config1 = described_class.default_config
8
+ default_config2 = described_class.default_config
9
+ expect(default_config1).to eq(default_config2)
10
+ expect(default_config1).not_to equal(default_config2)
11
+ end
12
+ end
13
+ end
@@ -23,6 +23,10 @@ describe "Method calls" do
23
23
  parsed("foo\n.bar").should == [:call, [:call, nil, :foo, [:arglist]], :bar, [:arglist]]
24
24
  lambda { parsed("foo\n..bar") }.should raise_error(Exception)
25
25
  end
26
+
27
+ it "parses method starting on the next line after \\" do
28
+ parsed("\\\nfoo").should == [:call, nil, :foo, [:arglist]]
29
+ end
26
30
  end
27
31
 
28
32
  describe "Operator calls" do
@@ -181,3 +185,17 @@ describe 'Calls with trailing comma' do
181
185
  [:hash, [:sym, :a], [:int, 100]]]]
182
186
  end
183
187
  end
188
+
189
+ describe 'Calls with kwsplat' do
190
+ it 'parses empty kwsplat' do
191
+ parsed('foo(**{})').should == [:call, nil, :foo, [:arglist, [:hash, [:kwsplat, [:hash]]]]]
192
+ end
193
+
194
+ it 'parses non-empty kwsplat' do
195
+ parsed('foo(**{ a: 1 })').should == [:call, nil, :foo, [:arglist, [:hash, [:kwsplat, [:hash, [:sym, :a], [:int, 1]]]]]]
196
+ end
197
+
198
+ it 'supports kwargs and kwsplat' do
199
+ parsed('foo(a: 1, **{ b: 2 })').should == [:call, nil, :foo, [:arglist, [:hash, [:sym, :a], [:int, 1], [:kwsplat, [:hash, [:sym, :b], [:int, 2]]]]]]
200
+ end
201
+ end
@@ -33,6 +33,10 @@ describe "The def keyword" do
33
33
  parsed("def foo(a = 1); end")[3].should == [:args, [:optarg, :a, [:int, 1]]]
34
34
  parsed("def foo(a = 1, b = 2); end")[3].should == [:args, [:optarg, :a, [:int, 1]], [:optarg, :b, [:int, 2]]]
35
35
  end
36
+
37
+ it "parses norm arg after optarg" do
38
+ parsed("def foo(a = 1, b); end")[3].should == [:args, [:optarg, :a, [:int, 1]], [:arg, :b]]
39
+ end
36
40
  end
37
41
 
38
42
  describe "with rest args" do
@@ -77,4 +81,29 @@ describe "The def keyword" do
77
81
  parsed("def foo a: 1, b: 2; end")[3].should == [:args, [:kwoptarg, :a, [:int, 1]], [:kwoptarg, :b, [:int, 2]]]
78
82
  end
79
83
  end
84
+
85
+ it "parses (a,b=1,*c,d,&blk) arguments" do
86
+ expected = [:args, [:arg, :a], [:optarg, :b, [:int, 1]], [:restarg, :c], [:arg, :d], [:blockarg, :blk]]
87
+ parsed("def m(a,b=1,*c,d,&blk); end")[3].should == expected
88
+ end
89
+
90
+ it "parses (a,b=1,c,&blk) arguments" do
91
+ expected = [:args, [:arg, :a], [:optarg, :b, [:int, 1]], [:arg, :c], [:blockarg, :blk]]
92
+ parsed("def m(a,b=1,c,&blk); end")[3].should == expected
93
+ end
94
+
95
+ it "parses (a,*b,c,&blk) arguments" do
96
+ expected = [:args, [:arg, :a], [:restarg, :b], [:arg, :c], [:blockarg, :blk]]
97
+ parsed("def m(a,*b,c,&blk); end")[3].should == expected
98
+ end
99
+
100
+ it "parses (a=1,*b,c,&blk) arguments" do
101
+ expected = [:args, [:optarg, :a, [:int, 1]], [:restarg, :b], [:arg, :c], [:blockarg, :blk]]
102
+ parsed("def m(a=1,*b,c,&blk); end")[3].should == expected
103
+ end
104
+
105
+ it "parses (*b,c,&blk) arguments" do
106
+ expected = [:args, [:restarg, :b], [:arg, :c], [:blockarg, :blk]]
107
+ parsed("def m(*b,c,&blk); end")[3].should == expected
108
+ end
80
109
  end
@@ -21,39 +21,39 @@ describe "Iters" do
21
21
  end
22
22
 
23
23
  describe "with normal args" do
24
- it "adds a single s(:lasgn) for 1 norm arg" do
25
- parsed("proc do |a|; end")[4][1].should == [:lasgn, :a]
24
+ it "adds a single s(:masgn) for 1 norm arg" do
25
+ parsed("proc do |a|; end")[4][1].should == [:masgn, [:args, [:arg, :a]]]
26
26
  end
27
27
 
28
28
  it "lists multiple norm args inside a s(:masgn)" do
29
- parsed("proc do |a, b|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
30
- parsed("proc do |a, b, c|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:lasgn, :c]]]
29
+ parsed("proc do |a, b|; end")[4][1].should == [:masgn, [:args, [:arg, :a], [:arg, :b]]]
30
+ parsed("proc do |a, b, c|; end")[4][1].should == [:masgn, [:args, [:arg, :a], [:arg, :b], [:arg, :c]]]
31
31
  end
32
32
  end
33
33
 
34
34
  describe "with splat arg" do
35
- it "adds a s(:masgn) for the s(:splat) even if its the only arg" do
36
- parsed("proc do |*a|; end")[4][1].should == [:masgn, [:array, [:splat, [:lasgn, :a]]]]
37
- parsed("proc do |a, *b|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:splat, [:lasgn, :b]]]]
35
+ it "adds a s(:masgn) for the s(:restarg) even if its the only arg" do
36
+ parsed("proc do |*a|; end")[4][1].should == [:masgn, [:args, [:restarg, :a]]]
37
+ parsed("proc do |a, *b|; end")[4][1].should == [:masgn, [:args, [:arg, :a], [:restarg, :b]]]
38
38
  end
39
39
  end
40
40
 
41
41
  describe "with opt args" do
42
- it "adds a s(:block) arg to end of s(:masgn) for each lasgn" do
43
- parsed("proc do |a = 1|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:block, [:lasgn, :a, [:int, 1]]]]]
44
- parsed("proc do |a = 1, b = 2|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :a, [:int, 1]], [:lasgn, :b, [:int, 2]]]]]
42
+ it "adds a s(:optarg) arg each optional argument" do
43
+ parsed("proc do |a = 1|; end")[4][1].should == [:masgn, [:args, [:optarg, :a, [:int, 1]]]]
44
+ parsed("proc do |a = 1, b = 2|; end")[4][1].should == [:masgn, [:args, [:optarg, :a, [:int, 1]], [:optarg, :b, [:int, 2]]]]
45
45
  end
46
46
 
47
- it "should add lasgn block after all other args" do
48
- parsed("proc do |a, b = 1|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :b, [:int, 1]]]]]
49
- parsed("proc do |b = 1, *c|; end")[4][1].should == [:masgn, [:array, [:lasgn, :b], [:splat, [:lasgn, :c]], [:block, [:lasgn, :b, [:int, 1]]]]]
50
- parsed("proc do |b = 1, &c|; end")[4][1].should == [:masgn, [:array, [:lasgn, :b], [:block_pass, [:lasgn, :c]], [:block, [:lasgn, :b, [:int, 1]]]]]
47
+ it "should add args in the direct order" do
48
+ parsed("proc do |a, b = 1|; end")[4][1].should == [:masgn, [:args, [:arg, :a], [:optarg, :b, [:int, 1]]]]
49
+ parsed("proc do |b = 1, *c|; end")[4][1].should == [:masgn, [:args, [:optarg, :b, [:int, 1]], [:restarg, :c]]]
50
+ parsed("proc do |b = 1, &c|; end")[4][1].should == [:masgn, [:args, [:optarg, :b, [:int, 1]], [:block_pass, [:lasgn, :c]]]]
51
51
  end
52
52
  end
53
53
 
54
54
  describe "with block arg" do
55
55
  it "should add block arg with s(:block_pass) wrapping s(:lasgn) prefix" do
56
- parsed("proc do |&a|; end")[4][1].should == [:masgn, [:array, [:block_pass, [:lasgn, :a]]]]
56
+ parsed("proc do |&a|; end")[4][1].should == [:masgn, [:args, [:block_pass, [:lasgn, :a]]]]
57
57
  end
58
58
  end
59
59
  end
@@ -10,6 +10,10 @@ describe "Lambda literals" do
10
10
  parsed("-> {}").should == [:call, nil, :lambda, [:arglist], [:iter, nil]]
11
11
  end
12
12
 
13
+ def parsed_args(source)
14
+ parsed(source)[4][1][1]
15
+ end
16
+
13
17
  describe "with no args" do
14
18
  it "should accept no args" do
15
19
  parsed("-> {}")[4][1].should == nil
@@ -17,34 +21,34 @@ describe "Lambda literals" do
17
21
  end
18
22
 
19
23
  describe "with normal args" do
20
- it "adds a single s(:lasgn) for 1 norm arg" do
21
- parsed("->(a) {}")[4][1].should == [:lasgn, :a]
24
+ it "adds a single s(:masgn) for 1 norm arg" do
25
+ parsed("->(a) {}")[4][1].should == [:masgn, [:args, [:arg, :a]]]
22
26
  end
23
27
 
24
28
  it "lists multiple norm args inside a s(:masgn)" do
25
- parsed("-> (a, b) {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
26
- parsed("-> (a, b, c) {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:lasgn, :c]]]
29
+ parsed("-> (a, b) {}")[4][1].should == [:masgn, [:args, [:arg, :a], [:arg, :b]]]
30
+ parsed("-> (a, b, c) {}")[4][1].should == [:masgn, [:args, [:arg, :a], [:arg, :b], [:arg, :c]]]
27
31
  end
28
32
  end
29
33
 
30
34
  describe "with optional braces" do
31
35
  it "parses normal args" do
32
- parsed("-> a {}")[4][1].should == [:lasgn, :a]
33
- parsed("-> a, b {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
36
+ parsed("-> a {}")[4][1].should == [:masgn, [:args, [:arg, :a]]]
37
+ parsed("-> a, b {}")[4][1].should == [:masgn, [:args, [:arg, :a], [:arg, :b]]]
34
38
  end
35
39
 
36
40
  it "parses splat args" do
37
- parsed("-> *a {}")[4][1].should == [:masgn, [:array, [:splat, [:lasgn, :a]]]]
38
- parsed("-> a, *b {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:splat, [:lasgn, :b]]]]
41
+ parsed("-> *a {}")[4][1].should == [:masgn, [:args, [:restarg, :a]]]
42
+ parsed("-> a, *b {}")[4][1].should == [:masgn, [:args, [:arg, :a], [:restarg, :b]]]
39
43
  end
40
44
 
41
45
  it "parses opt args" do
42
- parsed("-> a = 1 {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:block, [:lasgn, :a, [:int, 1]]]]]
43
- parsed("-> a = 1, b = 2 {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :a, [:int, 1]], [:lasgn, :b, [:int, 2]]]]]
46
+ parsed("-> a = 1 {}")[4][1].should == [:masgn, [:args, [:optarg, :a, [:int, 1]]]]
47
+ parsed("-> a = 1, b = 2 {}")[4][1].should == [:masgn, [:args, [:optarg, :a, [:int, 1]], [:optarg, :b, [:int, 2]]]]
44
48
  end
45
49
 
46
50
  it "parses block args" do
47
- parsed("-> &a {}")[4][1].should == [:masgn, [:array, [:block_pass, [:lasgn, :a]]]]
51
+ parsed("-> &a {}")[4][1].should == [:masgn, [:args, [:block_pass, [:lasgn, :a]]]]
48
52
  end
49
53
  end
50
54
 
@@ -64,7 +68,7 @@ describe "Lambda literals" do
64
68
 
65
69
  it "can parse do..end blocks inside lambda body" do
66
70
  # regression test; see GH issue 544
67
- call_b = [:call, nil, :b, [:arglist], [:iter, [:lasgn, :c]]]
71
+ call_b = [:call, nil, :b, [:arglist], [:iter, [:masgn, [:args, [:arg, :c]]]]]
68
72
  lambda = [:call, nil, :lambda, [:arglist], [:iter, nil, call_b]]
69
73
  expected = [:call, nil, :a, [:arglist, lambda]]
70
74
  parsed("a -> { b do |c| end }").should == expected
@@ -75,4 +79,141 @@ describe "Lambda literals" do
75
79
  expected = [:call, nil, :a, [:arglist, [:call, nil, :lambda, [:arglist], [:iter, nil, [:call, nil, :b, [:arglist]]]]], [:iter, nil]]
76
80
  parsed("a ->{b} do; end").should == expected
77
81
  end
82
+
83
+ context "kwargs as arguments" do
84
+ def s_kwarg
85
+ [:kwarg, :kw]
86
+ end
87
+
88
+ def s_kwoptarg
89
+ [:kwoptarg, :kwopt, [:sym, :default]]
90
+ end
91
+
92
+ def s_kwrestarg
93
+ [:kwrestarg, :kwrest]
94
+ end
95
+
96
+ def s_block
97
+ [:block_pass, [:lasgn, :blk]]
98
+ end
99
+
100
+ it "parses kwarg" do
101
+ parsed_args("->(kw:){}").should == [:args, s_kwarg]
102
+ end
103
+
104
+ it "parses kwoptarg" do
105
+ parsed_args("->(kwopt: :default){}").should == [:args, s_kwoptarg]
106
+ end
107
+
108
+ it "parses kwrestarg" do
109
+ parsed_args("->(**kwrest){}").should == [:args, s_kwrestarg]
110
+ end
111
+
112
+ it "parses kwarg + kwoptarg" do
113
+ parsed_args("->(kw:,kwopt: :default){}").should == [:args, s_kwarg, s_kwoptarg]
114
+ end
115
+
116
+ it "parses kwarg + kwrestarg" do
117
+ parsed_args("->(kw:,**kwrest){}").should == [:args, s_kwarg, s_kwrestarg]
118
+ end
119
+
120
+ it "parses kwarg + kwoptarg + kwrestarg" do
121
+ parsed_args("->(kw:,kwopt: :default,**kwrest){}").should == [:args, s_kwarg, s_kwoptarg, s_kwrestarg]
122
+ end
123
+
124
+ it "parses block + kwarg" do
125
+ parsed_args("->(kw:,&blk){}").should == [:args, s_kwarg, s_block]
126
+ end
127
+
128
+ it "parses block + kwoptarg" do
129
+ parsed_args("->(kwopt: :default,&blk){}").should == [:args, s_kwoptarg, s_block]
130
+ end
131
+
132
+ it "parses block + kwrestarg" do
133
+ parsed_args("->(**kwrest,&blk){}").should == [:args, s_kwrestarg, s_block]
134
+ end
135
+ end
136
+
137
+ context 'rest args' do
138
+ it "parses ->(*a,b)" do
139
+ parsed_args("->(*a, b){}").should == [:args, [:restarg, :a], [:arg, :b]]
140
+ end
141
+
142
+ it "parses ->(a,b=1,*c,d,&blk)" do
143
+ expected = [:args, [:arg, :a], [:optarg, :b, [:int, 1]], [:restarg, :c], [:arg, :d], [:block_pass, [:lasgn, :blk]]]
144
+ parsed_args("->(a,b=1,*c,d,&blk){}").should == expected
145
+ end
146
+
147
+ it "parses ->(a,b=1,c,&blk)" do
148
+ expected = [:args, [:arg, :a], [:optarg, :b, [:int, 1]], [:arg, :c], [:block_pass, [:lasgn, :blk]]]
149
+ parsed_args("->(a,b=1,c,&blk){}").should == expected
150
+ end
151
+
152
+ it "parses ->(a,*b,c,&blk){}" do
153
+ expected = [:args, [:arg, :a], [:restarg, :b], [:arg, :c], [:block_pass, [:lasgn, :blk]]]
154
+ parsed_args("->(a,*b,c,&blk){}").should == expected
155
+ end
156
+
157
+ it "parses ->(a=1,*b,c,&blk){}" do
158
+ expected = [:args, [:optarg, :a, [:int, 1]], [:restarg, :b], [:arg, :c], [:block_pass, [:lasgn, :blk]]]
159
+ parsed_args("->(a=1,*b,c,&blk){}").should == expected
160
+ end
161
+
162
+ it "parses ->(a=1,b,&blk)" do
163
+ expected = [:args, [:optarg, :a, [:int, 1]], [:arg, :b], [:block_pass, [:lasgn, :blk]]]
164
+ parsed_args("->(a=1,b,&blk){}").should == expected
165
+ end
166
+ end
167
+
168
+ context 'shadow args' do
169
+ it "parses lambda{|a;b|}" do
170
+ parsed_args("lambda{|a;b|}").should == [:args, [:arg, :a], [:shadowarg, :b]]
171
+ end
172
+
173
+ it "parses lambda{|;a|}" do
174
+ parsed_args("lambda{|;a|}").should == [:args, [:shadowarg, :a]]
175
+ end
176
+ end
177
+
178
+ context 'mlhs args' do
179
+ it "parses ->((a)){}" do
180
+ parsed_args("->((a)){}").should == [:args, [:mlhs, [:arg, :a]]]
181
+ end
182
+
183
+ it "parses ->((a,*b)){}" do
184
+ parsed_args("->((a,*b)){}").should == [:args, [:mlhs, [:arg, :a], [:restarg, :b]]]
185
+ end
186
+
187
+ it "parses ->((a,*b,c)){}" do
188
+ parsed_args("->((a,*b,c)){}").should == [:args, [:mlhs, [:arg, :a], [:restarg, :b], [:arg, :c]]]
189
+ end
190
+
191
+ it "parses ->((a,*)){}" do
192
+ parsed_args("->((a,*)){}").should == [:args, [:mlhs, [:arg, :a], [:restarg]]]
193
+ end
194
+
195
+ it "parses ->((a,*,b)){}" do
196
+ parsed_args("->((a,*,b)){}").should == [:args, [:mlhs, [:arg, :a], [:restarg], [:arg, :b]]]
197
+ end
198
+
199
+ it "parses ->((*a)){}" do
200
+ parsed_args("->((*a)){}").should == [:args, [:mlhs, [:restarg, :a]]]
201
+ end
202
+
203
+ it "parses ->((*a,b)){}" do
204
+ parsed_args("->((*a,b)){}").should == [:args, [:mlhs, [:restarg, :a], [:arg, :b]]]
205
+ end
206
+
207
+ it "parses ->((*)){}" do
208
+ parsed_args("->((*)){}").should == [:args, [:mlhs, [:restarg]]]
209
+ end
210
+
211
+ it "parses ->((*,a)){}" do
212
+ parsed_args("->((*,a)){}").should == [:args, [:mlhs, [:restarg], [:arg, :a]]]
213
+ end
214
+
215
+ it "parses ->(a,(b,(c,d))){}" do
216
+ parsed_args("->(a,(b,(c,d))){}").should == [:args, [:arg, :a], [:mlhs, [:arg, :b], [:mlhs, [:arg, :c], [:arg, :d]]]]
217
+ end
218
+ end
78
219
  end