Created
July 23, 2020 14:26
-
-
Save ashleysommer/b85982f191b1c0baab5c4d353cdcc814 to your computer and use it in GitHub Desktop.
Fixed Julia include file for Intellij-Julia
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Debugger | |
using JuliaInterpreter | |
using Sockets | |
using REPL | |
using JSON | |
import Debugger: Debugger, locdesc, locinfo, print_sourcecode, print_next_expr, print_locals, maybe_quote, pattern_match_kw_call, pattern_match_apply_call, breakpoint_linenumbers, repr_limited | |
import JuliaInterpreter: JuliaInterpreter, Frame, @lookup, caller, pc_expr, isexpr | |
_intellij_debug_mode = true | |
_intellij_current_stack = [] | |
_intellij_debug_port = 0 | |
function _intellij_send_to(rows) | |
if _intellij_debug_port != 0 | |
f = connect(getipaddr(), _intellij_debug_port) | |
write(f,json(rows) * "\n") | |
end | |
end | |
const MAX_BYTES_REPR = Ref(1024) | |
function Debugger.print_var(var::JuliaInterpreter.Variable)::Dict | |
T = typeof(var.value) | |
val = repr_limited(var.value, MAX_BYTES_REPR[]) | |
Dict("name" => string(var.name), "type" => string(T), "value" => val) | |
end | |
const _print_full_path = Ref(true) | |
function Debugger.locdesc(frame::Frame; current_line=false)::Dict | |
func = "" | |
file = "" | |
framecode = frame.framecode | |
meth = framecode.scope | |
@assert meth isa Method | |
argnames = framecode.src.slotnames[2:meth.nargs] | |
spectypes = Any[Any for i=1:length(argnames)] | |
is_kw = false | |
if frame.caller !== nothing | |
is_kw = occursin("#kw##", string(frame.caller.framecode.scope)) | |
end | |
if is_kw | |
i = 0 | |
for arg in argnames | |
if arg == Symbol("") | |
break | |
end | |
i += 1 | |
end | |
kw_indices = 1:i | |
positional_indices = i+2:length(argnames) | |
else | |
kw_indices = 1:0 | |
positional_indices = 1:length(argnames) | |
end | |
methname = string(meth.name) | |
if is_kw | |
m = match(r"#(.*?)#(?:[0-9]*)$", methname) | |
m === nothing || (methname = m.captures[1]) | |
end | |
func *= "$methname(" | |
function print_indices(indices) | |
first = true | |
for (argname, argT) in zip(argnames[indices], spectypes[indices]) | |
first || (func *= ", ") | |
first = false | |
func *= "$argname" | |
!(argT === Any) && (func *= "::$argT") | |
end | |
end | |
print_indices(positional_indices) | |
if !isempty(kw_indices) | |
func *= "; " | |
print_indices(kw_indices) | |
end | |
func *= ")" | |
line = current_line ? JuliaInterpreter.linenumber(frame) : meth.line | |
#path = string(_print_full_path[] ? meth.file : basename(String(meth.file)), ":", line) | |
path = string(_print_full_path[] ? meth.file : basename(String(meth.file))) | |
#path = CodeTracking.replace_buildbot_stdlibpath(String(path)) # TODO: CodeTracking | |
Dict("function" => func, "file" => path, "line" => line) | |
end | |
# function Debugger.print_status(io, state, frame) | |
# # Buffer to avoid flickering | |
# outbuf = IOContext(IOBuffer(), io) | |
# # printstyled(outbuf, "In ", locdesc(frame), "\n"; color=:bold) | |
# # println("location: $fl") | |
# loc = locinfo(frame) | |
# | |
# currentLine = loc.line | |
# fileInfo::Dict = locdesc(frame) | |
# !_intellij_debug_mode && | |
# if loc !== nothing | |
# data = if isa(loc, BufferLocInfo) | |
# loc.data | |
# else | |
# VERSION < v"0.7" ? read(loc.filepath, String) : | |
# read(loc.filepath, String) | |
# end | |
# print_sourcecode(outbuf, data, | |
# loc.line, loc.defline) | |
# else | |
# buf = IOBuffer() | |
# active_line = print_status_synthtic(buf, state, frame, 2, 5)::Int | |
# code = split(String(take!(buf)),'\n') | |
# @assert active_line <= length(code) | |
# for (lineno, line) in enumerate(code) | |
# if lineno == active_line | |
# printstyled(outbuf, "=> ", bold = true, color = :yellow); println(outbuf, line) | |
# else | |
# printstyled(outbuf, "? ", bold = true); println(outbuf, line) | |
# end | |
# end | |
# end | |
# print_next_expr(outbuf, state, frame) | |
# # print(io, String(take!(outbuf.io))) | |
# about_to_run = String(take!(outbuf.io)) | |
# | |
# arr = print_backtrace(state) | |
# _intellij_send_to(Dict("next" => Dict("line" => currentLine, "expr" => about_to_run, "file" => fileInfo["file"]),"frames" => arr)) | |
# end | |
function Debugger.print_status(io::IO, frame::Frame; force_lowered=false) | |
# Buffer to avoid flickering | |
outbuf = IOContext(IOBuffer(), io) | |
loc = locinfo(frame) | |
fileInfo::Dict = locdesc(frame) | |
if _intellij_debug_mode | |
_, current_line, _ = loc | |
else | |
if loc !== nothing && !force_lowered | |
defline, current_line, body = loc | |
breakpoint_lines = breakpoint_linenumbers(frame) | |
ok = print_sourcecode(outbuf, body, current_line, defline, breakpoint_lines) | |
if !ok | |
printstyled(io, "failed to lookup source code, showing lowered code:\n"; color=Base.warn_color()) | |
print_codeinfo(outbuf, frame) | |
end | |
else | |
current_line = 0 | |
print_codeinfo(outbuf, frame) | |
end | |
end | |
print_next_expr(outbuf, frame) | |
about_to_run = String(take!(outbuf.io)) | |
arr = print_backtrace(frame) | |
_intellij_send_to(Dict("next" => Dict("line" => current_line, "expr" => about_to_run, "file" => fileInfo["file"]),"frames" => arr)) | |
end | |
function Debugger.print_next_expr(io::IO, frame::Frame) | |
expr = pc_expr(frame) | |
@assert expr !== nothing | |
#print(io, "About to run: ") | |
isa(expr, Expr) && (expr = copy(expr)) | |
if isexpr(expr, :(=)) | |
expr = expr.args[2] | |
end | |
if isexpr(expr, :call) || isexpr(expr, :return) | |
for i in 1:length(expr.args) | |
val = try | |
@lookup(frame, expr.args[i]) | |
catch err | |
err isa UndefVarError || rethrow(err) | |
expr.args[i] | |
end | |
expr.args[i] = maybe_quote(val) | |
end | |
end | |
expr = pattern_match_kw_call(expr) | |
expr = pattern_match_apply_call(expr, frame) | |
limit_expr = repr_limited(expr, MAX_BYTES_REPR[], print) | |
print(io, limit_expr) | |
#print(io, highlight_code(limit_expr; context=io)) | |
#println(io) | |
end | |
function print_locdesc(frame::Frame; current_line=False) | |
sprint() do io | |
Debugger.locdesc(io, frame; current_line=current_line) | |
end | |
end | |
function print_locdesc(io::IO, frame::Frame; current_line=False) | |
Debugger.locdesc(io, frame; current_line=current_line) | |
end | |
function Debugger.print_frame(io::IO, num::Integer, frame::Frame; current_line=false)::Dict | |
#print(io, "[$num] ") | |
#println(io, locdesc(frame; current_line=current_line)) | |
stackInfo::Dict = Debugger.locdesc(frame; current_line=current_line) | |
global _intellij_current_stack | |
varinfo = _intellij_current_stack = [] | |
print_locals(frame) | |
Dict("stack" => stackInfo, "vars" => varinfo) | |
end | |
function print_backtrace(frame::Frame)::Array | |
num = 0 | |
arr = [] | |
sprint() do io | |
while frame !== nothing | |
num += 1 | |
frame_info::Dict = Debugger.print_frame(io, num, frame; current_line=true) | |
push!(arr, frame_info) | |
frame = caller(frame) | |
end | |
end | |
arr | |
end | |
function print_backtrace(state)::Array | |
io = Base.pipe_writer(state.terminal) | |
iob = IOContext(IOBuffer(), io) | |
num = 0 | |
arr = [] | |
frame = state.frame | |
while frame !== nothing | |
num += 1 | |
frame_info::Dict = Debugger.print_frame(iob, num, frame; current_line=true) | |
push!(arr, frame_info) | |
frame = caller(frame) | |
end | |
arr | |
end | |
function Debugger.print_locals(frame::Frame) | |
global _intellij_current_stack | |
vars = JuliaInterpreter.locals(frame) | |
for var in vars | |
# Hide gensymmed variables | |
if var.name == Symbol("#self#") | |
val = var.value | |
(isa(val, Type) || sizeof(val) == 0) && continue | |
else | |
startswith(string(var.name), "#") && continue | |
end | |
ret = Debugger.print_var(var) | |
push!(_intellij_current_stack,ret) | |
end | |
#TODO: Do sparams? | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment