rdl 2.0.0.rc2 → 2.0.0.rc3

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