rdl 2.0.0.rc3 → 2.0.0.rc4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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"