Skip to content

Commit 0d39fa9

Browse files
authored
When an error occurs show line/col info for each frame in the stack (#2573)
Fixes #2495 . When an error occurs show line/col info for each frame in the stack.
1 parent 7706cff commit 0d39fa9

File tree

2 files changed

+41
-19
lines changed

2 files changed

+41
-19
lines changed

source/compiler/qsc/src/interpret/debug.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#[cfg(test)]
55
mod tests;
66

7+
use qsc_data_structures::line_column::{Encoding, Position};
78
use qsc_eval::debug::Frame;
89
use qsc_fir::fir::{Global, PackageStoreLookup, StoreItemId};
910
use qsc_frontend::compile::PackageStore;
@@ -48,8 +49,15 @@ pub(crate) fn format_call_stack(
4849
write!(trace, "{}", call.name.name).expect("writing to string should succeed");
4950

5051
let name = get_item_file_name(store, frame.id);
51-
write!(trace, " in {}", name.unwrap_or("<expression>".to_string()))
52-
.expect("writing to string should succeed");
52+
let pos = get_position(frame, store);
53+
write!(
54+
trace,
55+
" in {}:{}:{}",
56+
name.unwrap_or("<expression>".to_string()),
57+
pos.line,
58+
pos.column,
59+
)
60+
.expect("writing to string should succeed");
5361

5462
trace.push('\n');
5563
}
@@ -89,3 +97,16 @@ fn get_ns_name(item: &Item) -> Option<Rc<str>> {
8997
};
9098
Some(ns.name())
9199
}
100+
101+
/// Converts the [`Span`] of [`Frame`] into a [`Position`].
102+
fn get_position(frame: Frame, store: &PackageStore) -> Position {
103+
let filename = get_item_file_name(store, frame.id).expect("file should exist");
104+
let package_id = map_fir_package_to_hir(frame.id.package);
105+
let unit = store.get(package_id).expect("package should exist");
106+
let source = unit
107+
.sources
108+
.find_by_name(&filename)
109+
.expect("source should exist");
110+
let contents = &source.contents;
111+
Position::from_utf8_byte_offset(Encoding::Utf8, contents, frame.span.lo)
112+
}

source/compiler/qsc/src/interpret/debug/tests.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
use expect_test::expect;
45
use indoc::indoc;
56
use miette::Result;
67
use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
@@ -90,15 +91,15 @@ fn stack_traces_can_cross_eval_session_and_file_boundaries() {
9091
let stack_trace = e[0]
9192
.stack_trace()
9293
.expect("code should have a valid stack trace");
93-
let expectation = indoc! {r#"
94-
Error: division by zero
95-
Call stack:
96-
at Adjoint Test.C in 1.qs
97-
at Adjoint Test.B in 1.qs
98-
at Adjoint Test2.A in 2.qs
99-
at Z in line_0
100-
"#};
101-
assert_eq!(expectation, stack_trace);
94+
expect![[r#"
95+
Error: division by zero
96+
Call stack:
97+
at Adjoint Test.C in 1.qs:10:12
98+
at Adjoint Test.B in 1.qs:3:12
99+
at Adjoint Test2.A in 2.qs:9:0
100+
at Z in line_0:0:34
101+
"#]]
102+
.assert_eq(stack_trace);
102103
}
103104
}
104105
}
@@ -161,14 +162,14 @@ fn stack_traces_can_cross_file_and_entry_boundaries() {
161162
let stack_trace = e[0]
162163
.stack_trace()
163164
.expect("code should have a valid stack trace");
164-
let expectation = indoc! {r#"
165-
Error: division by zero
166-
Call stack:
167-
at Adjoint Test.C in 1.qs
168-
at Adjoint Test.B in 1.qs
169-
at Adjoint Test2.A in 2.qs
170-
"#};
171-
assert_eq!(expectation, stack_trace);
165+
expect![[r#"
166+
Error: division by zero
167+
Call stack:
168+
at Adjoint Test.C in 1.qs:11:8
169+
at Adjoint Test.B in 1.qs:5:0
170+
at Adjoint Test2.A in 2.qs:9:0
171+
"#]]
172+
.assert_eq(stack_trace);
172173
}
173174
}
174175
}

0 commit comments

Comments
 (0)