Skip to content

Commit 96c9440

Browse files
authored
Fixes for Expr(:incomplete) detection (#260)
Fix #110
1 parent 4fb97b8 commit 96c9440

File tree

2 files changed

+23
-16
lines changed

2 files changed

+23
-16
lines changed

src/hooks.jl

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,20 @@ end
2929
# next if the incomplete stream was to continue. (Though this is just rough. In
3030
# practice several categories are combined for the purposes of the REPL -
3131
# perhaps we can/should do something more precise in the future.)
32-
function _incomplete_tag(n::SyntaxNode)
32+
function _incomplete_tag(n::SyntaxNode, codelen)
3333
i,c = _first_error(n)
34-
if isnothing(c)
34+
if isnothing(c) || last_byte(c) < codelen || codelen == 0
3535
return :none
36+
elseif first_byte(c) < codelen
37+
if kind(c) == K"ErrorEofMultiComment" && last_byte(c) == codelen
38+
# This is the one weird case where the token itself is an
39+
# incomplete error
40+
return :comment
41+
else
42+
return :none
43+
end
3644
end
37-
# TODO: Check error hits last character
38-
if kind(c) == K"ErrorEofMultiComment"
39-
return :comment
40-
elseif kind(c) == K"error" && begin
45+
if kind(c) == K"error" && begin
4146
cs = children(c)
4247
length(cs) > 0
4348
end
@@ -71,10 +76,8 @@ function _incomplete_tag(n::SyntaxNode)
7176
end
7277

7378
#-------------------------------------------------------------------------------
74-
@static if isdefined(Core, :_setparser!)
79+
if isdefined(Core, :_setparser!)
7580
const _set_core_parse_hook = Core._setparser!
76-
elseif isdefined(Core, :set_parser)
77-
const _set_core_parse_hook = Core.set_parser
7881
else
7982
function _set_core_parse_hook(parser)
8083
# HACK! Fool the runtime into allowing us to set Core._parse, even during
@@ -164,12 +167,8 @@ function _core_parser_hook(code, filename::String, lineno::Int, offset::Int, opt
164167
if any_error(stream)
165168
tree = build_tree(SyntaxNode, stream,
166169
wrap_toplevel_as_kind=K"None", first_line=lineno)
167-
_,err = _first_error(tree)
168-
# In the flisp parser errors are normally `Expr(:error, msg)` where
169-
# `msg` is a String. By using a ParseError for msg we can do fancy
170-
# error reporting instead.
171-
if last_byte(err) == lastindex(code)
172-
tag = _incomplete_tag(tree)
170+
tag = _incomplete_tag(tree, lastindex(code))
171+
if tag !== :none
173172
# Here we replicate the particular messages
174173
msg =
175174
tag === :string ? "incomplete: invalid string syntax" :
@@ -180,6 +179,9 @@ function _core_parser_hook(code, filename::String, lineno::Int, offset::Int, opt
180179
"incomplete: premature end of input"
181180
error_ex = Expr(:incomplete, msg)
182181
else
182+
# In the flisp parser errors are normally `Expr(:error, msg)` where
183+
# `msg` is a String. By using a JuliaSyntax.ParseError for msg
184+
# we can do fancy error reporting instead.
183185
error_ex = Expr(:error, ParseError(stream, filename=filename, first_line=lineno))
184186
end
185187
ex = options === :all ? Expr(:toplevel, error_ex) : error_ex

test/hooks.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
@test Meta.isexpr(Meta.parse("[x"), :incomplete)
5555

5656
for (str, tag) in [
57-
"" => :none
5857
"\"" => :string
5958
"\"\$foo" => :string
6059
"#=" => :comment
@@ -101,6 +100,12 @@
101100
"1, " => :other
102101
"1,\n" => :other
103102
"1, \n" => :other
103+
104+
# Syntax which may be an error but is not incomplete
105+
"" => :none
106+
")" => :none
107+
"1))" => :none
108+
"a b" => :none
104109
]
105110
@testset "$(repr(str))" begin
106111
@test Base.incomplete_tag(Meta.parse(str, raise=false)) == tag

0 commit comments

Comments
 (0)