Skip to content

Commit 34d1dde

Browse files
committed
Add explicit check for Syntax Error
As suggested in #119 (comment) we are now explicitly checking the type of the incoming error. Rather than raise a new error, I've chosen to emit a warning and re-raise the original error. This is a similar pattern to the case where we are not able to detect the filename from the error message. The goal is to provide visibility into the source of the behavior, but to break as few expectations as possible. The `DeadEnd.handle_error` should (ideally) never raise an error to the end user. The purpose of the library is to provide progressive error enhancement. If it fails it means we cannot make a better error, so therefore we should warn (so the user can fix or report the problem) and then fall back to the original error. I also added a test for the failure error condition where the filename cannot be pulled out of the SyntaxError message which was added in #114.
1 parent 78297ee commit 34d1dde

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

lib/dead_end/api.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Error < StandardError; end
1616

1717
# DeadEnd.handle_error [Public]
1818
#
19-
# Takes an exception from a syntax error, uses that
19+
# Takes a `SyntaxError`` exception, uses the
2020
# error message to locate the file. Then the file
2121
# will be analyzed to find the location of the syntax
2222
# error and emit that location to stderr.
@@ -37,7 +37,12 @@ class Error < StandardError; end
3737
# exception will be re-raised (even with
3838
# `re_raise: false`).
3939
def self.handle_error(e, re_raise: true, io: $stderr)
40-
file = PathnameFromMessage.new(e.message).call.name
40+
unless e.is_a?(SyntaxError)
41+
io.puts("DeadEnd: Must pass a SyntaxError, got: #{e.class}")
42+
raise e
43+
end
44+
45+
file = PathnameFromMessage.new(e.message, io: io).call.name
4146
raise e unless file
4247

4348
io.sync = true

lib/dead_end/pathname_from_message.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def call
3030
end
3131

3232
if @parts.empty?
33-
@io.puts "DeadEnd: could not find filename from #{@line.inspect}"
33+
@io.puts "DeadEnd: Could not find filename from #{@line.inspect}"
3434
@name = nil
3535
end
3636

spec/unit/api_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module DeadEnd
1010
def fake_error.message
1111
"#{__FILE__}:216: unterminated string meets end of file "
1212
end
13+
def fake_error.is_a?(v); true; end
1314

1415
io = StringIO.new
1516
DeadEnd.handle_error(
@@ -20,5 +21,39 @@ def fake_error.message
2021

2122
expect(io.string.strip).to eq("Syntax OK")
2223
end
24+
25+
it "raises original error with warning if a non-syntax error is passed" do
26+
error = NameError.new("blerg")
27+
io = StringIO.new
28+
expect {
29+
DeadEnd.handle_error(
30+
error,
31+
re_raise: false,
32+
io: io
33+
)
34+
}.to raise_error {|e|
35+
expect(io.string).to include("Must pass a SyntaxError")
36+
expect(e).to eq(error)
37+
}
38+
end
39+
40+
it "raises original error with warning if file is not found" do
41+
fake_error = SyntaxError.new
42+
def fake_error.message
43+
"#does/not/exist/lol/doesnotexist:216: unterminated string meets end of file "
44+
end
45+
46+
io = StringIO.new
47+
expect {
48+
DeadEnd.handle_error(
49+
fake_error,
50+
re_raise: false,
51+
io: io
52+
)
53+
}.to raise_error {|e|
54+
expect(io.string).to include("Could not find filename")
55+
expect(e).to eq(fake_error)
56+
}
57+
end
2358
end
2459
end

0 commit comments

Comments
 (0)