From ebaca54550f1cf74a34478ae862d80d0db8dc184 Mon Sep 17 00:00:00 2001 From: ksew1 Date: Sun, 8 Feb 2026 21:42:01 +0100 Subject: [PATCH] StackTrace requests support for inlined functions Closes #14 commit-id:c549ee5c --- .DS_Store | Bin 0 -> 6148 bytes src/debugger/call_stack.rs | 48 ++++++++++++++++++++++++++----------- src/debugger/context.rs | 21 +++++++++++----- 3 files changed, 49 insertions(+), 20 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d09741a9895bb67b6c797f265ebe1609b3a1074b GIT binary patch literal 6148 zcmeHKF-rq66n?3-t-81r92`z?RVWC8(QaR^s9;s6^kOu_7x6XxZj6_H0K@ z9#{8`(bS>jVazu<#An#`kGXyy-h>i0D1aJkcr!4zcqEz+@mVIHsqAe_mzecTUSDTg z{1T_kuLs<~%i=_vjdsN3vC!OWy(4;_SvwlF>d_T!_I|Jm;Me|wU9atb&F{*?kEnV-+k;3w&`HS**5to6{A(AYRHR4AvQ j)5ozK@KHR3CJix<2S8tAs1P2Q`y(J_aGg`&R~7gGJGJfU literal 0 HcmV?d00001 diff --git a/src/debugger/call_stack.rs b/src/debugger/call_stack.rs index 8af5cff..4e9d475 100644 --- a/src/debugger/call_stack.rs +++ b/src/debugger/call_stack.rs @@ -1,7 +1,8 @@ use std::iter::once; use std::path::Path; -use cairo_annotations::annotations::coverage::CodeLocation; +use cairo_annotations::annotations::coverage::{CodeLocation, SourceFileFullPath}; +use cairo_annotations::annotations::profiler::FunctionName; use cairo_lang_sierra::program::StatementIdx; use dap::types::{Scope, ScopePresentationhint, StackFrame, Variable}; use dap::types::{Source, StackFramePresentationhint}; @@ -64,8 +65,8 @@ impl CallStack { .map(|(call_statement_idx, _)| call_statement_idx) .cloned() .chain(once(statement_idx)) - .map(|statement_idx| self.build_stack_frame(ctx, statement_idx)) .rev() + .flat_map(|statement_idx| self.build_stack_frames(ctx, statement_idx)) .collect() } @@ -92,19 +93,34 @@ impl CallStack { vec![] } - fn build_stack_frame(&self, ctx: &Context, statement_idx: StatementIdx) -> StackFrame { - let id = MIN_OBJECT_REFERENCE + 2 * self.call_ids.len() as i64; - let Some(CodeLocation(source_file, code_span, _)) = - ctx.code_location_for_statement_idx(statement_idx) - else { - return unknown_frame(); + /// Builds a vector of stack frames, ordered from the most nested (innermost) to the least nested (outermost) element. + fn build_stack_frames(&self, ctx: &Context, statement_idx: StatementIdx) -> Vec { + let Some(code_locations) = ctx.code_locations_for_statement_idx(statement_idx) else { + return vec![unknown_frame()]; }; - let file_path = Path::new(&source_file.0); - let name = ctx - .function_name_for_statement_idx(statement_idx) - .map(|name| name.0) - .unwrap_or("test".to_string()); + let default_function_names = vec![FunctionName("test".to_string())]; + let function_names = + ctx.function_names_for_statement_idx(statement_idx).unwrap_or(&default_function_names); + + code_locations + .iter() + .zip(function_names) + .map(|(code_location, function_name)| { + self.build_stack_frame(code_location, function_name, ctx) + }) + .collect() + } + + fn build_stack_frame( + &self, + CodeLocation(SourceFileFullPath(source_file), code_span, _): &CodeLocation, + FunctionName(function_name): &FunctionName, + ctx: &Context, + ) -> StackFrame { + let id = MIN_OBJECT_REFERENCE + 2 * self.call_ids.len() as i64; + let file_path = Path::new(&source_file); + let name = function_name.clone(); let is_user_code = file_path.starts_with(&ctx.root_path); let presentation_hint = Some(if is_user_code { @@ -121,7 +137,11 @@ impl CallStack { StackFrame { id, name, - source: Some(Source { name: None, path: Some(source_file.0), ..Default::default() }), + source: Some(Source { + name: None, + path: Some(source_file.clone()), + ..Default::default() + }), line, column, presentation_hint, diff --git a/src/debugger/context.rs b/src/debugger/context.rs index 8c02c9d..ba3d9bd 100644 --- a/src/debugger/context.rs +++ b/src/debugger/context.rs @@ -86,6 +86,7 @@ impl Context { ) } + /// Return code location for the current statement, not including inlined code locations. pub fn code_location_for_statement_idx( &self, statement_idx: StatementIdx, @@ -96,14 +97,22 @@ impl Context { .and_then(|locations| locations.first().cloned()) } - pub fn function_name_for_statement_idx( + /// Return code locations for the current statement, including inlined code locations. + /// The first element is not inlined. + pub fn code_locations_for_statement_idx( &self, statement_idx: StatementIdx, - ) -> Option { - self.function_names - .statements_functions - .get(&statement_idx) - .and_then(|locations| locations.first().cloned()) + ) -> Option<&Vec> { + self.code_locations.statements_code_locations.get(&statement_idx) + } + + /// Return function names for the current statement, including inlined function names. + /// The first element is not inlined. + pub fn function_names_for_statement_idx( + &self, + statement_idx: StatementIdx, + ) -> Option<&Vec> { + self.function_names.statements_functions.get(&statement_idx) } pub fn statement_idxs_for_breakpoint(