rdl 2.0.0.rc3 → 2.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12683f52b0d365695fbbddde7ab7494ae049202e
4
- data.tar.gz: 67d2aaf4bde9eba67027f5bc7662fd7d7e33c746
3
+ metadata.gz: 036f7f5447f5a5405a0624b7f346101e19012c19
4
+ data.tar.gz: 3004e573e29f44e4adea3c2b1cdc314134fa4f4f
5
5
  SHA512:
6
- metadata.gz: f42995d41cd05b3d9e1115c0cf7e20a4873f840659e9fd56e0f476941adac6dfef199dce88bacafdefaacbc3cf410be917fc6213b77ebe0a5428840e75721542
7
- data.tar.gz: 0ee8aa838a19d9977acc2556bba2ef295bc8be97a6a6407af4a7882a2ecd62c09ef4d5b6464a61f49137d26751bd43c581df932e883424f96126847edf1606f9
6
+ metadata.gz: 0355d89a993299da187c096dd85b27209205a0155c80780944c88118a775e2b82f6f9746536465f8f096a8197ebfd1084f64c613f90a1319e2a31b88f5b1645a
7
+ data.tar.gz: db84c871660e4e4e6458d31f11bef1ed5a68056d3ac5dd8fd293e85b5b189cc9431c359c28a1db41fc3dd27244835f854aa8aa287a5873786bb0f4b7a72b72b9
data/CHANGES.md CHANGED
@@ -10,9 +10,13 @@
10
10
 
11
11
  ### Changed
12
12
  - Modified `self` type to be any instance of the self's class
13
- - Library types now use new aliases %integer and %numeric instead of the Integer and Numeric classes.
13
+ - Library types now use new aliases %integer and %numeric instead of the Integer and Numeric classes
14
+ - Instead of requiring `rdl_types.rb`, require `types/core`
15
+
16
+ ### Fixed
14
17
  - Fix issue #14 - allow type/pre/post to coexist, improve docs on dependent types
15
18
  - Fix typos in README, pull req #13
19
+ - Fix bug where calling method overloaded sometimes with block and sometimes without would always report type error
16
20
 
17
21
  ## [1.1.1] - 2016-05-21
18
22
  ### Fixed
data/README.md CHANGED
@@ -148,7 +148,29 @@ For performance reasons you probably don't want to use RDL in production code. T
148
148
 
149
149
  ## Rails
150
150
 
151
- To use RDL with Rails, use the [rdl-rails](https://github.com/plum-umd/rdl-rails) gem.
151
+ To add types to a Ruby on Rails application, add
152
+
153
+ ```ruby
154
+ gem 'rdl'
155
+ ```
156
+
157
+ to your `Gemfile` to get the latest stable version, or
158
+
159
+ ```ruby
160
+ gem 'rdl', git: 'https://github.com/plum-umd/rdl'
161
+ ```
162
+
163
+ to get the head version from github.
164
+
165
+ In development and test mode, you will now have access to `rdl`, `types/core` from RDL, and extra type annotations for Rails and some related gems. In production mode, RDL will be disabled (by loading `rdl_disable`).
166
+
167
+ Currently, rdl has types for the following versions of Rails:
168
+
169
+ * Rails 5.x support - limited to the following:
170
+ * Automatically generates
171
+ * Models
172
+ * Type annotations for model column getters and setters
173
+ * `find_by` and `find_by!`
152
174
 
153
175
  ## Preconditions and Postconditions
154
176
 
@@ -688,6 +710,8 @@ RDL uses the same approach for hashes: hash literals are treated as finite hashe
688
710
 
689
711
  * *Caching.* If `typecheck: :call` is specified on a method, Ruby will type check the method every time it is called. In the future, RDL will cache these checks.
690
712
 
713
+ * *Dependent Types.* RDL ignores refinements in checking code with dependent types. E.g., given a `Fixnum x {{ x > 0 }}`, RDL will simply treat `x` as a `Fixnum` and ignore the requirement that it be positive.
714
+
691
715
  * *Unsupported Features.* There are several features of Ruby that are currently not handled by RDL. Here is a non-exhaustive list:
692
716
  * `super` is not supported.
693
717
  * `lambda` has special semantics for `return`; this is not supported.
data/lib/rdl.rb CHANGED
@@ -1,129 +1,7 @@
1
- require 'delegate'
2
- require 'digest'
3
- require 'set'
4
- require 'parser/current'
1
+ # This wrapper file allows us to completely disable RDL in certain modes.
5
2
 
6
- module RDL
3
+ if defined?(Rails)
4
+ require 'rdl/boot_rails'
5
+ else
6
+ require 'rdl/boot'
7
7
  end
8
-
9
- require 'rdl/config.rb'
10
- def RDL.config
11
- yield(RDL::Config.instance)
12
- end
13
- require 'rdl/info.rb'
14
-
15
- # Method/variable info table with kinds:
16
- # For methods
17
- # :pre to array of precondition contracts
18
- # :post to array of postcondition contracts
19
- # :type to array of types
20
- # :source_location to [filename, linenumber] location of most recent definition
21
- # :typecheck - boolean that is true if method should be statically type checked
22
- # :otype to set of types that were observed at run time, where a type is a finite hash {:args => Array<Class>, :ret => Class, :block => %bool}
23
- # :context_types to array of [klass, meth, Type] - method types that exist only within this method. An icky hack to deal with Rails `params`.
24
- # For variables
25
- # :type to type
26
- $__rdl_info = RDL::Info.new
27
-
28
- # Map from full_method_name to number of times called when wrapped
29
- $__rdl_wrapped_calls = Hash.new 0
30
-
31
- # Hash from class name to array of symbols that are the class's type parameters
32
- $__rdl_type_params = Hash.new
33
-
34
- # Hash from class name to method name to its alias method name
35
- # class names are strings
36
- # method names are symbols
37
- $__rdl_aliases = Hash.new
38
-
39
- # Set of [class, method] pairs to wrap.
40
- # class is a string
41
- # method is a symbol
42
- $__rdl_to_wrap = Set.new
43
-
44
- # Map from symbols to set of [class, method] pairs to type check when those symbols are rdl_do_typecheck'd
45
- # (or the methods are defined, for the symbol :now)
46
- $__rdl_to_typecheck = Hash.new
47
- $__rdl_to_typecheck[:now] = Set.new
48
-
49
- # List of contracts that should be applied to the next method definition
50
- $__rdl_deferred = []
51
-
52
- # Create switches to control whether wrapping happens and whether
53
- # contracts are checked. These need to be created before rdl/wrap.rb
54
- # is loaded.
55
- require 'rdl/switch.rb'
56
- $__rdl_wrap_switch = RDL::Switch.new
57
- $__rdl_contract_switch = RDL::Switch.new
58
-
59
- require 'rdl/types/type.rb'
60
- require 'rdl/types/annotated_arg.rb'
61
- require 'rdl/types/bot.rb'
62
- require 'rdl/types/dependent_arg.rb'
63
- require 'rdl/types/dots_query.rb'
64
- require 'rdl/types/finite_hash.rb'
65
- require 'rdl/types/generic.rb'
66
- require 'rdl/types/intersection.rb'
67
- require 'rdl/types/lexer.rex.rb'
68
- require 'rdl/types/method.rb'
69
- require 'rdl/types/singleton.rb'
70
- require 'rdl/types/nominal.rb'
71
- require 'rdl/types/non_null.rb'
72
- require 'rdl/types/optional.rb'
73
- require 'rdl/types/parser.tab.rb'
74
- require 'rdl/types/structural.rb'
75
- require 'rdl/types/top.rb'
76
- require 'rdl/types/tuple.rb'
77
- require 'rdl/types/type_query.rb'
78
- require 'rdl/types/union.rb'
79
- require 'rdl/types/var.rb'
80
- require 'rdl/types/vararg.rb'
81
- require 'rdl/types/wild_query.rb'
82
-
83
- require 'rdl/contracts/contract.rb'
84
- require 'rdl/contracts/and.rb'
85
- require 'rdl/contracts/flat.rb'
86
- require 'rdl/contracts/or.rb'
87
- require 'rdl/contracts/proc.rb'
88
-
89
- require 'rdl/util.rb'
90
- require 'rdl/wrap.rb'
91
- require 'rdl/query.rb'
92
- require 'rdl/typecheck.rb'
93
- #require_relative 'rdl/stats.rb'
94
-
95
- $__rdl_parser = RDL::Type::Parser.new
96
-
97
- # Map from file names to [digest, cache] where 2nd elt maps
98
- # :ast to the AST
99
- # :line_defs maps linenumber to AST for def at that line
100
- $__rdl_ruby_parser_cache = Hash.new
101
-
102
- # Some generally useful types; not really a big deal to do this since
103
- # NominalTypes are cached, but these names are shorter to type
104
- $__rdl_nil_type = RDL::Type::NominalType.new NilClass # actually creates singleton type
105
- $__rdl_top_type = RDL::Type::TopType.new
106
- $__rdl_bot_type = RDL::Type::BotType.new
107
- $__rdl_object_type = RDL::Type::NominalType.new Object
108
- $__rdl_true_type = RDL::Type::NominalType.new TrueClass # actually creates singleton type
109
- $__rdl_false_type = RDL::Type::NominalType.new FalseClass # also singleton type
110
- $__rdl_bool_type = RDL::Type::UnionType.new($__rdl_true_type, $__rdl_false_type)
111
- $__rdl_fixnum_type = RDL::Type::NominalType.new Fixnum
112
- $__rdl_bignum_type = RDL::Type::NominalType.new Bignum
113
- $__rdl_float_type = RDL::Type::NominalType.new Float
114
- $__rdl_complex_type = RDL::Type::NominalType.new Complex
115
- $__rdl_rational_type = RDL::Type::NominalType.new Rational
116
- $__rdl_integer_type = RDL::Type::UnionType.new($__rdl_fixnum_type, $__rdl_bignum_type)
117
- $__rdl_numeric_type = RDL::Type::NominalType.new Numeric
118
- $__rdl_string_type = RDL::Type::NominalType.new String
119
- $__rdl_array_type = RDL::Type::NominalType.new Array
120
- $__rdl_hash_type = RDL::Type::NominalType.new Hash
121
- $__rdl_symbol_type = RDL::Type::NominalType.new Symbol
122
- $__rdl_range_type = RDL::Type::NominalType.new Range
123
- $__rdl_regexp_type = RDL::Type::NominalType.new Regexp
124
- $__rdl_standard_error_type = RDL::Type::NominalType.new StandardError
125
-
126
- # Hash from special type names to their values
127
- $__rdl_special_types = {'%any' => $__rdl_top_type,
128
- '%bot' => $__rdl_bot_type,
129
- '%bool' => $__rdl_bool_type}
@@ -0,0 +1,129 @@
1
+ require 'delegate'
2
+ require 'digest'
3
+ require 'set'
4
+ require 'parser/current'
5
+
6
+ module RDL
7
+ end
8
+
9
+ require 'rdl/config.rb'
10
+ def RDL.config
11
+ yield(RDL::Config.instance)
12
+ end
13
+ require 'rdl/info.rb'
14
+
15
+ # Method/variable info table with kinds:
16
+ # For methods
17
+ # :pre to array of precondition contracts
18
+ # :post to array of postcondition contracts
19
+ # :type to array of types
20
+ # :source_location to [filename, linenumber] location of most recent definition
21
+ # :typecheck - boolean that is true if method should be statically type checked
22
+ # :otype to set of types that were observed at run time, where a type is a finite hash {:args => Array<Class>, :ret => Class, :block => %bool}
23
+ # :context_types to array of [klass, meth, Type] - method types that exist only within this method. An icky hack to deal with Rails `params`.
24
+ # For variables
25
+ # :type to type
26
+ $__rdl_info = RDL::Info.new
27
+
28
+ # Map from full_method_name to number of times called when wrapped
29
+ $__rdl_wrapped_calls = Hash.new 0
30
+
31
+ # Hash from class name to array of symbols that are the class's type parameters
32
+ $__rdl_type_params = Hash.new
33
+
34
+ # Hash from class name to method name to its alias method name
35
+ # class names are strings
36
+ # method names are symbols
37
+ $__rdl_aliases = Hash.new
38
+
39
+ # Set of [class, method] pairs to wrap.
40
+ # class is a string
41
+ # method is a symbol
42
+ $__rdl_to_wrap = Set.new
43
+
44
+ # Map from symbols to set of [class, method] pairs to type check when those symbols are rdl_do_typecheck'd
45
+ # (or the methods are defined, for the symbol :now)
46
+ $__rdl_to_typecheck = Hash.new
47
+ $__rdl_to_typecheck[:now] = Set.new
48
+
49
+ # List of contracts that should be applied to the next method definition
50
+ $__rdl_deferred = []
51
+
52
+ # Create switches to control whether wrapping happens and whether
53
+ # contracts are checked. These need to be created before rdl/wrap.rb
54
+ # is loaded.
55
+ require 'rdl/switch.rb'
56
+ $__rdl_wrap_switch = RDL::Switch.new
57
+ $__rdl_contract_switch = RDL::Switch.new
58
+
59
+ require 'rdl/types/type.rb'
60
+ require 'rdl/types/annotated_arg.rb'
61
+ require 'rdl/types/bot.rb'
62
+ require 'rdl/types/dependent_arg.rb'
63
+ require 'rdl/types/dots_query.rb'
64
+ require 'rdl/types/finite_hash.rb'
65
+ require 'rdl/types/generic.rb'
66
+ require 'rdl/types/intersection.rb'
67
+ require 'rdl/types/lexer.rex.rb'
68
+ require 'rdl/types/method.rb'
69
+ require 'rdl/types/singleton.rb'
70
+ require 'rdl/types/nominal.rb'
71
+ require 'rdl/types/non_null.rb'
72
+ require 'rdl/types/optional.rb'
73
+ require 'rdl/types/parser.tab.rb'
74
+ require 'rdl/types/structural.rb'
75
+ require 'rdl/types/top.rb'
76
+ require 'rdl/types/tuple.rb'
77
+ require 'rdl/types/type_query.rb'
78
+ require 'rdl/types/union.rb'
79
+ require 'rdl/types/var.rb'
80
+ require 'rdl/types/vararg.rb'
81
+ require 'rdl/types/wild_query.rb'
82
+
83
+ require 'rdl/contracts/contract.rb'
84
+ require 'rdl/contracts/and.rb'
85
+ require 'rdl/contracts/flat.rb'
86
+ require 'rdl/contracts/or.rb'
87
+ require 'rdl/contracts/proc.rb'
88
+
89
+ require 'rdl/util.rb'
90
+ require 'rdl/wrap.rb'
91
+ require 'rdl/query.rb'
92
+ require 'rdl/typecheck.rb'
93
+ #require_relative 'rdl/stats.rb'
94
+
95
+ $__rdl_parser = RDL::Type::Parser.new
96
+
97
+ # Map from file names to [digest, cache] where 2nd elt maps
98
+ # :ast to the AST
99
+ # :line_defs maps linenumber to AST for def at that line
100
+ $__rdl_ruby_parser_cache = Hash.new
101
+
102
+ # Some generally useful types; not really a big deal to do this since
103
+ # NominalTypes are cached, but these names are shorter to type
104
+ $__rdl_nil_type = RDL::Type::NominalType.new NilClass # actually creates singleton type
105
+ $__rdl_top_type = RDL::Type::TopType.new
106
+ $__rdl_bot_type = RDL::Type::BotType.new
107
+ $__rdl_object_type = RDL::Type::NominalType.new Object
108
+ $__rdl_true_type = RDL::Type::NominalType.new TrueClass # actually creates singleton type
109
+ $__rdl_false_type = RDL::Type::NominalType.new FalseClass # also singleton type
110
+ $__rdl_bool_type = RDL::Type::UnionType.new($__rdl_true_type, $__rdl_false_type)
111
+ $__rdl_fixnum_type = RDL::Type::NominalType.new Fixnum
112
+ $__rdl_bignum_type = RDL::Type::NominalType.new Bignum
113
+ $__rdl_float_type = RDL::Type::NominalType.new Float
114
+ $__rdl_complex_type = RDL::Type::NominalType.new Complex
115
+ $__rdl_rational_type = RDL::Type::NominalType.new Rational
116
+ $__rdl_integer_type = RDL::Type::UnionType.new($__rdl_fixnum_type, $__rdl_bignum_type)
117
+ $__rdl_numeric_type = RDL::Type::NominalType.new Numeric
118
+ $__rdl_string_type = RDL::Type::NominalType.new String
119
+ $__rdl_array_type = RDL::Type::NominalType.new Array
120
+ $__rdl_hash_type = RDL::Type::NominalType.new Hash
121
+ $__rdl_symbol_type = RDL::Type::NominalType.new Symbol
122
+ $__rdl_range_type = RDL::Type::NominalType.new Range
123
+ $__rdl_regexp_type = RDL::Type::NominalType.new Regexp
124
+ $__rdl_standard_error_type = RDL::Type::NominalType.new StandardError
125
+
126
+ # Hash from special type names to their values
127
+ $__rdl_special_types = {'%any' => $__rdl_top_type,
128
+ '%bot' => $__rdl_bot_type,
129
+ '%bool' => $__rdl_bool_type}
@@ -0,0 +1,13 @@
1
+ if Rails.env.development? || Rails.env.test?
2
+ require 'rdl/boot'
3
+ require 'types/core'
4
+
5
+ dir = Rails::VERSION::STRING.split('.')[0] + ".x"
6
+ require_relative "../types/rails-#{dir}/_helpers.rb" # load type aliases first
7
+ Dir[File.dirname(__FILE__) + "/../types/rails-#{dir}/**/*.rb"].each { |f| require f }
8
+ elsif Rails.env.production?
9
+ require 'rdl_disable'
10
+ def (ActionController::Base).params_type(typs); end
11
+ else
12
+ raise RuntimeError, "Don't know what to do in Rails environment #{Rails.env}"
13
+ end
@@ -805,9 +805,6 @@ RUBY
805
805
  when :lvar # local variable
806
806
  error :undefined_local_or_method, [name], e unless env.has_key? name
807
807
  capture(scope, name, env[name].canonical) if scope[:outer_env] && (scope[:outer_env].has_key? name) && (not (scope[:outer_env].fixed? name))
808
- # if scope[:outer_env] && (scope[:outer_env].has_key? name) && (not (scope[:outer_env].fixed? name))
809
- # error :nonlocal_access, [name], e
810
- # end
811
808
  if scope[:captured] && scope[:captured].has_key?(name) then
812
809
  [env, scope[:captured][name]]
813
810
  else
@@ -1114,6 +1111,7 @@ RUBY
1114
1111
  # *always* included module's instance methods only
1115
1112
  # if included, those methods are added to instance_methods
1116
1113
  # if extended, those methods are added to singleton_methods
1114
+ # (except Kernel is special...)
1117
1115
  def self.lookup(scope, klass, name, e)
1118
1116
  if scope[:context_types]
1119
1117
  # return array of all matching types from context_types, if any
@@ -1121,7 +1119,11 @@ RUBY
1121
1119
  scope[:context_types].each { |ctk, ctm, ctt| ts << ctt if ctk.to_s == klass && ctm == name }
1122
1120
  return ts unless ts.empty?
1123
1121
  end
1124
- return scope[:context_types][klass][name] if scope[:context_types] && scope[:context_types][klass] && scope[:context_types][klass][name]
1122
+ if scope[:context_types]
1123
+ scope[:context_types].each { |k, m, t|
1124
+ return t if k == klass && m = name
1125
+ }
1126
+ end
1125
1127
  t = $__rdl_info.get_with_aliases(klass, name, :type)
1126
1128
  return t if t # simplest case, no need to walk inheritance hierarchy
1127
1129
  the_klass = RDL::Util.to_class(klass)
@@ -1141,7 +1143,10 @@ RUBY
1141
1143
  return tancestor if tancestor
1142
1144
  end
1143
1145
  if ancestor.instance_methods(false).member?(name)
1144
- klass = RDL::Util.remove_singleton_marker klass if RDL::Util.has_singleton_marker klass
1146
+ if RDL::Util.has_singleton_marker klass
1147
+ klass = RDL::Util.remove_singleton_marker klass
1148
+ klass = '(singleton) ' + klass
1149
+ end
1145
1150
  error :missing_ancestor_type, [ancestor, klass, name], e
1146
1151
  end
1147
1152
  }
@@ -1162,18 +1167,17 @@ type_error_messages = {
1162
1167
  inconsistent_var_type: "local variable `%s' has declared type on some paths but not all",
1163
1168
  inconsistent_var_type_type: "local variable `%s' declared with inconsistent types %s",
1164
1169
  no_each_type: "can't find `each' method with signature `() { (t1) -> t2 } -> t3' in class `%s'",
1165
- tuple_finite_hash_promote: "can't promote %s to %s",
1170
+ tuple_finite_hash_promote: "can't promote `%s' to `%s'",
1166
1171
  masgn_bad_rhs: "multiple assignment has right-hand side of type `%s' where tuple or array expected",
1167
1172
  masgn_num: "can't multiple-assign %d values to %d variables",
1168
1173
  masgn_bad_lhs: "no corresponding right-hand side elemnt for left-hand side assignee",
1169
- kw_not_allowed: "can't use %s in current scope",
1170
- kw_arg_not_allowed: "argument to %s not allowed in current scope",
1171
- arg_count_mismatch: "%s signature expects %d arguments, actual %s has %d arguments",
1172
- nonlocal_access: "variable %s from outer scope must have type declared with var_type",
1174
+ kw_not_allowed: "can't use `%s' in current scope",
1175
+ kw_arg_not_allowed: "argument to `%s' not allowed in current scope",
1176
+ arg_count_mismatch: "`%s' signature expects %d arguments, actual `%s' has %d arguments",
1173
1177
  no_block: "attempt to call yield in method not declared to take a block argument",
1174
1178
  block_block: "can't call yield on a block expecting another block argument",
1175
1179
  block_type_error: "argument type error for block\n%s",
1176
- missing_ancestor_type: "ancestor %s of %s has method %s but no type for it",
1180
+ missing_ancestor_type: "ancestor `%s' of `%s' has method `%s' but no type for it",
1177
1181
  type_cast_format: "type_cast must be called as `type_cast type-string' or `type_cast type-string, force: expr'",
1178
1182
  var_type_format: "var_type must be called as `var_type :var-name, type-string'",
1179
1183
  puts_type_format: "puts_type must be called as `puts_type e'",
@@ -61,10 +61,10 @@ module RDL::Type
61
61
  check_arg_preds(bind, preds) if preds.size > 0
62
62
  @args.each_with_index {|a,i| args[i] = block_wrap(slf, inst, a, bind, &args[i]) if a.is_a? MethodType }
63
63
  if @block then
64
- raise TypeError, "Expected method block of type {@block}, received no block." unless blk
64
+ next unless blk
65
65
  blk = block_wrap(slf, inst, @block, bind, &blk)
66
66
  elsif blk then
67
- raise TypeError, "Block passed to method expecting no block."
67
+ next
68
68
  end
69
69
  return [true, args, blk, bind]
70
70
  end
@@ -537,6 +537,7 @@ class Object
537
537
 
538
538
  # Type check all methods that had annotation `typecheck: sym' at type call
539
539
  def rdl_do_typecheck(sym)
540
+ return unless $__rdl_to_typecheck[sym]
540
541
  $__rdl_to_typecheck[sym].each { |klass, meth|
541
542
  RDL::Typecheck.typecheck(klass, meth)
542
543
  }
@@ -18,6 +18,7 @@ class Object
18
18
  def type_alias(*args); end
19
19
  def rdl_do_typecheck(*args); end
20
20
  def rdl_note_type(*args); end
21
+ def rdl_remove_type(*args); end
21
22
 
22
23
  def attr_accessor_type(*args)
23
24
  args.each_slice(2) { |name, typ| attr_accessor name }
@@ -35,7 +36,4 @@ class Object
35
36
  args.each_slice(2) { |name, typ| attr_writer name }
36
37
  nil
37
38
  end
38
-
39
-
40
-
41
39
  end
@@ -0,0 +1,32 @@
1
+ # :integer, :bigint, :float, :decimal, :numeric, :datetime, :time, :date, :binary, :boolean.
2
+ # null allowed
3
+
4
+ module RDL
5
+ class Rails
6
+
7
+ # [+ rails_type +] is a Rails column type (:string, :integer, etc)
8
+ # returns a String containing an RDL type
9
+ def self.column_to_rdl(rails_type)
10
+ case rails_type
11
+ when :string, :text, :binary
12
+ return 'String'
13
+ when :integer
14
+ return 'Fixnum'
15
+ when :float
16
+ return 'Float'
17
+ when :decimal
18
+ return 'BigDecimal'
19
+ when :boolean
20
+ return '%bool'
21
+ when :date
22
+ return 'Date'
23
+ when :time
24
+ return 'Time'
25
+ when :datetime
26
+ return 'DateTime'
27
+ else
28
+ raise RuntimeError, "Unrecoganized column type #{rails_type}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ module ActionController
2
+ module MimeResponds
3
+ type :respond_to, '(*(String or Symbol)) { (ActionController::MimeResponds::Collector) -> %any } -> Array<String> or String'
4
+
5
+ class Collector
6
+ Mime::EXTENSION_LOOKUP.each { |mime|
7
+ type :method_missing, "(#{mime[1].symbol.inspect}) { (ActionController::MimeResponds::Collector::VariantCollector) -> %any } -> %any"
8
+ }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ # TODO: This is all a bit of a hack. Right now, ActionControll::Parameters has its [] method set appropriately during the context
2
+ # of the next method by params_types. But that doesn't quite match what actually happens in Rails.
3
+
4
+ class ActionController::Base
5
+
6
+ # [+ typ_hash +] is a Hash<Symbol, String>, where the keys are the parameter names and the Strings are the corresponding types
7
+ # adds these parameters to the `params` hash in the immediately following controller method
8
+ def self.params_type(typs)
9
+ # TODO: Ick, this is ugly. Once it's obvious how to generalize this kind of reasoning to other cases, clean this up!
10
+ typs.each_pair { |param, param_type|
11
+ param_type = $__rdl_parser.scan_str "#T #{param_type}"
12
+ meth_type = $__rdl_parser.scan_str "(#{param.inspect}) -> #{param_type}" # given singleton symbol arg, get param's return type
13
+ $__rdl_deferred << [self, :context_types, [ActionController::Parameters, :[], meth_type], class_check: self]
14
+ }
15
+ end
16
+ end
17
+
18
+ module ActionController
19
+ module StrongParameters
20
+ type :params, '() -> ActionController::Parameters'
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ module ActionDispatch
2
+ module Routing
3
+ class RouteSet
4
+ post(:draw) { |ret|
5
+ # puts "Routes are: #{Rails.application.routes.named_routes.helper_names}"
6
+ true
7
+ }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ module ActiveRecord
2
+ module ModelSchema
3
+ module ClassMethods
4
+ post(:load_schema!) { |ret| # load_schema! doesn't return anything interesting
5
+ find_by_args = []
6
+
7
+ columns_hash.each { |name, col|
8
+ t = RDL::Rails.column_to_rdl(col.type)
9
+ if col.null
10
+ # may be null; show nullability in return type
11
+ type name, "() -> #{t} or nil" # getter
12
+ type "#{name}=", "(#{t}) -> #{t} or nil" # setter
13
+ type "write_attribute", "(:#{name}, #{t}) -> %bool"
14
+ type "update_attribute", "(:#{name}, #{t}) -> %bool"
15
+ type "update_column", "(:#{name}, #{t}) -> %bool"
16
+ find_by_args << "#{name}: ?#{t}"
17
+ else
18
+ # not null; can't truly check in type system but hint via the name
19
+ type name, "() -> !#{t}" # getter
20
+ type "#{name}=", "(!#{t}) -> !#{t}" # setter
21
+ type "write_attribute", "(:#{name}, !#{t}) -> %bool"
22
+ type "update_attribute", "(:#{name}, #{t}) -> %bool"
23
+ type "update_column", "(:#{name}, #{t}) -> %bool"
24
+ find_by_args << "#{name}: ?!#{t}"
25
+ end
26
+ }
27
+ hash_args = find_by_args.join(',')
28
+ type 'self.find_by', '(' + hash_args + ") -> #{self} or nil"
29
+ type 'self.find_by!', '(' + hash_args + ") -> #{self}"
30
+ type 'update', '(' + hash_args + ') -> %bool'
31
+ type 'update_columns', '(' + hash_args + ') -> %bool'
32
+ type 'attributes=', '(' + hash_args + ') -> %bool'
33
+
34
+ # If called with String arguments, can't check types as precisely
35
+ type 'write_attribute', '(String, %any) -> %bool'
36
+ type 'update_attribute', '(String, %any) -> %bool'
37
+ type 'update_column', '(String, %any) -> %bool'
38
+ true
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ class Fixnum
2
+ type :*, '(ActiveSupport::Duration) -> ActiveSupport::Duration'
3
+ end
@@ -4,8 +4,8 @@
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'rdl'
7
- s.version = '2.0.0.rc3'
8
- s.date = '2016-08-11'
7
+ s.version = '2.0.0.rc4'
8
+ s.date = '2016-08-13'
9
9
  s.summary = 'Ruby type and contract system'
10
10
  s.description = <<-EOF
11
11
  RDL is a gem that adds types and contracts to Ruby. RDL includes extensive
@@ -1,7 +1,7 @@
1
1
  require 'minitest/autorun'
2
2
  $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
3
  require 'rdl'
4
- require 'rdl_types'
4
+ require 'types/core'
5
5
 
6
6
  class TestLe < Minitest::Test
7
7
  include RDL::Type
@@ -10,7 +10,7 @@ require 'uri'
10
10
  require 'minitest/autorun'
11
11
  $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
12
12
  require 'rdl'
13
- require 'rdl_types.rb'
13
+ require 'types/core'
14
14
 
15
15
  class Dummy
16
16
  def self.each
@@ -264,4 +264,31 @@ class TestTypeContract < Minitest::Test
264
264
  assert_raises(TypeError) { p8.call(43, x: "foo", y: "foo") }
265
265
  assert_raises(TypeError) { p8.call(43, x: :foo, y: "foo", z: 44) }
266
266
  end
267
+
268
+ type '() { () -> nil } -> nil'
269
+ def _test_with_block
270
+ nil
271
+ end
272
+
273
+ type '() -> nil'
274
+ def _test_without_block
275
+ nil
276
+ end
277
+
278
+ type '() -> nil'
279
+ type '() { () -> nil } -> nil'
280
+ def _test_with_without_block
281
+ nil
282
+ end
283
+
284
+ def test_block
285
+ assert_nil(_test_with_block { nil })
286
+ assert_raises(TypeError) { _test_with_block }
287
+
288
+ assert_raises(TypeError) { _test_without_block { nil } }
289
+ assert_nil(_test_without_block)
290
+
291
+ assert_nil(_test_with_without_block)
292
+ assert_nil(_test_with_without_block { nil })
293
+ end
267
294
  end
@@ -1,7 +1,7 @@
1
1
  require 'minitest/autorun'
2
2
  $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
3
  require 'rdl'
4
- require 'rdl_types'
4
+ require 'types/core'
5
5
 
6
6
  class TestTypecheck < Minitest::Test
7
7
 
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.rc3
4
+ version: 2.0.0.rc4
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-08-11 00:00:00.000000000 Z
15
+ date: 2016-08-13 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: parser
@@ -112,6 +112,8 @@ files:
112
112
  - extras/type_tests/|.rb
113
113
  - gemfiles/Gemfile.travis
114
114
  - lib/rdl.rb
115
+ - lib/rdl/boot.rb
116
+ - lib/rdl/boot_rails.rb
115
117
  - lib/rdl/config.rb
116
118
  - lib/rdl/contracts/and.rb
117
119
  - lib/rdl/contracts/contract.rb
@@ -151,7 +153,6 @@ files:
151
153
  - lib/rdl/util.rb
152
154
  - lib/rdl/wrap.rb
153
155
  - lib/rdl_disable.rb
154
- - lib/rdl_types.rb
155
156
  - lib/types/core-ruby-2.x/_aliases.rb
156
157
  - lib/types/core-ruby-2.x/abbrev.rb
157
158
  - lib/types/core-ruby-2.x/array.rb
@@ -201,6 +202,12 @@ files:
201
202
  - lib/types/core-ruby-2.x/uri.rb
202
203
  - lib/types/core-ruby-2.x/yaml.rb
203
204
  - lib/types/core.rb
205
+ - lib/types/rails-5.x/_helpers.rb
206
+ - lib/types/rails-5.x/action_controller/mime_responds.rb
207
+ - lib/types/rails-5.x/action_controller/strong_parameters.rb
208
+ - lib/types/rails-5.x/action_dispatch/routing.rb
209
+ - lib/types/rails-5.x/active_record/model_schema.rb
210
+ - lib/types/rails-5.x/fixnum.rb
204
211
  - rdl.gemspec
205
212
  - test/disabled_test_coverage.rb
206
213
  - test/disabled_test_rdoc.rb
@@ -1 +0,0 @@
1
- require_relative "types/core.rb"