Skip to content

Commit a72a784

Browse files
authored
tools: store the V source line of a C error in a bug_reports.v_lines column (#27342)
1 parent d0637eb commit a72a784

3 files changed

Lines changed: 31 additions & 18 deletions

File tree

‎cmd/tools/modules/vbugreport/c_error_storage.v‎

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@ pub:
99
ccompiler string
1010
error_string string
1111
lines string
12+
v_lines string
1213
}
1314

1415
// new_stored_c_error_report builds the fields stored by the C error report receiver.
16+
// The generated C context is stored in `lines`, while the corresponding V source
17+
// context (the V line that caused the C error and its surrounding lines) is stored
18+
// separately in `v_lines`.
1519
pub fn new_stored_c_error_report(c_file string, target_os string, ccompiler string, c_error string, c_lines []string, v_lines []string) StoredCErrorReport {
1620
return StoredCErrorReport{
1721
c_file_name: normalized_file_name(c_file)
1822
target_os: target_os
1923
ccompiler: ccompiler
2024
error_string: c_error_string(c_error)
21-
lines: c_error_report_lines(c_lines, v_lines)
25+
lines: c_lines.join('\n')
26+
v_lines: v_lines.join('\n')
2227
}
2328
}
2429

@@ -40,17 +45,6 @@ fn c_error_string(c_output string) string {
4045
return ''
4146
}
4247

43-
fn c_error_report_lines(c_lines []string, v_lines []string) string {
44-
mut lines := []string{cap: c_lines.len + v_lines.len}
45-
for line in c_lines {
46-
lines << line
47-
}
48-
for line in v_lines {
49-
lines << line
50-
}
51-
return lines.join('\n')
52-
}
53-
5448
fn normalized_error_string(trimmed string, lower string) ?string {
5549
if lower.starts_with('fatal error:') || lower.starts_with('fatal error ') {
5650
return 'error: ${trimmed}'

‎cmd/tools/modules/vbugreport/c_error_storage_test.v‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ fn test_new_stored_c_error_report_extracts_sql_fields() {
1212
assert report.target_os == 'linux'
1313
assert report.ccompiler == 'clang'
1414
assert report.error_string == 'error: unknown type name "Foo"'
15-
assert report.lines == 'void main__main(void) {\n\tFoo x;\nfoo := Foo{}'
15+
assert report.lines == 'void main__main(void) {\n\tFoo x;'
16+
assert report.v_lines == 'foo := Foo{}'
1617
}
1718

1819
fn test_new_stored_c_error_report_handles_windows_c_file_path() {

‎cmd/tools/vbug-report.v‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ fn connect_db(db_path string) !sqlite.DB {
188188
}
189189

190190
fn init_db(db sqlite.DB) ! {
191-
db.exec('create table if not exists bug_reports (
191+
db.exec("create table if not exists bug_reports (
192192
id text primary key,
193193
delete_token text not null,
194194
created_at text not null,
@@ -198,12 +198,29 @@ fn init_db(db sqlite.DB) ! {
198198
target_os text not null,
199199
ccompiler text not null,
200200
error_string text not null,
201-
lines text not null
202-
)')!
201+
lines text not null,
202+
v_lines text not null default ''
203+
)")!
204+
// Add columns that were introduced after the table already existed, so older
205+
// databases pick them up without losing their stored reports.
206+
ensure_column(db, 'bug_reports', 'v_lines', "text not null default ''")!
203207
db.exec('create index if not exists idx_bug_reports_created_at
204208
on bug_reports(created_at)')!
205209
}
206210

211+
// ensure_column adds `column` to `table` when it is not present yet. SQLite has no
212+
// `add column if not exists`, so the existing columns are inspected first.
213+
fn ensure_column(db sqlite.DB, table string, column string, definition string) ! {
214+
rows := db.exec('pragma table_info(${table})')!
215+
for row in rows {
216+
// pragma table_info columns are: cid, name, type, notnull, dflt_value, pk
217+
if row.vals.len > 1 && row.vals[1] == column {
218+
return
219+
}
220+
}
221+
db.exec('alter table ${table} add column ${column} ${definition}')!
222+
}
223+
207224
// create stores a compiler bug report and returns its deletion token.
208225
@['/bug-report'; post]
209226
pub fn (mut app App) create(mut ctx Context) veb.Result {
@@ -227,8 +244,8 @@ pub fn (mut app App) create(mut ctx Context) veb.Result {
227244
delete_token := rand.uuid_v4()
228245
app.db.exec_param_many('insert into bug_reports (
229246
id, delete_token, created_at, remote_ip, user_agent,
230-
c_file_name, target_os, ccompiler, error_string, lines
231-
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
247+
c_file_name, target_os, ccompiler, error_string, lines, v_lines
248+
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
232249
id,
233250
delete_token,
234251
time.utc().format_rfc3339(),
@@ -239,6 +256,7 @@ pub fn (mut app App) create(mut ctx Context) veb.Result {
239256
stored_report.ccompiler,
240257
stored_report.error_string,
241258
stored_report.lines,
259+
stored_report.v_lines,
242260
]) or { return ctx.server_error('could not store report') }
243261
return ctx.json(CreateBugReportResponse{
244262
id: id

0 commit comments

Comments
 (0)