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.
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