lib/contracts/builtin_contracts.rb in contracts-lite-0.14.0 vs lib/contracts/builtin_contracts.rb in contracts-lite-0.15.0

- old
+ new

@@ -1,9 +1,5 @@ -require "contracts/formatters" -require "set" - -# rdoc # This module contains all the builtin contracts. # If you want to use them, first: # # import Contracts # @@ -20,60 +16,60 @@ # That says that the +add+ function takes two numbers and returns a number. module Contracts module Builtin # Check that an argument is +Numeric+. class Num - def self.valid? val + def self.valid?(val) val.is_a? Numeric end end # Check that an argument is a positive number. class Pos - def self.valid? val + def self.valid?(val) val && val.is_a?(Numeric) && val > 0 end end # Check that an argument is a negative number. class Neg - def self.valid? val + def self.valid?(val) val && val.is_a?(Numeric) && val < 0 end end # Check that an argument is an +Integer+. class Int - def self.valid? val + def self.valid?(val) val && val.is_a?(Integer) end end # Check that an argument is a natural number (includes zero). class Nat - def self.valid? val + def self.valid?(val) val && val.is_a?(Integer) && val >= 0 end end # Check that an argument is a positive natural number (excludes zero). class NatPos - def self.valid? val + def self.valid?(val) val && val.is_a?(Integer) && val > 0 end end # Passes for any argument. class Any - def self.valid? val + def self.valid?(val) true end end # Fails for any argument. class None - def self.valid? val + def self.valid?(val) false end end # Use this when you are writing your own contract classes. @@ -89,29 +85,36 @@ def self.[](*vals) new(*vals) end end + class EnumInspector + include ::Contracts::Formatters + def self.inspect(vals, last_join_word) + vals[0, vals.size-1].map do |x| + InspectWrapper.create(x) + end.join(", ") + " #{last_join_word} " + InspectWrapper.create(vals[-1]).to_s + end + end + # Takes a variable number of contracts. # The contract passes if any of the contracts pass. # Example: <tt>Or[Fixnum, Float]</tt> class Or < CallableClass def initialize(*vals) @vals = vals end def valid?(val) @vals.any? do |contract| - res, _ = Contract.valid?(val, contract) + res, = Contract.valid?(val, contract) res end end def to_s - @vals[0, @vals.size-1].map do |x| - InspectWrapper.create(x) - end.join(", ") + " or " + InspectWrapper.create(@vals[-1]).to_s + EnumInspector.inspect(@vals, "or") end end # Takes a variable number of contracts. # The contract passes if exactly one of those contracts pass. @@ -121,20 +124,18 @@ @vals = vals end def valid?(val) results = @vals.map do |contract| - res, _ = Contract.valid?(val, contract) + res, = Contract.valid?(val, contract) res end results.count(true) == 1 end def to_s - @vals[0, @vals.size-1].map do |x| - InspectWrapper.create(x) - end.join(", ") + " xor " + InspectWrapper.create(@vals[-1]).to_s + EnumInspector.inspect(@vals, "xor") end end # Takes a variable number of contracts. # The contract passes if all contracts pass. @@ -144,19 +145,17 @@ @vals = vals end def valid?(val) @vals.all? do |contract| - res, _ = Contract.valid?(val, contract) + res, = Contract.valid?(val, contract) res end end def to_s - @vals[0, @vals.size-1].map do |x| - InspectWrapper.create(x) - end.join(", ") + " and " + InspectWrapper.create(@vals[-1]).to_s + EnumInspector.inspect(@vals, "and") end end # Takes a variable number of method names as symbols. # The contract passes if the argument responds to all @@ -255,11 +254,11 @@ @vals = vals end def valid?(val) @vals.all? do |contract| - res, _ = Contract.valid?(val, contract) + res, = Contract.valid?(val, contract) !res end end def to_s @@ -280,11 +279,11 @@ end def valid?(vals) return false unless vals.is_a?(@collection_class) vals.all? do |val| - res, _ = Contract.valid?(val, @contract) + res, = Contract.valid?(val, @contract) res end end def to_s @@ -300,11 +299,11 @@ def new(contract) @before_new && @before_new.call CollectionOf.new(@collection_class, contract) end - alias_method :[], :new + alias [] new end end # Takes a contract. The related argument must be an array. # Checks the contract against every element of the array. @@ -319,24 +318,32 @@ SetOf = CollectionOf::Factory.new(Set) # Used for <tt>*args</tt> (variadic functions). Takes a contract # and uses it to validate every element passed in # through <tt>*args</tt>. - # Example: <tt>Args[Or[String, Num]]</tt> - class Args < CallableClass + # Example: <tt>SplatArgs[Or[String, Num]]</tt> + class SplatArgs < CallableClass attr_reader :contract def initialize(contract) @contract = contract end def to_s - "Args[#{@contract}]" + "SplatArgs[#{@contract}]" end end + # for compatibility + class Args < SplatArgs + def initialize(contract) + puts "DEPRECATION WARNING: \nContract::Args was renamed to Contract::SplatArgs, please update your before the next major version" + @contract = contract + end + end + class Bool - def self.valid? val + def self.valid?(val) val.is_a?(TrueClass) || val.is_a?(FalseClass) end end # Use this to specify a Range object of a particular datatype. @@ -359,11 +366,11 @@ # Use this to specify the Hash characteristics. Takes two contracts, # one for hash keys and one for hash values. # Example: <tt>HashOf[Symbol, String]</tt> class HashOf < CallableClass - INVALID_KEY_VALUE_PAIR = "You should provide only one key-value pair to HashOf contract" + INVALID_KEY_VALUE_PAIR = "You should provide only one key-value pair to HashOf contract".freeze def initialize(key, value = nil) if value @key = key @value = value @@ -387,11 +394,11 @@ end private def validate_hash(hash) - fail ArgumentError, INVALID_KEY_VALUE_PAIR unless hash.count == 1 + raise ArgumentError, INVALID_KEY_VALUE_PAIR unless hash.count == 1 end end # Use this to specify the Hash characteristics. This contracts fails # if there are any extra keys that don't have contracts on them. @@ -466,11 +473,11 @@ # Use this for specifying optional keyword argument # Example: <tt>Optional[Num]</tt> class Optional < CallableClass UNABLE_TO_USE_OUTSIDE_OF_OPT_HASH = - "Unable to use Optional contract outside of KeywordArgs contract" + "Unable to use Optional contract outside of KeywordArgs contract".freeze def self._valid?(hash, key, contract) return Contract.valid?(hash[key], contract) unless contract.is_a?(Optional) contract.within_opt_hash! !hash.key?(key) || Contract.valid?(hash[key], contract) @@ -503,10 +510,10 @@ attr_reader :contract, :within_opt_hash def ensure_within_opt_hash return if within_opt_hash - fail ArgumentError, UNABLE_TO_USE_OUTSIDE_OF_OPT_HASH + raise ArgumentError, UNABLE_TO_USE_OUTSIDE_OF_OPT_HASH end def formatted_contract Formatters::InspectWrapper.create(contract) end