what_weve_got_here_is_an_error_to_communicate 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Readme.md +9 -7
  4. data/experiments/formatting/other_resources +7 -0
  5. data/lib/error_to_communicate/at_exit.rb +15 -9
  6. data/lib/error_to_communicate/config.rb +55 -22
  7. data/lib/error_to_communicate/exception_info.rb +86 -31
  8. data/lib/error_to_communicate/format_terminal.rb +146 -0
  9. data/lib/error_to_communicate/heuristic/exception.rb +22 -0
  10. data/lib/error_to_communicate/heuristic/load_error.rb +57 -0
  11. data/lib/error_to_communicate/heuristic/no_method_error.rb +35 -0
  12. data/lib/error_to_communicate/heuristic/syntax_error.rb +55 -0
  13. data/lib/error_to_communicate/heuristic/wrong_number_of_arguments.rb +73 -0
  14. data/lib/error_to_communicate/heuristic.rb +54 -0
  15. data/lib/error_to_communicate/project.rb +50 -0
  16. data/lib/error_to_communicate/rspec_formatter.rb +8 -9
  17. data/lib/error_to_communicate/theme.rb +137 -0
  18. data/lib/error_to_communicate/version.rb +2 -2
  19. data/lib/error_to_communicate.rb +4 -2
  20. data/spec/acceptance/exception_spec.rb +2 -4
  21. data/spec/acceptance/load_error_spec.rb +23 -0
  22. data/spec/acceptance/name_error_spec.rb +46 -0
  23. data/spec/acceptance/no_methood_error_spec.rb +6 -8
  24. data/spec/acceptance/runtime_error_spec.rb +27 -0
  25. data/spec/acceptance/short_and_long_require_spec.rb +29 -0
  26. data/spec/acceptance/spec_helper.rb +4 -3
  27. data/spec/acceptance/syntax_error_spec.rb +32 -0
  28. data/spec/acceptance/{argument_error_spec.rb → wrong_number_of_arguments_spec.rb} +1 -1
  29. data/spec/config_spec.rb +120 -0
  30. data/spec/heuristic/exception_spec.rb +17 -0
  31. data/spec/heuristic/load_error_spec.rb +195 -0
  32. data/spec/heuristic/no_method_error_spec.rb +25 -0
  33. data/spec/heuristic/spec_helper.rb +33 -0
  34. data/spec/heuristic/wrong_number_of_arguments_spec.rb +115 -0
  35. data/spec/heuristic_spec.rb +76 -0
  36. data/spec/parsing_exception_info_spec.rb +212 -0
  37. data/spec/rspec_formatter_spec.rb +3 -1
  38. data/spec/spec_helper.rb +28 -1
  39. data/what_weve_got_here_is_an_error_to_communicate.gemspec +2 -2
  40. metadata +29 -19
  41. data/lib/error_to_communicate/format/terminal_helpers.rb +0 -97
  42. data/lib/error_to_communicate/format.rb +0 -132
  43. data/lib/error_to_communicate/parse/backtrace.rb +0 -34
  44. data/lib/error_to_communicate/parse/exception.rb +0 -21
  45. data/lib/error_to_communicate/parse/no_method_error.rb +0 -27
  46. data/lib/error_to_communicate/parse/registry.rb +0 -30
  47. data/lib/error_to_communicate/parse/wrong_number_of_arguments.rb +0 -35
  48. data/spec/parse/backtrace_spec.rb +0 -101
  49. data/spec/parse/exception_spec.rb +0 -14
  50. data/spec/parse/no_method_error_spec.rb +0 -23
  51. data/spec/parse/registered_parsers_spec.rb +0 -68
  52. data/spec/parse/spec_helper.rb +0 -23
  53. 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
@@ -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