what_weve_got_here_is_an_error_to_communicate 0.0.1 → 0.0.2
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 +4 -4
- data/.rspec +1 -0
- data/Readme.md +9 -7
- data/experiments/formatting/other_resources +7 -0
- data/lib/error_to_communicate/at_exit.rb +15 -9
- data/lib/error_to_communicate/config.rb +55 -22
- data/lib/error_to_communicate/exception_info.rb +86 -31
- data/lib/error_to_communicate/format_terminal.rb +146 -0
- data/lib/error_to_communicate/heuristic/exception.rb +22 -0
- data/lib/error_to_communicate/heuristic/load_error.rb +57 -0
- data/lib/error_to_communicate/heuristic/no_method_error.rb +35 -0
- data/lib/error_to_communicate/heuristic/syntax_error.rb +55 -0
- data/lib/error_to_communicate/heuristic/wrong_number_of_arguments.rb +73 -0
- data/lib/error_to_communicate/heuristic.rb +54 -0
- data/lib/error_to_communicate/project.rb +50 -0
- data/lib/error_to_communicate/rspec_formatter.rb +8 -9
- data/lib/error_to_communicate/theme.rb +137 -0
- data/lib/error_to_communicate/version.rb +2 -2
- data/lib/error_to_communicate.rb +4 -2
- data/spec/acceptance/exception_spec.rb +2 -4
- data/spec/acceptance/load_error_spec.rb +23 -0
- data/spec/acceptance/name_error_spec.rb +46 -0
- data/spec/acceptance/no_methood_error_spec.rb +6 -8
- data/spec/acceptance/runtime_error_spec.rb +27 -0
- data/spec/acceptance/short_and_long_require_spec.rb +29 -0
- data/spec/acceptance/spec_helper.rb +4 -3
- data/spec/acceptance/syntax_error_spec.rb +32 -0
- data/spec/acceptance/{argument_error_spec.rb → wrong_number_of_arguments_spec.rb} +1 -1
- data/spec/config_spec.rb +120 -0
- data/spec/heuristic/exception_spec.rb +17 -0
- data/spec/heuristic/load_error_spec.rb +195 -0
- data/spec/heuristic/no_method_error_spec.rb +25 -0
- data/spec/heuristic/spec_helper.rb +33 -0
- data/spec/heuristic/wrong_number_of_arguments_spec.rb +115 -0
- data/spec/heuristic_spec.rb +76 -0
- data/spec/parsing_exception_info_spec.rb +212 -0
- data/spec/rspec_formatter_spec.rb +3 -1
- data/spec/spec_helper.rb +28 -1
- data/what_weve_got_here_is_an_error_to_communicate.gemspec +2 -2
- metadata +29 -19
- data/lib/error_to_communicate/format/terminal_helpers.rb +0 -97
- data/lib/error_to_communicate/format.rb +0 -132
- data/lib/error_to_communicate/parse/backtrace.rb +0 -34
- data/lib/error_to_communicate/parse/exception.rb +0 -21
- data/lib/error_to_communicate/parse/no_method_error.rb +0 -27
- data/lib/error_to_communicate/parse/registry.rb +0 -30
- data/lib/error_to_communicate/parse/wrong_number_of_arguments.rb +0 -35
- data/spec/parse/backtrace_spec.rb +0 -101
- data/spec/parse/exception_spec.rb +0 -14
- data/spec/parse/no_method_error_spec.rb +0 -23
- data/spec/parse/registered_parsers_spec.rb +0 -68
- data/spec/parse/spec_helper.rb +0 -23
- data/spec/parse/wrong_number_of_arguments_spec.rb +0 -77
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'error_to_communicate/exception_info'
|
2
|
-
require 'error_to_communicate/parse/backtrace'
|
3
|
-
|
4
|
-
module WhatWeveGotHereIsAnErrorToCommunicate
|
5
|
-
module Parse
|
6
|
-
module NoMethodError
|
7
|
-
def self.parse?(exception)
|
8
|
-
exception.kind_of? ::NoMethodError
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.parse(exception)
|
12
|
-
ExceptionInfo::NoMethodError.new(
|
13
|
-
exception: exception,
|
14
|
-
classname: exception.class.to_s,
|
15
|
-
explanation: exception.message[/^[^\(]*/].strip,
|
16
|
-
backtrace: Backtrace.parse(exception),
|
17
|
-
undefined_method_name: extract_method_name(exception.message),
|
18
|
-
)
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.extract_method_name(message)
|
22
|
-
words = message.split(/\s+/)
|
23
|
-
words[2][1...-1]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module WhatWeveGotHereIsAnErrorToCommunicate
|
2
|
-
module Parse
|
3
|
-
class Registry
|
4
|
-
def initialize(options)
|
5
|
-
@dont_parse = options.fetch :dont_parse
|
6
|
-
@parsers = options.fetch :parsers
|
7
|
-
end
|
8
|
-
|
9
|
-
def <<(parser)
|
10
|
-
@parsers << parser
|
11
|
-
self
|
12
|
-
end
|
13
|
-
|
14
|
-
def parser_for(exception)
|
15
|
-
return nil if @dont_parse.call exception
|
16
|
-
@parsers.find { |parser| parser.parse? exception }
|
17
|
-
end
|
18
|
-
|
19
|
-
def parse?(exception)
|
20
|
-
!!parser_for(exception)
|
21
|
-
end
|
22
|
-
|
23
|
-
def parse(exception)
|
24
|
-
parser = @parsers.find { |parser| parser.parse? exception }
|
25
|
-
return parser.parse exception if parser
|
26
|
-
raise ::ArgumentError.new, "No parser found for #{exception.inspect}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'error_to_communicate/exception_info'
|
2
|
-
require 'error_to_communicate/parse/backtrace'
|
3
|
-
|
4
|
-
module WhatWeveGotHereIsAnErrorToCommunicate
|
5
|
-
module Parse
|
6
|
-
module WrongNumberOfArguments
|
7
|
-
def self.parse?(exception)
|
8
|
-
exception.respond_to?(:message) && extract_from(exception)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.parse(exception)
|
12
|
-
num_received, num_expected = extract_from(exception)
|
13
|
-
ExceptionInfo::WrongNumberOfArguments.new(
|
14
|
-
exception: exception,
|
15
|
-
classname: exception.class.to_s,
|
16
|
-
explanation: 'Wrong number of arguments',
|
17
|
-
backtrace: Backtrace.parse(exception),
|
18
|
-
num_expected: num_expected,
|
19
|
-
num_received: num_received,
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def self.extract_from(exception)
|
26
|
-
case exception.message
|
27
|
-
when /^wrong number of arguments.*?\((\d+) for (\d+)\)$/ # MRI / JRuby
|
28
|
-
num_received, num_expected = $1.to_i, $2.to_i
|
29
|
-
when /^method '.*?': given (\d+).*? expected (\d+)$/ # RBX
|
30
|
-
num_received, num_expected = $1.to_i, $2.to_i
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,101 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'error_to_communicate/parse/backtrace'
|
3
|
-
|
4
|
-
RSpec.describe 'parsing an ArgumentError', parse: true do
|
5
|
-
let :exception do
|
6
|
-
FakeException.new backtrace: [
|
7
|
-
"file.rb:111:in `method1'",
|
8
|
-
"file.rb:222:in `method2'",
|
9
|
-
"file.rb:333:in `method3'"
|
10
|
-
]
|
11
|
-
end
|
12
|
-
|
13
|
-
def parse(exception)
|
14
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Parse::Backtrace.parse(exception)
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'records the linenum, and label of each backtrace location' do
|
18
|
-
locations = parse exception
|
19
|
-
expect(locations.map &:linenum).to eq [111, 222, 333]
|
20
|
-
expect(locations.map &:label).to eq %w[method1 method2 method3]
|
21
|
-
end
|
22
|
-
|
23
|
-
specify 'the predecessor is the parsed location from the previous index, or nil for the first' do
|
24
|
-
l1, l2, l3 = locations = parse(exception)
|
25
|
-
expect(locations.map &:pred).to eq [nil, l1, l2]
|
26
|
-
end
|
27
|
-
|
28
|
-
specify 'the successor is the parsed locations from the next index, or nil for the last' do
|
29
|
-
l1, l2, l3 = locations = parse(exception)
|
30
|
-
expect(locations.map &:succ).to eq [l2, l3, nil]
|
31
|
-
end
|
32
|
-
|
33
|
-
# it 'records the absolute filepath if it can find the file'
|
34
|
-
# it 'records the relative filepath if it can find the file'
|
35
|
-
# it 'records the relative filepath if it cannot fild the file'
|
36
|
-
|
37
|
-
def assert_parses_line(line, assertions)
|
38
|
-
parsed = WhatWeveGotHereIsAnErrorToCommunicate::Parse::Backtrace.parse_backtrace_line(line)
|
39
|
-
assertions.each do |method_name, expected|
|
40
|
-
actual = parsed.__send__ method_name
|
41
|
-
expect(actual).to eq expected
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'records the path whether its absolute or relative' do
|
46
|
-
assert_parses_line "file.rb:111:in `method1'", path: "file.rb"
|
47
|
-
assert_parses_line "/file.rb:111:in `method1'", path: "/file.rb"
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'does not get confused by numbers in directories, filenames, or method names' do
|
51
|
-
line = "/a1/b2/c3123/file123.rb:111:in `method1'"
|
52
|
-
assert_parses_line line, path: "/a1/b2/c3123/file123.rb"
|
53
|
-
assert_parses_line line, linenum: 111
|
54
|
-
assert_parses_line line, label: "method1"
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'random ass colons in the middle of like files and directories and shit' do
|
58
|
-
# $ mkdir 'a:b'
|
59
|
-
# $ echo 'begin; define_method("a:b") { |arg| }; send "a:b"; rescue Exception; p $!.backtrace; end' > 'a:b/c:d.rb'
|
60
|
-
|
61
|
-
# $ chruby-exec 2.2 -- ruby -v
|
62
|
-
# > ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin13]
|
63
|
-
#
|
64
|
-
# $ chruby-exec 2.2 -- ruby 'a:b/c:d.rb'
|
65
|
-
# > ["a:b/c:d.rb:1:in `block in <main>'", "a:b/c:d.rb:1:in `<main>'"]
|
66
|
-
it 'does not get confused with MRI style results' do
|
67
|
-
line = "a:b/c:d.rb:1:in `block in <main>'"
|
68
|
-
assert_parses_line line, path: "a:b/c:d.rb"
|
69
|
-
assert_parses_line line, linenum: 1
|
70
|
-
assert_parses_line line, label: "block in <main>"
|
71
|
-
end
|
72
|
-
|
73
|
-
# $ chruby-exec rbx -- ruby -v
|
74
|
-
# > rubinius 2.5.0 (2.1.0 50777f41 2015-01-17 3.5.0 JI) [x86_64-darwin14.1.0]
|
75
|
-
#
|
76
|
-
# $ chruby-exec rbx -- ruby 'a:b/c:d.rb'
|
77
|
-
# > ["a:b/c:d.rb:1:in `__script__'",
|
78
|
-
# "kernel/delta/code_loader.rb:66:in `load_script'",
|
79
|
-
# "kernel/delta/code_loader.rb:152:in `load_script'",
|
80
|
-
# "kernel/loader.rb:645:in `script'",
|
81
|
-
# "kernel/loader.rb:799:in `main'"]
|
82
|
-
it 'does not get confused with RBX style results' do
|
83
|
-
line = "a:b/c:d.rb:1:in `__script__'"
|
84
|
-
assert_parses_line line, path: "a:b/c:d.rb"
|
85
|
-
assert_parses_line line, linenum: 1
|
86
|
-
assert_parses_line line, label: "__script__"
|
87
|
-
end
|
88
|
-
|
89
|
-
# $ chruby-exec jruby -- ruby -v
|
90
|
-
# > jruby 1.7.16 (1.9.3p392) 2014-09-25 575b395 on Java HotSpot(TM) 64-Bit Server VM 1.7.0_51-b13 +jit [darwin-x86_64]
|
91
|
-
#
|
92
|
-
# $ chruby-exec jruby -- ruby 'a:b/c:d.rb'
|
93
|
-
# > ["a:b/c:d.rb:1:in `(root)'"]
|
94
|
-
it 'does not get confused by Jruby style results' do
|
95
|
-
line = "a:b/c:d.rb:1:in `(root)'"
|
96
|
-
assert_parses_line line, path: "a:b/c:d.rb"
|
97
|
-
assert_parses_line line, linenum: 1
|
98
|
-
assert_parses_line line, label: "(root)"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'parse/spec_helper'
|
2
|
-
require 'error_to_communicate/parse/exception'
|
3
|
-
|
4
|
-
RSpec.describe 'parsing an Exception', parse: true do
|
5
|
-
def parse(exception)
|
6
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Parse::Exception.parse(exception)
|
7
|
-
end
|
8
|
-
|
9
|
-
it_behaves_like 'an exception parser', sample_message: 'literally anything'
|
10
|
-
|
11
|
-
# Going to wait on implementing these as they may not be correct,
|
12
|
-
# e.g. anyone can raise an argument error for any reason.
|
13
|
-
it 'extracts the name of the method that was called'
|
14
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'parse/spec_helper'
|
2
|
-
require 'error_to_communicate/parse/no_method_error'
|
3
|
-
|
4
|
-
RSpec.describe 'parsing a NoMethodError', parse: true do
|
5
|
-
def error_class
|
6
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Parse::NoMethodError
|
7
|
-
end
|
8
|
-
|
9
|
-
def parse(exception)
|
10
|
-
error_class.parse(exception)
|
11
|
-
end
|
12
|
-
|
13
|
-
it_behaves_like 'an exception parser', sample_message: "undefined method `<' for nil:NilClass"
|
14
|
-
|
15
|
-
def extracts_method_name!(expected, message)
|
16
|
-
actual = error_class.extract_method_name(message)
|
17
|
-
expect(actual).to eq expected
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'extracts the name of the method that was called' do
|
21
|
-
extracts_method_name! '<', "undefined method `<' for nil:NilClass"
|
22
|
-
end
|
23
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'error_to_communicate/config'
|
2
|
-
|
3
|
-
RSpec.describe 'registered parsers', parse: true do
|
4
|
-
p = WhatWeveGotHereIsAnErrorToCommunicate::Parse
|
5
|
-
|
6
|
-
def capture
|
7
|
-
yield
|
8
|
-
raise 'NO EXCEPTION WAS RAISED!'
|
9
|
-
rescue Exception
|
10
|
-
return $!
|
11
|
-
end
|
12
|
-
|
13
|
-
describe 'selected parsers' do
|
14
|
-
def parser_for(exception)
|
15
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Config
|
16
|
-
.new.registry.parser_for(exception)
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'doesn\'t parse nil' do
|
20
|
-
expect(parser_for nil).to eq nil
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'doesn\'t parse a SystemExit' do
|
24
|
-
err = capture { exit }
|
25
|
-
expect(parser_for err).to eq nil
|
26
|
-
|
27
|
-
err = capture { exit 1 }
|
28
|
-
expect(parser_for err).to eq nil
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'parses wrong number of arguments' do
|
32
|
-
err = capture { lambda { }.call :arg }
|
33
|
-
expect(parser_for err).to eq p::WrongNumberOfArguments
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'parses NoMethodErrors' do
|
37
|
-
err = capture { sdfsdfsdf() }
|
38
|
-
expect(parser_for err).to eq p::NoMethodError
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'lets ArgumentErrors that are not wrong number of arguments fall through', t:true do
|
42
|
-
err = capture { raise ArgumentError, "zomg" }
|
43
|
-
expect(parser_for err).to eq p::Exception
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'parses Exception' do
|
47
|
-
err = capture { raise Exception, "wat" }
|
48
|
-
expect(parser_for err).to eq p::Exception
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe 'config.parse' do
|
53
|
-
def parse(exception)
|
54
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Config
|
55
|
-
.new.parse(exception)
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'parses the exception if anything is willing to do it' do
|
59
|
-
exception = capture { sdfsdfsdf() }
|
60
|
-
exception_info = parse exception
|
61
|
-
expect(exception_info.exception).to equal exception
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'raises an ArgumentError if there are no parsers for this exception' do
|
65
|
-
expect { parse "not an error" }.to raise_error ArgumentError, /"not an error"/
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/spec/parse/spec_helper.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.shared_examples 'an exception parser' do |attributes|
|
4
|
-
let(:message) { attributes.fetch :sample_message }
|
5
|
-
let(:explanation) { attributes.fetch :sample_explanation, message }
|
6
|
-
|
7
|
-
let :exception do
|
8
|
-
FakeException.new message: message,
|
9
|
-
backtrace: ["/Users/someone/a/b/c.rb:123:in `some_method_name'"]
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'records the exception, class name, and explanation comes from the message' do
|
13
|
-
info = parse exception
|
14
|
-
expect(info.exception ).to equal exception
|
15
|
-
expect(info.classname ).to eq 'FakeException'
|
16
|
-
expect(info.explanation).to eq explanation
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'records the backtrace locations' do
|
20
|
-
info = parse exception
|
21
|
-
expect(info.backtrace.map &:linenum).to eq [123]
|
22
|
-
end
|
23
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'parse/spec_helper'
|
3
|
-
require 'error_to_communicate/parse/wrong_number_of_arguments'
|
4
|
-
|
5
|
-
RSpec.describe 'parsing wrong number of arguments', parse: true do
|
6
|
-
def parse(exception)
|
7
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Parse::WrongNumberOfArguments.parse(exception)
|
8
|
-
end
|
9
|
-
|
10
|
-
it_behaves_like 'an exception parser',
|
11
|
-
sample_message: "wrong number of arguments (1 for 0) (ArgumentError)",
|
12
|
-
sample_explanation: "Wrong number of arguments"
|
13
|
-
|
14
|
-
describe 'parse?' do
|
15
|
-
def will_parse?(exception)
|
16
|
-
WhatWeveGotHereIsAnErrorToCommunicate::Parse::WrongNumberOfArguments.parse?(exception)
|
17
|
-
end
|
18
|
-
|
19
|
-
def will_parse!(exception)
|
20
|
-
expect(will_parse? exception).to be_truthy
|
21
|
-
end
|
22
|
-
|
23
|
-
def wont_parse!(exception)
|
24
|
-
expect(will_parse? exception).to be_falsy
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'is true when given an MRI style wrong number of arguments message' do
|
28
|
-
will_parse! ArgumentError.new "wrong number of arguments (1 for 0)"
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'is true when given an RBX style wrong number of arguments message' do
|
32
|
-
will_parse! ArgumentError.new "method 'a': given 1, expected 0"
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'is true when given an JRuby style wrong number of arguments message' do
|
36
|
-
will_parse! ArgumentError.new "wrong number of arguments calling `a` (1 for 0)"
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'is true when given an MRI style wrong number of arguments message' do
|
40
|
-
will_parse! ArgumentError.new "wrong number of arguments (1 for 0)"
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'is false for ArgumentErrors that are not "wrong number of arguments"' do
|
44
|
-
wont_parse! ArgumentError.new "Some other kind of ArgumentError"
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'is false when the message is contained within some other message (not overeager)' do
|
48
|
-
wont_parse! RSpec::Expectations::ExpectationNotMetError.new(<<-MESSAGE)
|
49
|
-
expected: "wrong number of arguments (1 for 0) (ArgumentError)"
|
50
|
-
got: "Wrong number of arguments"
|
51
|
-
|
52
|
-
(compared using ==)
|
53
|
-
MESSAGE
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe 'parse' do
|
58
|
-
let(:mri_message) { "wrong number of arguments (1 for 0)" }
|
59
|
-
let(:mri_parsed) { parse FakeException.new(message: mri_message) }
|
60
|
-
|
61
|
-
let(:rbx_message) { "method 'a': given 1, expected 0" }
|
62
|
-
let(:rbx_parsed) { parse FakeException.new(message: rbx_message) }
|
63
|
-
|
64
|
-
let(:jruby_message) { "wrong number of arguments calling `a` (1 for 0)" }
|
65
|
-
let(:jruby_parsed) { parse FakeException.new(message: "wrong number of arguments calling `a` (1 for 0)") }
|
66
|
-
|
67
|
-
it 'extracts the number of arguments that were passed' do
|
68
|
-
expect(rbx_parsed.num_expected).to eq 0
|
69
|
-
expect(mri_parsed.num_expected).to eq 0
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'extracts the number of arguments that were received' do
|
73
|
-
expect(rbx_parsed.num_received).to eq 1
|
74
|
-
expect(mri_parsed.num_received).to eq 1
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|