justified 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Petr Chalupa <git@pitr.ch>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ require 'justified'
2
+
3
+ class StandardError
4
+ include Justified::Error
5
+ end
6
+
7
+
data/lib/justified.rb ADDED
@@ -0,0 +1,74 @@
1
+ module Justified
2
+ SKIP_STR = ' ... skipped %s lines'
3
+ CAUSED_STR = 'caused by:'
4
+
5
+ module Error
6
+ def initialize(message = nil, cause = $!)
7
+ super(message)
8
+ set_cause cause
9
+ @backtrace = nil
10
+ end
11
+
12
+ # Set cause of the exception
13
+ # @param [nil, Exception] exception
14
+ def cause=(exception)
15
+ set_cause exception
16
+ set_backtrace
17
+ end
18
+
19
+ # @return [Exception] cause of the exception
20
+ def cause
21
+ @cause
22
+ end
23
+
24
+ def set_backtrace(backtrace = nil)
25
+ @backtrace ||= backtrace
26
+ backtrace ||= @backtrace
27
+
28
+ if backtrace
29
+ unless cause
30
+ super backtrace
31
+ else
32
+ cause_backtrace, rest = split_cause_backtrace
33
+ same_line_count = calculate_same_line_count backtrace, cause_backtrace
34
+ cause_backtrace_striped = cause_backtrace[0..-(same_line_count+1)]
35
+
36
+ super backtrace +
37
+ ["#{CAUSED_STR} (#{cause.class}) #{cause.message}"] +
38
+ cause_backtrace_striped +
39
+ [SKIP_STR % same_line_count] +
40
+ recalculate_rest(rest, same_line_count)
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def set_cause(cause)
48
+ cause.nil? or exception.kind_of? Exception or
49
+ raise ArgumentError, 'cause must be kind of Exception'
50
+ @cause = cause
51
+ end
52
+
53
+ def split_cause_backtrace
54
+ _, cause_index = cause.backtrace.each_with_index.find { |line, _| line =~ /^#{CAUSED_STR}/ }
55
+ if cause_index
56
+ [cause.backtrace[0...cause_index], cause.backtrace[cause_index..-1]]
57
+ else
58
+ [cause.backtrace, []]
59
+ end
60
+ end
61
+
62
+ def recalculate_rest(rest, same_line_count)
63
+ rest.map do |line|
64
+ line.gsub(/^#{SKIP_STR % '(\d+)'}$/) do
65
+ SKIP_STR % ($1.to_i - same_line_count)
66
+ end
67
+ end
68
+ end
69
+
70
+ def calculate_same_line_count(backtrace, cause_backtrace)
71
+ backtrace.reverse.zip(cause_backtrace.reverse).select { |a, b| a == b }.size
72
+ end
73
+ end
74
+ end
data/spec/justified.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'pp'
4
+ require 'justified/standard_error'
5
+
6
+ class AnError < StandardError
7
+ end
8
+
9
+ class Test
10
+ def bad_code
11
+ raise AnError, 'bad'
12
+ end
13
+
14
+ def handle_error
15
+ raise AnError, 'something'
16
+ end
17
+
18
+ def something
19
+ bad_code
20
+ rescue
21
+ handle_error
22
+ end
23
+
24
+ def do_something
25
+ something
26
+ end
27
+ end
28
+
29
+
30
+ describe 'justified' do
31
+ let :error do
32
+ Test.new.do_something rescue $!
33
+ end
34
+
35
+ describe 'normal raise' do
36
+ it { error.message.must_equal 'something' }
37
+ it { error.cause.message.must_equal 'bad' }
38
+ it { error.backtrace.must_include 'caused by: (AnError) bad' }
39
+ it do
40
+ assert error.backtrace.any? { |l| l =~ %r"/justified/spec/justified\.rb:\d+:in `bad_code'" }
41
+ end
42
+ end
43
+
44
+ describe 'erasing cause' do
45
+ let :error2 do
46
+ error.tap { |e| e.cause = nil }
47
+ end
48
+
49
+ it { error2.message.must_equal 'something' }
50
+ it { error2.cause.must_be_nil }
51
+ it { error2.backtrace.wont_include 'caused by: (AnError) bad' }
52
+ it do
53
+ refute error2.backtrace.
54
+ any? { |l| l =~ %r"/justified/spec/justified\.rb:15:in `bad_code'" }
55
+ end
56
+ end
57
+
58
+ describe 'set different cause' do
59
+ let :error2 do
60
+ cause = raise('other') rescue $!
61
+ error.tap { |e| e.cause = cause }
62
+ end
63
+
64
+ it { error2.message.must_equal 'something' }
65
+ it { error2.cause.message.must_equal 'other' }
66
+ it { error2.backtrace.must_include 'caused by: (RuntimeError) other' }
67
+ it do
68
+ assert error2.backtrace.any? do |l|
69
+ l =~ %r"/justified/spec/justified\.rb:\d+:in `block \(\d levels\)'"
70
+ end
71
+ end
72
+ end
73
+
74
+ describe 'manual creation' do
75
+ let :error do
76
+ cause = raise('other') rescue $!
77
+ error = AnError.new 'something'
78
+ error.cause = cause
79
+ raise(error) rescue $!
80
+ end
81
+
82
+ it { error.message.must_equal 'something' }
83
+ it { error.cause.message.must_equal 'other' }
84
+ it { error.backtrace.must_include 'caused by: (RuntimeError) other' }
85
+ it do
86
+ assert error.backtrace.any? do |l|
87
+ l =~ %r"/justified/spec/justified\.rb:\d+:in `block \(\d levels\)'"
88
+ end
89
+ end
90
+ end
91
+
92
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: justified
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Petr Chalupa
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pry
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: yard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: redcarpet
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: github-markup
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: ! ' Provides causes for exceptions.
95
+
96
+ '
97
+ email: git@pitr.ch
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files:
101
+ - MIT-LICENSE
102
+ files:
103
+ - lib/justified/standard_error.rb
104
+ - lib/justified.rb
105
+ - MIT-LICENSE
106
+ - spec/justified.rb
107
+ homepage: https://github.com/pitr-ch/justified
108
+ licenses: []
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 1.8.23
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Exception causes
131
+ test_files:
132
+ - spec/justified.rb
133
+ has_rdoc: