Skip to content

Commit 1ea6980

Browse files
authored
Let Base handle parsing errors on Julia 1.10+ (#793)
Now that sufficient line information is incorporated into the error-expressions returned by parsing, we can eliminate our old hack to try to find some identifying information. Fixes #655
1 parent 9f7bd4e commit 1ea6980

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
matrix:
1515
version:
1616
- '1.6' # LTS
17+
- '1.9' # parsing errors branch on 1.10, so test the last pre-1.10 version
1718
- '1' # current stable
1819
os:
1920
- ubuntu-latest

src/parsing.jl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ function parse_source!(mod_exprs_sigs::ModuleExprsSigs, src::AbstractString, fil
4040
ex = Base.parse_input_line(src; filename=filename)
4141
ex === nothing && return mod_exprs_sigs
4242
if isexpr(ex, :error) || isexpr(ex, :incomplete)
43+
if Base.VERSION >= v"1.10"
44+
eval(ex) # this will throw, so the statements below will not execute
45+
end
4346
prevex, pos = first_bad_position(src)
4447
ln = count(isequal('\n'), SubString(src, 1, min(pos, length(src)))) + 1
4548
throw(LoadError(filename, ln, ex.args[1]))
@@ -79,13 +82,15 @@ function process_source!(mod_exprs_sigs::ModuleExprsSigs, ex, filename, mod::Mod
7982
return mod_exprs_sigs
8083
end
8184

82-
function first_bad_position(str)
83-
ex, pos, n = nothing, 1, length(str)
84-
while pos < n
85-
ex, pos = Meta.parse(str, pos; greedy=true, raise=false)
86-
if isexpr(ex, :error) || isexpr(ex, :incomplete)
87-
return ex, pos
85+
if Base.VERSION < v"1.10"
86+
function first_bad_position(str)
87+
ex, pos, n = nothing, 1, length(str)
88+
while pos < n
89+
ex, pos = Meta.parse(str, pos; greedy=true, raise=false)
90+
if isexpr(ex, :error) || isexpr(ex, :incomplete)
91+
return ex, pos
92+
end
8893
end
94+
error("expected an error, finished without one")
8995
end
90-
error("expected an error, finished without one")
9196
end

test/runtests.jl

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ const issue639report = []
117117

118118
do_test("Parse errors") && @testset "Parse errors" begin
119119
md = Revise.ModuleExprsSigs(Main)
120-
@test_throws LoadError Revise.parse_source!(md, """
120+
errtype = Base.VERSION < v"1.10" ? LoadError : Base.Meta.ParseError
121+
@test_throws errtype Revise.parse_source!(md, """
121122
begin # this block should parse correctly, cf. issue #109
122123
123124
end
@@ -140,9 +141,13 @@ const issue639report = []
140141
try
141142
includet(file)
142143
catch err
143-
@test isa(err, LoadError)
144-
@test err.file == file
145-
@test endswith(errmsg(err.error), Base.VERSION < v"1.10" ? "requires end" : "Expected `end`")
144+
@test isa(err, errtype)
145+
if Base.VERSION < v"1.10"
146+
@test err.file == file
147+
@test endswith(err.error, "requires end")
148+
else
149+
@test occursin("Expected `end`", err.msg)
150+
end
146151
end
147152
end
148153

@@ -2006,14 +2011,17 @@ const issue639report = []
20062011
@test exc.file == fn
20072012
@test exc.line == line
20082013
@test occursin(msg, errmsg(exc.error))
2014+
elseif ErrorType === Base.Meta.ParseError
2015+
@test occursin(msg, exc.msg)
20092016
elseif ErrorType === UndefVarError
20102017
@test msg == exc.var
20112018
end
20122019
@test length(st) == 1
20132020
end
20142021

20152022
# test errors are reported the the first time
2016-
check_revision_error(logs[1], LoadError, Base.VERSION < v"1.10" ? "missing comma or }" : "Expected `}`", 2 + (Base.VERSION >= v"1.10"))
2023+
check_revision_error(logs[1], Base.VERSION < v"1.10" ? LoadError : Base.Meta.ParseError,
2024+
Base.VERSION < v"1.10" ? "missing comma or }" : "Expected `}`", 2 + (Base.VERSION >= v"1.10"))
20172025
# Check that there's an informative warning
20182026
rec = logs[2]
20192027
@test startswith(rec.message, "The running code does not match")
@@ -2029,7 +2037,8 @@ const issue639report = []
20292037
logs,_ = Test.collect_test_logs() do
20302038
Revise.errors()
20312039
end
2032-
check_revision_error(logs[1], LoadError, Base.VERSION < v"1.10" ? "missing comma or }" : "Expected `}`", 2 + (Base.VERSION >= v"1.10"))
2040+
check_revision_error(logs[1], Base.VERSION < v"1.10" ? LoadError : Base.Meta.ParseError,
2041+
Base.VERSION < v"1.10" ? "missing comma or }" : "Expected `}`", 2 + (Base.VERSION >= v"1.10"))
20332042

20342043
write(joinpath(dn, "RevisionErrors.jl"), """
20352044
module RevisionErrors
@@ -2060,7 +2069,8 @@ const issue639report = []
20602069
yry()
20612070
end
20622071
delim = Base.VERSION < v"1.10" ? '"' : '`'
2063-
check_revision_error(logs[1], LoadError, "unexpected $delim=$delim", 6 + (Base.VERSION >= v"1.10")*2)
2072+
check_revision_error(logs[1], Base.VERSION < v"1.10" ? LoadError : Base.Meta.ParseError,
2073+
"unexpected $delim=$delim", 6 + (Base.VERSION >= v"1.10")*2)
20642074

20652075
write(joinpath(dn, "RevisionErrors.jl"), """
20662076
module RevisionErrors
@@ -2106,7 +2116,11 @@ const issue639report = []
21062116
revise(throw=true)
21072117
false
21082118
catch err
2109-
isa(err, LoadError) && occursin(Base.VERSION < v"1.10" ? """unexpected "}" """ : "Expected `)`", errmsg(err.error))
2119+
if Base.VERSION < v"1.10"
2120+
isa(err, LoadError) && occursin("""unexpected "}" """, errmsg(err.error))
2121+
else
2122+
isa(err, Base.Meta.ParseError) && occursin("Expected `)`", err.msg)
2123+
end
21102124
end
21112125
sleep(mtimedelay)
21122126
write(joinpath(dn, "RevisionErrors.jl"), """

0 commit comments

Comments
 (0)