Skip to content

Commit c4f6b56

Browse files
feat(sourcemaps): Improve sourcemaps resolve command output (#1880)
This PR makes two improvements to the sourcemaps resolve command output: - The PR changes the output line and column values from zero-indexed to one-indexed values. By switching to one-indexed values, the output line and column numbers use the same scale as the input values and follow the standard convention for line and column numbers in source code files. This change fixes the off-by-one error reported in Source mapping is offset when using switch statements #1863. - The output text has been restructured and clarified to indicate that the sourcemap resolver locates the closest token to the line and column input that the user provides. With this change, it should be clear to users that the source and minified file line/column locations reported in the output are the locations of this nearest token that the sourcemap resolver locates. This change is specifically intended to help avoid confusion in cases where the nearest token may in a different location (perhaps even, on a different line) than the search location provided in the user's input. Fixes GH-1863
1 parent 627559b commit c4f6b56

File tree

2 files changed

+71
-27
lines changed

2 files changed

+71
-27
lines changed

src/commands/sourcemaps/resolve.rs

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::cmp;
12
use std::fs;
23
use std::path::PathBuf;
34

@@ -73,28 +74,65 @@ pub fn print_source(token: &Token<'_>, view: &SourceView) {
7374
}
7475
}
7576

77+
fn dst_location(token: &Token) -> (u32, u32) {
78+
(token.get_dst_line() + 1, token.get_dst_col() + 1)
79+
}
80+
81+
fn src_location(token: &Token) -> (u32, u32) {
82+
(token.get_src_line() + 1, token.get_src_col() + 1)
83+
}
84+
85+
fn as_string_len<T: ToString>(to_string: T) -> usize {
86+
to_string.to_string().len()
87+
}
88+
7689
fn print_token(token: &Token<'_>) {
77-
if let Some(name) = token.get_name() {
78-
println!(" name: {name:?}");
79-
} else {
80-
println!(" name: not found");
81-
}
82-
if let Some(source) = token.get_source() {
83-
println!(" source file: {source:?}");
84-
} else {
85-
println!(" source file: not found");
86-
}
87-
println!(" source line: {}", token.get_src_line());
88-
println!(" source column: {}", token.get_src_col());
89-
println!(" minified line: {}", token.get_dst_line());
90-
println!(" minified column: {}", token.get_dst_col());
90+
let token_display_name = match token.get_name() {
91+
Some(name) => format!("token \"{name}\""),
92+
None => String::from("token (unnamed)"),
93+
};
94+
let source_file = match token.get_source() {
95+
Some(file) => format!("{file:>4}"),
96+
None => String::from("(unknown path)"),
97+
};
98+
99+
let (dst_line, dst_col) = dst_location(token);
100+
let [dst_line_digits, dst_col_digits] = [dst_line, dst_col].map(as_string_len);
101+
102+
let (src_line, src_col) = src_location(token);
103+
let [src_line_digits, src_col_digits] = [src_line, src_col].map(as_string_len);
104+
105+
let line_align = cmp::max(dst_line_digits, src_line_digits);
106+
let col_align = cmp::max(dst_col_digits, src_col_digits);
107+
108+
let output_minified_line = format!(
109+
"Found the nearest {token_display_name} at line {:>line_align$}, column {:>col_align$} in the minified file.",
110+
dst_line,
111+
dst_col,
112+
);
113+
114+
let output_source_line = format!(
115+
"- The same token is located at line {:>line_align$}, column {:>col_align$} in source file {}.",
116+
src_line,
117+
src_col,
118+
source_file,
119+
);
120+
121+
let output_minified_line_align = 2 + output_minified_line.len();
122+
let output_source_line_align = output_minified_line.len() + source_file.len() - 3;
123+
124+
println!("{output_minified_line:>output_minified_line_align$}");
125+
println!();
126+
println!("{output_source_line:>output_source_line_align$}");
127+
println!("\n");
128+
91129
if let Some(view) = token.get_source_view() {
92-
println!(" source code:");
130+
println!(" Source code:");
93131
print_source(token, view);
94132
} else if token.get_source_view().is_none() {
95-
println!(" cannot find source");
133+
println!(" Cannot find source");
96134
} else {
97-
println!(" cannot find source line");
135+
println!(" Cannot find source line");
98136
}
99137
}
100138

@@ -112,14 +150,19 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
112150
};
113151
println!("source map path: {sourcemap_path:?}");
114152
println!("source map type: {ty}");
153+
println!();
115154

116155
// perform a lookup
117156
if let Some((line, column)) = lookup_pos(matches) {
118-
println!("lookup line: {line}, column: {column}:");
157+
println!(
158+
"Searching for token nearest to line {}, column {} in the minified file:\n",
159+
line + 1,
160+
column + 1
161+
);
119162
if let Some(token) = sm.lookup_token(line, column) {
120163
print_token(&token);
121164
} else {
122-
println!(" - no match");
165+
println!(" - no token found!");
123166
}
124167
}
125168

tests/integration/_cases/sourcemaps/sourcemaps-resolve.trycmd

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ $ sentry-cli sourcemaps resolve tests/integration/_fixtures/bundle.min.js.map -l
33
? success
44
source map path: "tests/integration/_fixtures/bundle.min.js.map"
55
source map type: regular
6-
lookup line: 0, column: 39:
7-
name: "bar"
8-
source file: "webpack://webpack-plugin/./src/app.js"
9-
source line: 1
10-
source column: 2
11-
minified line: 0
12-
minified column: 39
13-
source code:
6+
7+
Searching for token nearest to line 1, column 40 in the minified file:
8+
9+
Found the nearest token "bar" at line 1, column 40 in the minified file.
10+
11+
- The same token is located at line 2, column 3 in source file webpack://webpack-plugin/./src/app.js.
12+
13+
14+
Source code:
1415
function foo(msg) {
1516
bar(msg);
1617
}

0 commit comments

Comments
 (0)