Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
48 changes: 34 additions & 14 deletions src/debugger/call_stack.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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()
}

Expand All @@ -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<StackFrame> {
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 {
Expand All @@ -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,
Expand Down
21 changes: 15 additions & 6 deletions src/debugger/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<FunctionName> {
self.function_names
.statements_functions
.get(&statement_idx)
.and_then(|locations| locations.first().cloned())
) -> Option<&Vec<CodeLocation>> {
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<FunctionName>> {
self.function_names.statements_functions.get(&statement_idx)
}

pub fn statement_idxs_for_breakpoint(
Expand Down