From e542d590e0812586a3c4e6823bfa5fb87db5b4d0 Mon Sep 17 00:00:00 2001 From: Charles Kawczynski Date: Fri, 19 Apr 2024 12:07:20 -0400 Subject: [PATCH] Add type_depth_limit to CthulhuConfig Add helper Use depth-limited type printing --- TypedSyntax/src/show.jl | 33 +++++++++++++++++------- src/Cthulhu.jl | 4 ++- src/codeview.jl | 13 ++++++---- test/test_depth_limited_type_printing.jl | 22 ++++++++++++++++ 4 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 test/test_depth_limited_type_printing.jl diff --git a/TypedSyntax/src/show.jl b/TypedSyntax/src/show.jl index f3bfbe05..67291fcf 100644 --- a/TypedSyntax/src/show.jl +++ b/TypedSyntax/src/show.jl @@ -32,7 +32,9 @@ end function Base.printstyled(io::IO, rootnode::MaybeTypedSyntaxNode; type_annotations::Bool=true, iswarn::Bool=true, hide_type_stable::Bool=true, with_linenumber::Bool=true, - idxend = last_byte(rootnode)) + idxend = last_byte(rootnode), + maxtypedepth = 2 + ) rt = gettyp(rootnode) nd = with_linenumber ? ndigits_linenumbers(rootnode, idxend) : 0 rootnode = get_function_def(rootnode) @@ -43,11 +45,11 @@ function Base.printstyled(io::IO, rootnode::MaybeTypedSyntaxNode; @assert length(children(rootnode)) == 2 sig, body = children(rootnode) type_annotate, pre, pre2, post = type_annotation_mode(sig, rt; type_annotations, hide_type_stable) - position = show_src_expr(io, sig, position, pre, pre2; type_annotations, iswarn, hide_type_stable, nd) - type_annotate && show_annotation(io, rt, post, rootnode.source, position; iswarn) + position = show_src_expr(io, sig, position, pre, pre2; type_annotations, iswarn, hide_type_stable, nd, maxtypedepth) + type_annotate && show_annotation(io, rt, post, rootnode.source, position; iswarn, maxtypedepth) rootnode = body end - position = show_src_expr(io, rootnode, position, "", ""; type_annotations, iswarn, hide_type_stable, nd) + position = show_src_expr(io, rootnode, position, "", ""; type_annotations, iswarn, hide_type_stable, nd, maxtypedepth) catchup(io, rootnode, position, nd, idxend+1) # finish the node return nothing end @@ -63,7 +65,7 @@ function _print(io::IO, x, node, position) end end -function show_src_expr(io::IO, node::MaybeTypedSyntaxNode, position::Int, pre::String, pre2::String; type_annotations::Bool=true, iswarn::Bool=false, hide_type_stable::Bool=false, nd::Int) +function show_src_expr(io::IO, node::MaybeTypedSyntaxNode, position::Int, pre::String, pre2::String; type_annotations::Bool=true, iswarn::Bool=false, hide_type_stable::Bool=false, nd::Int, maxtypedepth) _lastidx = last_byte(node) position = catchup(io, node, position, nd) if haschildren(node) @@ -77,8 +79,8 @@ function show_src_expr(io::IO, node::MaybeTypedSyntaxNode, position::Int, pre::S i == 2 && _print(io, pre2, node.source, position) cT = gettyp(child) ctype_annotate, cpre, cpre2, cpost = type_annotation_mode(child, cT; type_annotations, hide_type_stable) - position = show_src_expr(io, child, position, cpre, cpre2; type_annotations, iswarn, hide_type_stable, nd) - ctype_annotate && show_annotation(io, cT, cpost, node.source, position; iswarn) + position = show_src_expr(io, child, position, cpre, cpre2; type_annotations, iswarn, hide_type_stable, nd, maxtypedepth) + ctype_annotate && show_annotation(io, cT, cpost, node.source, position; iswarn, maxtypedepth) end return Int(catchup(io, node, position, nd, _lastidx+1)) end @@ -113,12 +115,25 @@ function type_annotation_mode(node, @nospecialize(T); type_annotations::Bool, hi return type_annotate, pre, pre2, post end -function show_annotation(io, @nospecialize(T), post, node, position; iswarn::Bool) +function type_depth_limit(io::IO, s::String; maxtypedepth::Union{Nothing,Int}) + sz = get(io, :displaysize, displaysize(io))::Tuple{Int, Int} + return Base.type_depth_limit(s, max(sz[2], 120); maxdepth=maxtypedepth) +end + +type_depth_limit(::T; maxtypedepth) where {T} = type_depth_limit(T; maxtypedepth) + +function type_depth_limit(::Type{T}; maxtypedepth) where {T} + buf = IOBuffer() + io = IOContext(buf, :limit => true) + type_depth_limit(io, string(T); maxtypedepth) +end + +function show_annotation(io, @nospecialize(T), post, node, position; iswarn::Bool, maxtypedepth) diagnostics = get(io, :diagnostics, nothing) inlay_hints = get(io, :inlay_hints, nothing) print(io, post) - T_str = string(T) + T_str = type_depth_limit(T; maxtypedepth) if iswarn && is_type_unstable(T) color = is_small_union_or_tunion(T) ? :yellow : :red printstyled(io, "::", T_str; color) diff --git a/src/Cthulhu.jl b/src/Cthulhu.jl index e3db6de1..0c4b6531 100644 --- a/src/Cthulhu.jl +++ b/src/Cthulhu.jl @@ -47,6 +47,7 @@ Base.@kwdef mutable struct CthulhuConfig inlay_types_vscode::Bool = true diagnostics_vscode::Bool = true jump_always::Bool = false + type_depth_limit::Union{Nothing, Int} = 2 end """ @@ -411,6 +412,7 @@ function _descend(term::AbstractTerminal, interp::AbstractInterpreter, curs::Abs inlay_types_vscode::Bool = CONFIG.inlay_types_vscode, # default is true diagnostics_vscode::Bool = CONFIG.diagnostics_vscode, # default is true jump_always::Bool = CONFIG.jump_always, # default is false + type_depth_limit::Union{Nothing, Int} = CONFIG.type_depth_limit, # default is 2 ) if isnothing(hide_type_stable) @@ -651,7 +653,7 @@ function _descend(term::AbstractTerminal, interp::AbstractInterpreter, curs::Abs remarks, with_effects, exception_type, inline_cost, type_annotations, annotate_source, inlay_types_vscode, diagnostics_vscode, - jump_always) + jump_always, type_depth_limit) elseif toggle === :warn iswarn ⊻= true diff --git a/src/codeview.jl b/src/codeview.jl index bc55aa42..0e62e8d3 100644 --- a/src/codeview.jl +++ b/src/codeview.jl @@ -119,6 +119,7 @@ function cthulhu_typed(io::IO, debuginfo::Symbol, lineprinter = __debuginfo[debuginfo] rettype = ignorelimited(rt) lambda_io = IOContext(io, :limit=>true) + maxtypedepth = CONFIG.type_depth_limit if annotate_source && isa(src, CodeInfo) tsn, _ = get_typed_sourcetext(mi, src, rt) @@ -147,9 +148,9 @@ function cthulhu_typed(io::IO, debuginfo::Symbol, ) if istruncated - printstyled(lambda_io, tsn; type_annotations, iswarn, hide_type_stable, idxend) + printstyled(lambda_io, tsn; type_annotations, iswarn, hide_type_stable, idxend, maxtypedepth) else - printstyled(vscode_io, tsn; type_annotations, iswarn, hide_type_stable, idxend) + printstyled(vscode_io, tsn; type_annotations, iswarn, hide_type_stable, idxend, maxtypedepth) end callsite_diagnostics = TypedSyntax.Diagnostic[] @@ -186,6 +187,7 @@ function cthulhu_typed(io::IO, debuginfo::Symbol, show_variables(io, src, slotnames) end end + maxtypedepth = CONFIG.type_depth_limit # preprinter configuration preprinter = if src isa IRCode && inline_cost @@ -215,7 +217,7 @@ function cthulhu_typed(io::IO, debuginfo::Symbol, idx == -1 ? lpad(total_cost, nd+1) : " "^(nd+1) str = sprint(; context=:color=>true) do @nospecialize io - printstyled(io, str; color=:green) + printstyled(io, str; color=:green, maxtypedepth) end if debuginfo === :source str *= " " @@ -263,7 +265,7 @@ function cthulhu_typed(io::IO, debuginfo::Symbol, function (io::IO; idx::Int, @nospecialize(kws...)) _postprinter(io; idx, kws...) for i = searchsorted(pc2remarks, idx=>"", by=((idx,msg),)->idx) - printstyled(io, ' ', pc2remarks[i].second; color=:light_black) + printstyled(io, ' ', pc2remarks[i].second; color=:light_black, maxtypedepth) end end else @@ -301,8 +303,9 @@ function descend_into_callsite!(io::IO, tsn::TypedSyntaxNode; # We empty the body when filling kwargs istruncated = isempty(children(body)) idxend = istruncated ? JuliaSyntax.last_byte(sig) : lastindex(tsn.source) + maxtypedepth = CONFIG.type_depth_limit if !istruncated # If method only fills in default arguments - printstyled(io, tsn; type_annotations, iswarn, hide_type_stable, idxend) + printstyled(io, tsn; type_annotations, iswarn, hide_type_stable, idxend, maxtypedepth) end end diff --git a/test/test_depth_limited_type_printing.jl b/test/test_depth_limited_type_printing.jl new file mode 100644 index 00000000..5540fe95 --- /dev/null +++ b/test/test_depth_limited_type_printing.jl @@ -0,0 +1,22 @@ +#= +using Revise; include(joinpath("test", "test_depth_limited_type_printing.jl")) +=# +import Cthulhu + +Base.@kwdef struct Nested{A,B} + num::Int = 1 +end +struct F49231{a,b,c,d,e,f,g} + num::g +end; +bar(x) = rand() > 0.5 ? x : Any[0][1] +mysum(x) = sum(y-> bar(x.num), 1:5; init=0) +nest_val(na, nb, ::Val{1}) = Nested{na, nb}() +nest_val(na, nb, ::Val{n}) where {n} = nest_val(Nested{na, nb}, Nested{na, nb}, Val(n-1)) +nest_val(na, nb, n::Int) = nest_val(na, nb, Val(n)) +nest_val(n) = nest_val(1, 1, n) + +f = nest_val(5) +a = Any[f]; +mysum(a[1]) # make sure it runs +Cthulhu.@descend mysum(a[1]) # navigate to sum -> sum, and F49231 will be there