Skip to content

Commit df84e02

Browse files
authored
Only show the first parse error (#344)
Parser recovery commonly results in several errors which refer to much the same location in the broken source file and are not useful to the user. Currently the most useful error is the first one, so this PR trims down error printing to only show that one.
1 parent 94bad1a commit df84e02

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

src/parser_api.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ end
1717

1818
function Base.showerror(io::IO, err::ParseError)
1919
println(io, "ParseError:")
20-
show_diagnostics(io, err.diagnostics, err.source)
20+
# Only show the first parse error for now - later errors are often
21+
# misleading due to the way recovery works
22+
i = findfirst(is_error, err.diagnostics)
23+
if isnothing(i)
24+
i = lastindex(err.diagnostics)
25+
end
26+
show_diagnostics(io, err.diagnostics[1:i], err.source)
2127
end
2228

2329
"""

test/parser_api.jl

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,28 +117,56 @@ end
117117

118118
@testset "ParseError printing" begin
119119
try
120-
JuliaSyntax.parsestmt(JuliaSyntax.SyntaxNode, "a -- b -- c", filename="somefile.jl")
120+
parsestmt(SyntaxNode, "a -- b -- c", filename="somefile.jl")
121121
@assert false "error should be thrown"
122122
catch exc
123123
@test exc isa JuliaSyntax.ParseError
124124
@test sprint(showerror, exc) == """
125125
ParseError:
126126
# Error @ somefile.jl:1:3
127127
a -- b -- c
128-
# └┘ ── invalid operator
129-
# Error @ somefile.jl:1:8
130-
a -- b -- c
131-
# └┘ ── invalid operator"""
128+
# └┘ ── invalid operator"""
132129
@test occursin("Stacktrace:\n", sprint(showerror, exc, catch_backtrace()))
133130
file_url = JuliaSyntax._file_url("somefile.jl")
134131
@test sprint(showerror, exc, context=:color=>true) == """
135132
ParseError:
136133
\e[90m# Error @ \e[0;0m\e]8;;$file_url#1:3\e\\\e[90msomefile.jl:1:3\e[0;0m\e]8;;\e\\
137134
a \e[48;2;120;70;70m--\e[0;0m b -- c
138-
\e[90m# └┘ ── \e[0;0m\e[91minvalid operator\e[0;0m
139-
\e[90m# Error @ \e[0;0m\e]8;;$file_url#1:8\e\\\e[90msomefile.jl:1:8\e[0;0m\e]8;;\e\\
140-
a -- b \e[48;2;120;70;70m--\e[0;0m c
141-
\e[90m# └┘ ── \e[0;0m\e[91minvalid operator\e[0;0m"""
135+
\e[90m# └┘ ── \e[0;0m\e[91minvalid operator\e[0;0m"""
136+
end
137+
138+
try
139+
# Test that warnings are printed first followed by only the first error
140+
parsestmt(SyntaxNode, """
141+
@(a)
142+
x -- y
143+
z -- y""", filename="somefile.jl")
144+
@assert false "error should be thrown"
145+
catch exc
146+
@test exc isa JuliaSyntax.ParseError
147+
@test sprint(showerror, exc) == """
148+
ParseError:
149+
# Warning @ somefile.jl:1:2
150+
@(a)
151+
#└─┘ ── parenthesizing macro names is unnecessary
152+
# Error @ somefile.jl:2:1
153+
@(a)
154+
x
155+
╙ ── unexpected text after parsing statement"""
156+
end
157+
158+
try
159+
# Test that initial warnings are always printed
160+
parsestmt(SyntaxNode, """
161+
@(a)""", filename="somefile.jl")
162+
@assert false "error should be thrown"
163+
catch exc
164+
@test exc isa JuliaSyntax.ParseError
165+
@test sprint(showerror, exc) == """
166+
ParseError:
167+
# Warning @ somefile.jl:1:2
168+
@(a)
169+
#└─┘ ── parenthesizing macro names is unnecessary"""
142170
end
143171
end
144172

0 commit comments

Comments
 (0)