rdl 2.0.0.rc2 → 2.0.0.rc3

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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +7 -1
  3. data/README.md +94 -20
  4. data/lib/rdl.rb +4 -1
  5. data/lib/rdl/config.rb +90 -3
  6. data/lib/rdl/info.rb +16 -0
  7. data/lib/rdl/typecheck.rb +207 -79
  8. data/lib/rdl/types/bot.rb +1 -1
  9. data/lib/rdl/types/dependent_arg.rb +17 -8
  10. data/lib/rdl/types/{finitehash.rb → finite_hash.rb} +3 -29
  11. data/lib/rdl/types/generic.rb +1 -37
  12. data/lib/rdl/types/intersection.rb +1 -0
  13. data/lib/rdl/types/lexer.rex +2 -1
  14. data/lib/rdl/types/lexer.rex.rb +4 -1
  15. data/lib/rdl/types/method.rb +2 -12
  16. data/lib/rdl/types/nominal.rb +1 -22
  17. data/lib/rdl/types/non_null.rb +50 -0
  18. data/lib/rdl/types/parser.racc +3 -1
  19. data/lib/rdl/types/parser.tab.rb +222 -190
  20. data/lib/rdl/types/singleton.rb +1 -6
  21. data/lib/rdl/types/structural.rb +1 -10
  22. data/lib/rdl/types/top.rb +1 -2
  23. data/lib/rdl/types/tuple.rb +3 -19
  24. data/lib/rdl/types/type.rb +223 -0
  25. data/lib/rdl/types/union.rb +12 -2
  26. data/lib/rdl/types/var.rb +4 -1
  27. data/lib/rdl/types/wild_query.rb +1 -0
  28. data/lib/rdl/wrap.rb +199 -169
  29. data/lib/rdl_disable.rb +41 -0
  30. data/lib/rdl_types.rb +1 -4
  31. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/_aliases.rb +0 -0
  32. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/abbrev.rb +0 -0
  33. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/array.rb +56 -56
  34. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/base64.rb +0 -0
  35. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/basic_object.rb +0 -0
  36. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/benchmark.rb +0 -0
  37. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bigdecimal.rb +0 -0
  38. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bigmath.rb +0 -0
  39. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bignum.rb +0 -0
  40. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/class.rb +0 -0
  41. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/complex.rb +0 -0
  42. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/coverage.rb +0 -0
  43. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/csv.rb +0 -0
  44. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/date.rb +0 -0
  45. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/dir.rb +0 -0
  46. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/encoding.rb +0 -0
  47. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/enumerable.rb +0 -0
  48. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/enumerator.rb +0 -0
  49. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/exception.rb +0 -0
  50. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/file.rb +0 -0
  51. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/fileutils.rb +0 -0
  52. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/fixnum.rb +0 -0
  53. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/float.rb +26 -26
  54. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/gem.rb +0 -0
  55. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/hash.rb +0 -0
  56. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/integer.rb +8 -8
  57. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/io.rb +0 -0
  58. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/kernel.rb +12 -11
  59. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/marshal.rb +0 -0
  60. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/matchdata.rb +0 -0
  61. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/math.rb +0 -0
  62. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/module.rb +0 -0
  63. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/nil.rb +0 -0
  64. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/numeric.rb +0 -0
  65. data/lib/types/core-ruby-2.x/object.rb +75 -0
  66. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/pathname.rb +0 -0
  67. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/process.rb +0 -0
  68. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/random.rb +0 -0
  69. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/range.rb +0 -0
  70. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/rational.rb +0 -0
  71. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/regexp.rb +0 -0
  72. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/set.rb +0 -0
  73. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/string.rb +0 -0
  74. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/strscan.rb +0 -0
  75. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/symbol.rb +0 -0
  76. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/time.rb +0 -0
  77. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/uri.rb +0 -0
  78. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/yaml.rb +0 -0
  79. data/lib/types/core.rb +4 -0
  80. data/rdl.gemspec +2 -2
  81. data/test/test_le.rb +77 -35
  82. data/test/test_parser.rb +75 -59
  83. data/test/test_rdl.rb +18 -0
  84. data/test/test_typecheck.rb +73 -4
  85. metadata +54 -57
  86. data/lib/rails_types.rb +0 -1
  87. data/types/rails-4.2.1/fixnum.rb +0 -3
  88. data/types/rails-4.2.1/string.rb +0 -3
  89. data/types/rails-tmp/action_dispatch.rb +0 -406
  90. data/types/rails-tmp/active_record.rb +0 -406
  91. data/types/rails-tmp/devise_contracts.rb +0 -216
  92. data/types/ruby-2.x/object.rb +0 -73
@@ -356,4 +356,22 @@ RUBY
356
356
  }
357
357
  end
358
358
 
359
+ def test_inconsistent
360
+ self.class.class_eval {
361
+ type "(Fixnum) -> Fixnum"
362
+ pre { |x| true }
363
+ def inconsistent1(y) return y; end
364
+ }
365
+ end
366
+
367
+ def test_rdl_remove_type
368
+ self.class.class_eval {
369
+ type "() -> nil"
370
+ def remove1() return 42; end
371
+ }
372
+ assert_raises(RDL::Type::TypeError) { remove1 }
373
+ rdl_remove_type(self.class, :remove1)
374
+ assert_equal 42, remove1 # shouldn't raise type error with contract removed
375
+ end
376
+
359
377
  end
@@ -22,7 +22,7 @@ class TestTypecheck < Minitest::Test
22
22
  @env = RDL::Typecheck::Env.new(self: tt("TestTypecheck"))
23
23
  @scopef = { tret: $__rdl_fixnum_type }
24
24
  @tfs = RDL::Type::UnionType.new($__rdl_fixnum_type, $__rdl_string_type)
25
- @scopefs = { tret: @tfs }
25
+ @scopefs = { tret: @tfs, tblock: nil }
26
26
  end
27
27
 
28
28
  # [+ a +] is the environment, a map from symbols to types; empty if omitted
@@ -498,14 +498,57 @@ class TestTypecheck < Minitest::Test
498
498
  assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42) { |x, y| x + y }", env: @env) }
499
499
  assert_equal $__rdl_fixnum_type, do_tc("_send_block1(42) { |x| x }", env: @env)
500
500
  assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42) { |x| 'forty-two' }", env: @env) }
501
- assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = 1; _send_block1(42) { |y| x }", env: @env) }
502
- assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = 1; _send_block1(42) { |y| x = 2 }", env: @env) }
503
- assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = 1; _send_block1(42) { |y| for x in 1..5 do end }", env: @env) } # odd case...
501
+ self.class.class_eval {
502
+ type "() -> 1", typecheck: :now
503
+ def _send_blockd1
504
+ x = 1; _send_block1(42) { |y| x }; x
505
+ end
506
+ }
507
+ self.class.class_eval {
508
+ type "() -> 1 or String", typecheck: :now
509
+ def _send_blockd2
510
+ x = 1; _send_block1(42) { |y| x = 'one'; y}; x
511
+ end
512
+ }
513
+ self.class.class_eval {
514
+ type "() -> Fixnum or String", typecheck: :now
515
+ def _send_blockd3
516
+ x = 'one'; _send_block1(42) { |y| for x in 1..5 do end; y }; x
517
+ end
518
+ }
519
+ end
520
+
521
+ def test_send_method_generic
522
+ self.class.class_eval {
523
+ type :_send_method_generic1, '(t) -> t'
524
+ type :_send_method_generic2, '(t, u) -> t or u'
525
+ type :_send_method_generic3, '() { (u) -> Fixnum } -> Fixnum'
526
+ type :_send_method_generic4, '(t) { (t) -> t } -> t'
527
+ type :_send_method_generic5, '() { (u) -> u } -> u'
528
+ type :_send_method_generic6, '() { (Fixnum) -> u } -> u'
529
+ }
530
+ assert_equal @t3, do_tc('_send_method_generic1 3', env: @env)
531
+ assert_equal $__rdl_string_type, do_tc('_send_method_generic1 "foo"', env: @env)
532
+ assert_equal tt("3 or String"), do_tc('_send_method_generic2 3, "foo"', env: @env)
533
+ assert_equal $__rdl_fixnum_type, do_tc('_send_method_generic3 { |x| 42 }', env: @env)
534
+ assert_equal tt("42"), do_tc('_send_method_generic4(42) { |x| x }', env: @env)
535
+ assert_raises(RDL::Typecheck::StaticTypeError) { do_tc('_send_method_generic4(42) { |x| "foo" }', env: @env) }
536
+ assert_equal tt("u"), do_tc('_send_method_generic5 { |x| x }', env: @env) # not possible to implement _send_method_generic5!
537
+ assert_equal tt("3"), do_tc('_send_method_generic5 { |x| 3 }', env: @env) # weird example, but can pick u=3
538
+ assert_equal $__rdl_string_type, do_tc('_send_method_generic6 { |x| "foo" }', env: @env)
539
+ assert_equal tt("%integer"), do_tc('[1,2,3].index(Object.new)', env: @env)
540
+ assert_equal tt("Array<Fixnum or Bignum>"), do_tc('[1, 2, 3].map { |y| y * 4 }', env: @env)
541
+ assert_equal tt("Array<String>"), do_tc('[1, 2, 3].map { |y| y.to_s }', env: @env)
504
542
  end
505
543
 
506
544
  def test_send_union
545
+ self.class.class_eval {
546
+ type :_send_union1, "(Fixnum) -> Float"
547
+ type :_send_union1, "(String) -> Rational"
548
+ }
507
549
  assert_equal RDL::Type::UnionType.new(@tfs, $__rdl_bignum_type), do_tc("(if _any_object then Fixnum.new else String.new end) * 2", env: @env)
508
550
  assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("(if _any_object then Object.new else Fixnum.new end) + 2", env: @env) }
551
+ assert_equal tt("Float or Rational"), do_tc("if _any_object then x = Fixnum.new else x = String.new end; _send_union1(x)", env: @env)
509
552
  end
510
553
 
511
554
  def test_send_splat
@@ -774,6 +817,7 @@ class TestTypecheck < Minitest::Test
774
817
  # w/send
775
818
  assert_equal tt("2"), do_tc("e = E.new; e.f, b = 1, 2; b", env: @env)
776
819
  assert_equal $__rdl_fixnum_type, do_tc("e = E.new; e.f, b = @f_masgn; b", env: @env)
820
+ assert_equal tt("[1, 2]"), do_tc("@f_masgn[3], y = 1, 2", env: @env)
777
821
 
778
822
  # w/splat
779
823
  assert_equal tt("[1, 2, 3]"), do_tc("*x = [1, 2, 3]")
@@ -930,4 +974,29 @@ class TestTypecheck < Minitest::Test
930
974
  assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck.new.f_attr_accessor = 42", env: @env)
931
975
  end
932
976
 
977
+ # test code where we know different stuff about types on difference branches
978
+ def test_typeful_branches
979
+ assert_equal $__rdl_fixnum_type, do_tc("x = Object.new; case x when String; x.length; end", env: @env)
980
+ assert_equal $__rdl_fixnum_type, do_tc("x = Object.new; case x when String, Array; x.length; end", env: @env)
981
+ assert_equal @t3, do_tc("x = String.new; case x when String; 3; when Fixnum; 4; end", env: @env)
982
+ end
983
+
984
+ def test_context_typecheck
985
+ assert_raises(RDL::Typecheck::StaticTypeError) {
986
+ self.class.class_eval {
987
+ type '() -> Fixnum', typecheck: :now
988
+ def context_typecheck1
989
+ context_tc_in_context1 # should fail
990
+ end
991
+ }
992
+ }
993
+ $__rdl_info.add(self.class, :context_typecheck2, :context_types, [self.class, :context_tc_in_context2, $__rdl_parser.scan_str('() -> Fixnum')])
994
+ self.class.class_eval {
995
+ type '() -> Fixnum', typecheck: :now
996
+ def context_typecheck2
997
+ context_tc_in_context2 # should not fail since method defined in context
998
+ end
999
+ }
1000
+ end
1001
+
933
1002
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdl
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc2
4
+ version: 2.0.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeffrey S. Foster
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-07-19 00:00:00.000000000 Z
15
+ date: 2016-08-11 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: parser
@@ -111,7 +111,6 @@ files:
111
111
  - extras/type_tests/zero?.rb
112
112
  - extras/type_tests/|.rb
113
113
  - gemfiles/Gemfile.travis
114
- - lib/rails_types.rb
115
114
  - lib/rdl.rb
116
115
  - lib/rdl/config.rb
117
116
  - lib/rdl/contracts/and.rb
@@ -127,13 +126,14 @@ files:
127
126
  - lib/rdl/types/bot.rb
128
127
  - lib/rdl/types/dependent_arg.rb
129
128
  - lib/rdl/types/dots_query.rb
130
- - lib/rdl/types/finitehash.rb
129
+ - lib/rdl/types/finite_hash.rb
131
130
  - lib/rdl/types/generic.rb
132
131
  - lib/rdl/types/intersection.rb
133
132
  - lib/rdl/types/lexer.rex
134
133
  - lib/rdl/types/lexer.rex.rb
135
134
  - lib/rdl/types/method.rb
136
135
  - lib/rdl/types/nominal.rb
136
+ - lib/rdl/types/non_null.rb
137
137
  - lib/rdl/types/optional.rb
138
138
  - lib/rdl/types/parser.racc
139
139
  - lib/rdl/types/parser.tab.rb
@@ -150,7 +150,57 @@ files:
150
150
  - lib/rdl/types/wild_query.rb
151
151
  - lib/rdl/util.rb
152
152
  - lib/rdl/wrap.rb
153
+ - lib/rdl_disable.rb
153
154
  - lib/rdl_types.rb
155
+ - lib/types/core-ruby-2.x/_aliases.rb
156
+ - lib/types/core-ruby-2.x/abbrev.rb
157
+ - lib/types/core-ruby-2.x/array.rb
158
+ - lib/types/core-ruby-2.x/base64.rb
159
+ - lib/types/core-ruby-2.x/basic_object.rb
160
+ - lib/types/core-ruby-2.x/benchmark.rb
161
+ - lib/types/core-ruby-2.x/bigdecimal.rb
162
+ - lib/types/core-ruby-2.x/bigmath.rb
163
+ - lib/types/core-ruby-2.x/bignum.rb
164
+ - lib/types/core-ruby-2.x/class.rb
165
+ - lib/types/core-ruby-2.x/complex.rb
166
+ - lib/types/core-ruby-2.x/coverage.rb
167
+ - lib/types/core-ruby-2.x/csv.rb
168
+ - lib/types/core-ruby-2.x/date.rb
169
+ - lib/types/core-ruby-2.x/dir.rb
170
+ - lib/types/core-ruby-2.x/encoding.rb
171
+ - lib/types/core-ruby-2.x/enumerable.rb
172
+ - lib/types/core-ruby-2.x/enumerator.rb
173
+ - lib/types/core-ruby-2.x/exception.rb
174
+ - lib/types/core-ruby-2.x/file.rb
175
+ - lib/types/core-ruby-2.x/fileutils.rb
176
+ - lib/types/core-ruby-2.x/fixnum.rb
177
+ - lib/types/core-ruby-2.x/float.rb
178
+ - lib/types/core-ruby-2.x/gem.rb
179
+ - lib/types/core-ruby-2.x/hash.rb
180
+ - lib/types/core-ruby-2.x/integer.rb
181
+ - lib/types/core-ruby-2.x/io.rb
182
+ - lib/types/core-ruby-2.x/kernel.rb
183
+ - lib/types/core-ruby-2.x/marshal.rb
184
+ - lib/types/core-ruby-2.x/matchdata.rb
185
+ - lib/types/core-ruby-2.x/math.rb
186
+ - lib/types/core-ruby-2.x/module.rb
187
+ - lib/types/core-ruby-2.x/nil.rb
188
+ - lib/types/core-ruby-2.x/numeric.rb
189
+ - lib/types/core-ruby-2.x/object.rb
190
+ - lib/types/core-ruby-2.x/pathname.rb
191
+ - lib/types/core-ruby-2.x/process.rb
192
+ - lib/types/core-ruby-2.x/random.rb
193
+ - lib/types/core-ruby-2.x/range.rb
194
+ - lib/types/core-ruby-2.x/rational.rb
195
+ - lib/types/core-ruby-2.x/regexp.rb
196
+ - lib/types/core-ruby-2.x/set.rb
197
+ - lib/types/core-ruby-2.x/string.rb
198
+ - lib/types/core-ruby-2.x/strscan.rb
199
+ - lib/types/core-ruby-2.x/symbol.rb
200
+ - lib/types/core-ruby-2.x/time.rb
201
+ - lib/types/core-ruby-2.x/uri.rb
202
+ - lib/types/core-ruby-2.x/yaml.rb
203
+ - lib/types/core.rb
154
204
  - rdl.gemspec
155
205
  - test/disabled_test_coverage.rb
156
206
  - test/disabled_test_rdoc.rb
@@ -170,59 +220,6 @@ files:
170
220
  - test/test_typecheck.rb
171
221
  - test/test_types.rb
172
222
  - test/test_wrap.rb
173
- - types/rails-4.2.1/fixnum.rb
174
- - types/rails-4.2.1/string.rb
175
- - types/rails-tmp/action_dispatch.rb
176
- - types/rails-tmp/active_record.rb
177
- - types/rails-tmp/devise_contracts.rb
178
- - types/ruby-2.x/_aliases.rb
179
- - types/ruby-2.x/abbrev.rb
180
- - types/ruby-2.x/array.rb
181
- - types/ruby-2.x/base64.rb
182
- - types/ruby-2.x/basic_object.rb
183
- - types/ruby-2.x/benchmark.rb
184
- - types/ruby-2.x/bigdecimal.rb
185
- - types/ruby-2.x/bigmath.rb
186
- - types/ruby-2.x/bignum.rb
187
- - types/ruby-2.x/class.rb
188
- - types/ruby-2.x/complex.rb
189
- - types/ruby-2.x/coverage.rb
190
- - types/ruby-2.x/csv.rb
191
- - types/ruby-2.x/date.rb
192
- - types/ruby-2.x/dir.rb
193
- - types/ruby-2.x/encoding.rb
194
- - types/ruby-2.x/enumerable.rb
195
- - types/ruby-2.x/enumerator.rb
196
- - types/ruby-2.x/exception.rb
197
- - types/ruby-2.x/file.rb
198
- - types/ruby-2.x/fileutils.rb
199
- - types/ruby-2.x/fixnum.rb
200
- - types/ruby-2.x/float.rb
201
- - types/ruby-2.x/gem.rb
202
- - types/ruby-2.x/hash.rb
203
- - types/ruby-2.x/integer.rb
204
- - types/ruby-2.x/io.rb
205
- - types/ruby-2.x/kernel.rb
206
- - types/ruby-2.x/marshal.rb
207
- - types/ruby-2.x/matchdata.rb
208
- - types/ruby-2.x/math.rb
209
- - types/ruby-2.x/module.rb
210
- - types/ruby-2.x/nil.rb
211
- - types/ruby-2.x/numeric.rb
212
- - types/ruby-2.x/object.rb
213
- - types/ruby-2.x/pathname.rb
214
- - types/ruby-2.x/process.rb
215
- - types/ruby-2.x/random.rb
216
- - types/ruby-2.x/range.rb
217
- - types/ruby-2.x/rational.rb
218
- - types/ruby-2.x/regexp.rb
219
- - types/ruby-2.x/set.rb
220
- - types/ruby-2.x/string.rb
221
- - types/ruby-2.x/strscan.rb
222
- - types/ruby-2.x/symbol.rb
223
- - types/ruby-2.x/time.rb
224
- - types/ruby-2.x/uri.rb
225
- - types/ruby-2.x/yaml.rb
226
223
  homepage: https://github.com/plum-umd/rdl
227
224
  licenses:
228
225
  - BSD-3-Clause
@@ -1 +0,0 @@
1
- require_rel "../types/rails-#{Rails::VERSION::STRING}/*.rb"
@@ -1,3 +0,0 @@
1
- class Fixnum
2
- type :*, '(ActiveSupport::Duration) -> ActiveSupport::Duration'
3
- end
@@ -1,3 +0,0 @@
1
- class String
2
- type :html_safe, '() -> String'
3
- end
@@ -1,406 +0,0 @@
1
- module RailsHelper
2
- class << self
3
- attr_accessor :namespace
4
- attr_accessor :resources_stack
5
- attr_accessor :inside_member
6
- end
7
-
8
- def self.get_path_helper(name)
9
- stack = RailsHelper.resources_stack.map {|e| e.to_s.singularize}
10
- resources_str = stack.join("_")
11
- method_prefix = resources_str == "" ? "#{name}" : "#{name}_#{resources_str}"
12
- :"#{method_prefix}_path"
13
- end
14
-
15
- def self.get_resource_info(controller, action)
16
- controller_s = controller.singularize
17
- controller_c = controller_s.camelize
18
-
19
- case action
20
- when :new
21
- v = [/^GET$/]
22
- p = "/#{controller_s}/new"
23
- prefix = "#{controller_s}"
24
- pht = "() -> String"
25
- when :create
26
- v = [/^POST$/]
27
- p = "/#{controller_s}"
28
- prefix = "#{controller_s}"
29
- pht = "() -> String"
30
- when :show
31
- v = [/^GET$/]
32
- p = "/#{controller_s}"
33
- prefix = "#{controller_s}"
34
- pht = "() -> String"
35
- when :edit
36
- v = [/^GET$/]
37
- p = "/#{controller_s}/edit"
38
- prefix = "edit_#{controller_s}"
39
- pht = "() -> String"
40
- when :update
41
- v = [/^PUT$/, /^PATCH$/]
42
- p = "/#{controller_s}"
43
- prefix = "#{controller_s}"
44
- pht = "() -> String"
45
- when :destroy
46
- v = [/^DELETE$/]
47
- p = "/#{controller_s}"
48
- prefix = "#{controller_s}"
49
- pht = "() -> String"
50
- else
51
- raise Exception, "invalid action #{action.inspect}"
52
- end
53
-
54
- ph = "#{prefix}_path".to_sym
55
- uh = "#{prefix}_url".to_sym
56
- uht = pht
57
- {:verb => v, :path => p, :path_helper => [ph, pht], :url_helper => [uh, uht]}
58
- end
59
-
60
- def self.get_resources_info(controller, action)
61
- controller_s = controller.singularize
62
- controller_c = controller_s.camelize
63
- n = RailsHelper.namespace.to_s
64
- nnh = (n == "" ? "" : "#{n}_")
65
-
66
- case action
67
- when :index
68
- v = [/^GET$/]
69
- p = "/#{controller}"
70
- prefix = "#{nnh}#{controller}"
71
- pht = "() -> String"
72
- when :new
73
- v = [/^GET$/]
74
- p = "/#{controller}/new"
75
-
76
- if n == ""
77
- prefix = "#{controller_s}"
78
- else
79
- prefix = "new_#{nnh}#{controller_s}"
80
- end
81
-
82
- pht = "() -> String"
83
- when :create
84
- v = [/^POST$/]
85
- p = "/#{controller}"
86
- prefix = "#{nnh}#{controller}"
87
- pht = "() -> String"
88
- when :show
89
- v = [/^GET$/]
90
- p = "/#{controller}/:id"
91
- prefix = "#{nnh}#{controller_s}"
92
- pht = "(#{controller_c}) -> String"
93
- when :edit
94
- v = [/^GET$/]
95
- p = "/#{controller}/:id/edit"
96
- prefix = "edit_#{nnh}#{controller_s}"
97
- pht = "(#{controller_c}) -> String"
98
- when :update
99
- v = [/^PUT$/, /^PATCH$/]
100
- p = "/#{controller}/:id"
101
- prefix = "#{nnh}#{controller_s}"
102
- pht = "(#{controller_c}) -> String"
103
- when :destroy
104
- v = [/^DELETE$/]
105
- p = "/#{controller}/:id"
106
- prefix = "#{nnh}#{controller_s}"
107
- pht = "(#{controller_c}) -> String"
108
- else
109
- raise Exception, "invalid action #{action.inspect}"
110
- end
111
-
112
- p = "/#{nnh[0..-2]}#{p}" if nnh != ""
113
-
114
- ph = "#{prefix}_path".to_sym
115
- uh = "#{prefix}_url".to_sym
116
- uht = pht
117
- {:verb => v, :path => p, :path_helper => [ph, pht], :url_helper => [uh, uht]}
118
- end
119
-
120
- def self.resource_routes_info_valid?(routes, controller, action, options={})
121
- info = get_resource_info(controller, action)
122
- r_p = info[:path]
123
- r_v = info[:verb]
124
-
125
- routes.any? {|r|
126
- defaults = r.app.instance_variable_get(:@defaults)
127
- path = r.path.spec.to_s.split('(')[0]
128
-
129
- if defaults
130
- defaults[:controller] == controller and defaults[:action] == action.to_s and path == r_p and r_v.include?(r.verb)
131
- else
132
- false
133
- end
134
- }
135
- end
136
-
137
- def self.resources_routes_info_valid?(routes, controller, action, options={})
138
- info = get_resources_info(controller, action)
139
- r_p = info[:path]
140
- r_v = info[:verb]
141
-
142
- namespace = self.namespace.to_s
143
- namespace == "" ? c2 = controller : c2 = "#{namespace}/#{controller}"
144
-
145
- routes.any? {|r|
146
- defaults = r.app.instance_variable_get(:@defaults)
147
- path = r.path.spec.to_s.split('(')[0]
148
-
149
- if defaults
150
- defaults[:controller] == c2 and defaults[:action] == action.to_s and path == r_p and r_v.include?(r.verb)
151
- else
152
- false
153
- end
154
- }
155
- end
156
-
157
- def self.resource_routes_valid?(routes, resources_args)
158
- controller = resources_args[0].to_s.pluralize
159
- controller_obj = controller.pluralize.camelize + "Controller"
160
- controller_obj = eval(controller_obj)
161
- options = resources_args[1].nil? ? {} : resources_args[1]
162
- routes = Rails.application.routes.routes.to_a
163
-
164
- actions = [:new, :create, :show, :edit, :update, :destroy]
165
-
166
- if options.keys.include?(:only)
167
- actions = options[:only]
168
- elsif options.keys.include?(:except)
169
- actions = actions - options[:except]
170
- end
171
-
172
- r1 = actions.all? {|action|
173
- resource_routes_info_valid?(routes, controller, action, options)
174
- }
175
-
176
- r2 = actions.all? {|action|
177
- info = get_resource_info(controller, action)
178
- r_ph = info[:path_helper][0]
179
- r_uh = info[:url_helper][0]
180
-
181
- path_helper_added = controller_obj.instance_methods.include?(r_ph)
182
- url_helper_added = controller_obj.instance_methods.include?(r_uh)
183
-
184
- path_helper_added and url_helper_added
185
- }
186
-
187
- r1 and r2
188
- end
189
-
190
- def self.resources_routes_valid?(routes, resources_args)
191
- controller = resources_args[0].to_s
192
- controller_obj = controller.camelize + "Controller"
193
- controller_obj = eval(controller_obj)
194
- options = resources_args[1].nil? ? {} : resources_args[1]
195
- routes = Rails.application.routes.routes.to_a
196
-
197
- actions = [:index, :new, :create, :show, :edit, :update, :destroy]
198
-
199
- if options.keys.include?(:only)
200
- actions = options[:only]
201
- elsif options.keys.include?(:except)
202
- actions = actions - options[:except]
203
- end
204
-
205
- r1 = actions.all? {|action|
206
- resources_routes_info_valid?(routes, controller, action, options)
207
- }
208
-
209
- r2 = actions.all? {|action|
210
- info = get_resources_info(controller, action)
211
- r_ph = info[:path_helper][0]
212
- r_uh = info[:url_helper][0]
213
-
214
- path_helper_added = controller_obj.instance_methods.include?(r_ph)
215
- url_helper_added = controller_obj.instance_methods.include?(r_uh)
216
-
217
- path_helper_added and url_helper_added
218
- }
219
-
220
- r1 and r2
221
- end
222
- end
223
-
224
- module ActionDispatch
225
- module Routing
226
- class Mapper
227
- extend RDL
228
-
229
- spec :root do
230
- post_cond do |ret, *args|
231
- methods = [:root_path, :root_url]
232
-
233
- methods.all? {|m|
234
- puts "ApplicationController ##% #{m} : () -> String"
235
-
236
- #add_typesig(ApplicationController, m, "() -> String")
237
- ApplicationController.instance_methods.include?(m)
238
- }
239
- end
240
- end
241
-
242
- spec :namespace do
243
- pre_task do |*args, &blk|
244
- RailsHelper.namespace = args[0]
245
- end
246
-
247
- post_task do |ret, *args, &blk|
248
- RailsHelper.namespace = nil
249
- end
250
- end
251
-
252
- spec :get do
253
- pre_cond do |*args, &blk|
254
- options = args[1] || {}
255
-
256
- if options.keys.include?(:to)
257
- if options[:to].class == String
258
- controller = options[:to].split("#")[0]
259
- controller = controller.camelize
260
- action = options[:to].split("#")[1]
261
-
262
- controller_defined = Object.const_defined?(controller)
263
-
264
- # TODO: see if action was added. Need late binding?
265
-
266
- controller_defined
267
- else
268
- true
269
- end
270
- else
271
- true
272
- end
273
- end
274
-
275
- post_cond do |ret, *args|
276
- if RailsHelper.inside_member and not parent_resource.actions.include?(args[0])
277
- path_helper = RailsHelper.get_path_helper(args[0])
278
- ctrl = parent_resource.controller.singularize.camelize
279
-
280
- puts "ApplicationController ##% #{path_helper} : (#{ctrl}) -> String"
281
-
282
- add_typesig(ApplicationController, path_helper, "() -> String")
283
-
284
- ApplicationController.instance_methods.include?(path_helper)
285
- else
286
- true
287
- end
288
- end
289
- end
290
-
291
- spec :post do
292
- post_cond do |ret, *args|
293
- if RailsHelper.inside_member and not parent_resource.actions.include?(args[0])
294
- path_helper = RailsHelper.get_path_helper(args[0])
295
- ctrl = parent_resource.controller.singularize.camelize
296
-
297
- puts "ApplicationController ##% #{path_helper} : (#{ctrl}) -> String"
298
-
299
- add_typesig(ApplicationController, path_helper, "() -> String")
300
-
301
- ApplicationController.instance_methods.include?(path_helper)
302
- else
303
- true
304
- end
305
- end
306
- end
307
-
308
- spec :member do
309
- pre_task do |*args|
310
- RailsHelper.inside_member = true
311
- end
312
-
313
- post_task do |*args|
314
- RailsHelper.inside_member = false
315
- end
316
- end
317
-
318
- spec :resource do
319
- post_task do |ret, *args, &blk|
320
- return true if args[0] == :session or args[0] == :password or args[0] == :registration or args[0] == :confirmation
321
-
322
- controller = args[0].to_s
323
- controller_obj = controller.pluralize.camelize + "Controller"
324
- controller_obj = eval(controller_obj)
325
- options = args[1] || {}
326
- routes = Rails.application.routes.routes.to_a
327
-
328
- actions = [:new, :create, :show, :edit, :update, :destroy]
329
-
330
- if options.keys.include?(:only)
331
- actions = options[:only]
332
- elsif options.keys.include?(:except)
333
- actions = actions - options[:except]
334
- end
335
-
336
- actions.each {|action|
337
- info = RailsHelper.get_resource_info(controller, action)
338
- r_ph = info[:path_helper]
339
- r_uh = info[:url_helper]
340
-
341
- #typesig(controller_obj, r_ph[0], r_ph[1])
342
- #typesig(controller_obj, r_uh[0], r_uh[1])
343
- }
344
- end
345
-
346
- post_cond do |ret, *args, &blk|
347
- return true if args[0] == :session or args[0] == :password or args[0] == :registration or args[0] == :confirmation
348
-
349
- model = args[0].to_s
350
- routes = Rails.application.routes.routes.to_a
351
-
352
- new_routes_valid = RailsHelper.resource_routes_valid?(routes, args)
353
-
354
- new_routes_valid
355
- end
356
- end
357
-
358
- # TODO: resources arg can also be a list
359
- spec :resources do
360
- pre_task do |*args, &blk|
361
- RailsHelper.resources_stack = [] if not RailsHelper.resources_stack
362
- RailsHelper.resources_stack.push(args[0])
363
- end
364
-
365
- post_task do |ret, *args, &blk|
366
- RailsHelper.resources_stack.pop
367
-
368
- controller = args[0].to_s
369
- controller_obj = controller.camelize + "Controller"
370
- controller_obj = eval(controller_obj)
371
- options = args[1] || {}
372
- routes = Rails.application.routes.routes.to_a
373
-
374
- actions = [:index, :new, :create, :show, :edit, :update, :destroy]
375
-
376
- if options.keys.include?(:only)
377
- actions = options[:only]
378
- elsif options.keys.include?(:except)
379
- actions = actions - options[:except]
380
- end
381
-
382
- actions.each {|action|
383
- info = RailsHelper.get_resources_info(controller, action)
384
- r_ph = info[:path_helper]
385
- r_uh = info[:url_helper]
386
-
387
- puts "#{controller_obj} ##% #{r_ph[0]} : #{r_ph[1]}"
388
- puts "#{controller_obj} ##% #{r_uh[0]} : #{r_uh[1]}"
389
-
390
- #typesig(controller_obj, r_ph[0], r_ph[1])
391
- #typesig(controller_obj, r_uh[0], r_uh[1])
392
- }
393
- end
394
-
395
- post_cond do |ret, *args, &blk|
396
- model = args[0].to_s
397
- routes = Rails.application.routes.routes.to_a
398
-
399
- new_routes_valid = RailsHelper.resources_routes_valid?(routes, args)
400
-
401
- new_routes_valid
402
- end
403
- end
404
- end
405
- end
406
- end