You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.7 KiB
103 lines
3.7 KiB
From 726e28c473b8d4453b4485922a2c52e9511bfc42 Mon Sep 17 00:00:00 2001
|
|
From: Chris Seaton <chris@chrisseaton.com>
|
|
Date: Fri, 10 Nov 2017 17:20:38 +0000
|
|
Subject: [PATCH 1/5] Don't use exceptions for control flow
|
|
|
|
---
|
|
lib/contracts/call_with.rb | 22 +++++++++++++--------
|
|
lib/contracts/method_handler.rb | 34 +++++++++++++--------------------
|
|
2 files changed, 27 insertions(+), 29 deletions(-)
|
|
|
|
diff --git a/lib/contracts/call_with.rb b/lib/contracts/call_with.rb
|
|
index c8a8b62..2735d1e 100644
|
|
--- a/lib/contracts/call_with.rb
|
|
+++ b/lib/contracts/call_with.rb
|
|
@@ -1,6 +1,10 @@
|
|
module Contracts
|
|
module CallWith
|
|
def call_with(this, *args, &blk)
|
|
+ call_with_inner(false, this, *args, &blk)
|
|
+ end
|
|
+
|
|
+ def call_with_inner(returns, this, *args, &blk)
|
|
args << blk if blk
|
|
|
|
# Explicitly append blk=nil if nil != Proc contract violation anticipated
|
|
@@ -16,14 +20,16 @@ module Contracts
|
|
validator = @args_validators[i]
|
|
|
|
unless validator && validator[arg]
|
|
- return unless Contract.failure_callback(:arg => arg,
|
|
- :contract => contract,
|
|
- :class => klass,
|
|
- :method => method,
|
|
- :contracts => self,
|
|
- :arg_pos => i+1,
|
|
- :total_args => args.size,
|
|
- :return_value => false)
|
|
+ data = {:arg => arg,
|
|
+ :contract => contract,
|
|
+ :class => klass,
|
|
+ :method => method,
|
|
+ :contracts => self,
|
|
+ :arg_pos => i+1,
|
|
+ :total_args => args.size,
|
|
+ :return_value => false}
|
|
+ return ParamContractError.new("as return value", data) if returns
|
|
+ return unless Contract.failure_callback(data)
|
|
end
|
|
|
|
if contract.is_a?(Contracts::Func) && blk && !nil_block_appended
|
|
diff --git a/lib/contracts/method_handler.rb b/lib/contracts/method_handler.rb
|
|
index ee16b6b..fe301cd 100644
|
|
--- a/lib/contracts/method_handler.rb
|
|
+++ b/lib/contracts/method_handler.rb
|
|
@@ -125,31 +125,23 @@ module Contracts
|
|
# function. Otherwise we return the result.
|
|
# If we run out of functions, we raise the last error, but
|
|
# convert it to_contract_error.
|
|
- success = false
|
|
- i = 0
|
|
- result = nil
|
|
+
|
|
expected_error = decorated_methods[0].failure_exception
|
|
+ last_error = nil
|
|
|
|
- until success
|
|
- decorated_method = decorated_methods[i]
|
|
- i += 1
|
|
- begin
|
|
- success = true
|
|
- result = decorated_method.call_with(self, *args, &blk)
|
|
- rescue expected_error => error
|
|
- success = false
|
|
- unless decorated_methods[i]
|
|
- begin
|
|
- ::Contract.failure_callback(error.data, false)
|
|
- rescue expected_error => final_error
|
|
- raise final_error.to_contract_error
|
|
- end
|
|
- end
|
|
- end
|
|
+ decorated_methods.each do |decorated_method|
|
|
+ result = decorated_method.call_with_inner(true, self, *args, &blk)
|
|
+ return result unless result.is_a?(ParamContractError)
|
|
+ last_error = result
|
|
end
|
|
|
|
- # Return the result of successfully called method
|
|
- result
|
|
+ begin
|
|
+ if ::Contract.failure_callback(last_error.data, false)
|
|
+ decorated_methods.last.call_with_inner(false, self, *args, &blk)
|
|
+ end
|
|
+ rescue expected_error => final_error
|
|
+ raise final_error.to_contract_error
|
|
+ end
|
|
end
|
|
end
|
|
|
|
--
|
|
2.29.2
|
|
|