@@ -458,17 +458,18 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
458458 end
459459end
460460
461+ # Contains file name and file number. Gets set when a backtrace
462+ # or methodlist is shown. Used by the REPL to make it possible to open
463+ # the location of a stackframe/method in the editor.
464+ global LAST_SHOWN_LINE_INFOS = Tuple{String, Int}[]
465+
461466function show_trace_entry (io, frame, n; prefix = " " )
467+ push! (LAST_SHOWN_LINE_INFOS, (string (frame. file), frame. line))
462468 print (io, " \n " , prefix)
463469 show (io, frame, full_path= true )
464470 n > 1 && print (io, " (repeats " , n, " times)" )
465471end
466472
467- # Contains file name and file number. Gets set when a backtrace
468- # or methodlist is shown. Used by the REPL to make it possible to open
469- # the location of a stackframe/method in the editor.
470- global LAST_SHOWN_LINE_INFOS = Tuple{String, Int}[]
471-
472473# In case the line numbers in the source code have changed since the code was compiled,
473474# allow packages to set a callback function that corrects them.
474475# (Used by Revise and perhaps other packages.)
@@ -489,6 +490,10 @@ function show_reduced_backtrace(io::IO, t::Vector, with_prefix::Bool)
489490 frame appears just before. =#
490491
491492 displayed_stackframes = []
493+ repeated_cycle = Tuple{Int,Int,Int}[]
494+ # First: line to introuce the "cycle repetition" message
495+ # Second: length of the cycle
496+ # Third: number of repetitions
492497 frame_counter = 1
493498 while frame_counter < length (t)
494499 (last_frame, n) = t[frame_counter]
@@ -507,11 +512,10 @@ function show_reduced_backtrace(io::IO, t::Vector, with_prefix::Bool)
507512 while i < length (t) && t[i] == t[j]
508513 i+= 1 ; j+= 1
509514 end
510- if j >= frame_counter
515+ if j >= frame_counter- 1
511516 #= At least one cycle repeated =#
512517 repetitions = div (i - frame_counter + 1 , cycle_length)
513- print (io, " \n ... (the last " , cycle_length, " lines are repeated " ,
514- repetitions, " more time" , repetitions> 1 ? " s)" : " )" )
518+ push! (repeated_cycle, (length (displayed_stackframes), cycle_length, repetitions))
515519 frame_counter += cycle_length * repetitions - 1
516520 break
517521 end
@@ -524,13 +528,24 @@ function show_reduced_backtrace(io::IO, t::Vector, with_prefix::Bool)
524528
525529 try invokelatest (update_stackframes_callback[], displayed_stackframes) catch end
526530
527- for (frame, n) in displayed_stackframes
531+ push! (repeated_cycle, (0 ,0 ,0 )) # repeated_cycle is never empty
532+ frame_counter = 1
533+ for i in 1 : length (displayed_stackframes)
534+ (frame, n) = displayed_stackframes[i]
528535 if with_prefix
529- show_trace_entry (io, frame, n, prefix = string (" [" , frame_counter- 1 , " ] " ))
530- push! (LAST_SHOWN_LINE_INFOS, (string (frame. file), frame. line))
536+ show_trace_entry (io, frame, n, prefix = string (" [" , frame_counter, " ] " ))
531537 else
532538 show_trace_entry (io, frame, n)
533539 end
540+ while repeated_cycle[1 ][1 ] == i # never empty because of the initial (0,0,0)
541+ cycle_length = repeated_cycle[1 ][2 ]
542+ repetitions = repeated_cycle[1 ][3 ]
543+ popfirst! (repeated_cycle)
544+ print (io, " \n ... (the last " , cycle_length, " lines are repeated " ,
545+ repetitions, " more time" , repetitions> 1 ? " s)" : " )" )
546+ frame_counter += cycle_length * repetitions
547+ end
548+ frame_counter += 1
534549 end
535550end
536551
@@ -555,7 +570,6 @@ function show_backtrace(io::IO, t::Vector)
555570 for (last_frame, n) in filtered
556571 frame_counter += 1
557572 show_trace_entry (IOContext (io, :backtrace => true ), last_frame, n, prefix = string (" [" , frame_counter, " ] " ))
558- push! (LAST_SHOWN_LINE_INFOS, (string (last_frame. file), last_frame. line))
559573 end
560574 return
561575 end
0 commit comments