Skip to content

Commit e016293

Browse files
committed
Print file and line in diagnostics
1 parent ff99b65 commit e016293

File tree

6 files changed

+42
-19
lines changed

6 files changed

+42
-19
lines changed

src/diagnostics.jl

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,26 @@ last_byte(d::Diagnostic) = d.last_byte
4242
is_error(d::Diagnostic) = d.level == :error
4343

4444
function show_diagnostic(io::IO, diagnostic::Diagnostic, source::SourceFile)
45-
col,prefix = diagnostic.level == :error ? (:light_red, "Error") :
46-
diagnostic.level == :warning ? (:light_yellow, "Warning") :
47-
diagnostic.level == :note ? (:light_blue, "Note") :
48-
(:normal, "Info")
49-
printstyled(io, "$prefix: ", color=col)
50-
print(io, diagnostic.message, ":\n")
45+
color,prefix = diagnostic.level == :error ? (:light_red, "Error") :
46+
diagnostic.level == :warning ? (:light_yellow, "Warning") :
47+
diagnostic.level == :note ? (:light_blue, "Note") :
48+
(:normal, "Info")
49+
line, col = source_location(source, first_byte(diagnostic))
50+
linecol = "$line:$col"
51+
if !isnothing(source.filename)
52+
locstr = "$(source.filename):$linecol"
53+
if get(io, :color, false)
54+
# Also add hyperlinks in color terminals
55+
url = "file://$(abspath(source.filename))#$linecol"
56+
locstr = "\e]8;;$url\e\\$locstr\e]8;;\e\\"
57+
end
58+
else
59+
locstr = "line $locstr"
60+
end
61+
print(io, prefix, ": ")
62+
printstyled(io, diagnostic.message, color=color)
63+
printstyled(io, "\n", "@ $locstr", color=:light_black)
64+
print(io, "\n")
5165

5266
p = first_byte(diagnostic)
5367
q = last_byte(diagnostic)
@@ -66,6 +80,8 @@ function show_diagnostic(io::IO, diagnostic::Diagnostic, source::SourceFile)
6680

6781
hicol = (100,40,40)
6882

83+
# TODO: show line numbers on left
84+
6985
print(io, source[a:prevind(text, p)])
7086
# There's two situations, either
7187
if b >= c

src/parser_api.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ struct ParseError <: Exception
4747
end
4848

4949
function Base.showerror(io::IO, err::ParseError, bt; backtrace=false)
50+
println(io, "ParseError:")
5051
show_diagnostics(io, err.diagnostics, err.source)
5152
end
5253

5354
function Base.showerror(io::IO, err::ParseError)
55+
println(io, "ParseError:")
5456
show_diagnostics(io, err.diagnostics, err.source)
5557
end
5658

@@ -142,7 +144,7 @@ See [`parse`](@ref) for a more complete and powerful interface to the parser,
142144
as well as a description of the `version` and `rule` keywords.
143145
"""
144146
function parseall(::Type{T}, input...; rule=:toplevel, version=VERSION,
145-
ignore_trivia=true, kws...) where {T}
147+
ignore_trivia=true, filename=nothing) where {T}
146148
stream = ParseStream(input...; version=version)
147149
if ignore_trivia && rule != :toplevel
148150
bump_trivia(stream, skip_newlines=true)
@@ -154,20 +156,20 @@ function parseall(::Type{T}, input...; rule=:toplevel, version=VERSION,
154156
emit_diagnostic(stream, error="unexpected text after parsing $rule")
155157
end
156158
if any_error(stream.diagnostics)
157-
source = SourceFile(sourcetext(stream, steal_textbuf=true))
159+
source = SourceFile(sourcetext(stream, steal_textbuf=true), filename=filename)
158160
throw(ParseError(source, stream.diagnostics))
159161
end
160162
# TODO: Figure out a more satisfying solution to the wrap_toplevel_as_kind
161163
# mess that we've got here.
162164
# * It's kind of required for GreenNode, as GreenNode only records spans,
163165
# not absolute positions.
164166
# * Dropping it would be ok for SyntaxNode and Expr...
165-
tree = build_tree(T, stream; wrap_toplevel_as_kind=K"toplevel", kws...)
167+
tree = build_tree(T, stream; wrap_toplevel_as_kind=K"toplevel", filename=filename)
166168
if !isempty(stream.diagnostics)
167169
# Crudely format any warnings to the current logger.
168170
buf = IOBuffer()
169171
show_diagnostics(IOContext(buf, stdout), stream,
170-
SourceFile(sourcetext(stream, steal_textbuf=true)))
172+
SourceFile(sourcetext(stream, steal_textbuf=true), filename=filename))
171173
@warn Text(String(take!(buf)))
172174
end
173175
tree

src/syntax_tree.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ Base.Expr(node::SyntaxNode) = _to_expr(node)
423423

424424
#-------------------------------------------------------------------------------
425425

426-
function build_tree(::Type{SyntaxNode}, stream::ParseStream; filename="none", kws...)
426+
function build_tree(::Type{SyntaxNode}, stream::ParseStream; filename=nothing, kws...)
427427
green_tree = build_tree(GreenNode, stream; kws...)
428428
source = SourceFile(sourcetext(stream), filename=filename)
429429
SyntaxNode(source, green_tree, first_byte(stream))

src/utils.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,16 @@ function flisp_parse_all(code; filename="none")
2626
end
2727

2828
# Really remove line numbers, even from Expr(:toplevel)
29-
function remove_linenums!(ex)
30-
ex = Base.remove_linenums!(ex)
31-
if Meta.isexpr(ex, :toplevel)
32-
filter!(x->!(x isa LineNumberNode), ex.args)
29+
remove_linenums!(ex) = ex
30+
function remove_linenums!(ex::Expr)
31+
if ex.head === :block || ex.head === :quote || ex.head === :toplevel
32+
filter!(ex.args) do x
33+
!(isa(x, Expr) && x.head === :line || isa(x, LineNumberNode))
34+
end
3335
end
34-
ex
36+
for subex in ex.args
37+
subex isa Expr && remove_linenums!(subex)
38+
end
39+
return ex
3540
end
3641

test/syntax_tree.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
Expr(:(=),
1616
Expr(:call, :f),
1717
Expr(:block,
18-
LineNumberNode(1, :none),
18+
LineNumberNode(1),
1919
:xs))
2020
# flisp parser quirk: In a for loop the block is not added, despite
2121
# this defining a short-form function.

test/test_utils.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ end
4040

4141
function parsers_agree_on_file(path)
4242
text = read(path, String)
43-
ex = parseall(Expr, text)
44-
fl_ex = flisp_parse_all(text)
43+
ex = parseall(Expr, text, filename=path)
44+
fl_ex = flisp_parse_all(text, filename=path)
4545
JuliaSyntax.remove_linenums!(ex) == JuliaSyntax.remove_linenums!(fl_ex)
4646
end
4747

0 commit comments

Comments
 (0)