style: format the whole tree with cargo fmt (stock defaults, #35)

One-time, mechanical reformat — no functional changes. The tree was not
rustfmt-clean (~1800 hunks across ~100 files); this brings it to stock
`cargo fmt` defaults so a `cargo fmt --check` CI gate can follow.
Behaviour-preserving: 2509 pass / 0 fail / 1 ignored (unchanged baseline),
clippy clean. A .git-blame-ignore-revs entry follows so `git blame`
skips this commit.
This commit is contained in:
claude@clouddev1
2026-06-17 21:39:19 +00:00
parent e9606b5f6d
commit 41b7e9a049
102 changed files with 8017 additions and 4975 deletions
+3 -11
View File
@@ -43,17 +43,11 @@ impl Catalog {
}
}
fn flatten(
value: &serde_norway::Value,
prefix: String,
out: &mut HashMap<String, String>,
) {
fn flatten(value: &serde_norway::Value, prefix: String, out: &mut HashMap<String, String>) {
match value {
serde_norway::Value::Mapping(map) => {
for (k, v) in map {
let k_str = k
.as_str()
.expect("catalog keys must be strings");
let k_str = k.as_str().expect("catalog keys must be strings");
let next = if prefix.is_empty() {
k_str.to_string()
} else {
@@ -85,9 +79,7 @@ pub fn catalog() -> &'static Catalog {
/// See module docs for failure modes.
pub fn translate(key: &str, args: &[(&str, &dyn Display)]) -> String {
let template = catalog().get(key).unwrap_or_else(|| {
panic!(
"missing catalog key: `{key}` (the validator should have caught this)"
);
panic!("missing catalog key: `{key}` (the validator should have caught this)");
});
substitute(template, args, key)
}
+24 -29
View File
@@ -41,8 +41,14 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
("diagnostic.alias_used_as_column", &["name"]),
("diagnostic.ambiguous_column", &["column", "qualifiers"]),
("diagnostic.auto_column_overridden", &["column", "type"]),
("diagnostic.compound_arity_mismatch", &["op", "left_n", "right_n"]),
("diagnostic.cte_arity_mismatch", &["cte", "declared", "actual"]),
(
"diagnostic.compound_arity_mismatch",
&["op", "left_n", "right_n"],
),
(
"diagnostic.cte_arity_mismatch",
&["cte", "declared", "actual"],
),
("diagnostic.duplicate_cte", &["name"]),
("diagnostic.eq_null", &[]),
("diagnostic.insert_arity_mismatch", &["expected", "actual"]),
@@ -63,7 +69,10 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
),
("diagnostic.not_null_missing", &["column"]),
("diagnostic.like_numeric", &["column", "type"]),
("diagnostic.projection_alias_misplaced", &["alias", "clause"]),
(
"diagnostic.projection_alias_misplaced",
&["alias", "clause"],
),
("diagnostic.table_used_as_column", &["name"]),
("diagnostic.type_mismatch", &["column", "type"]),
("diagnostic.unknown_column", &["name", "table"]),
@@ -149,10 +158,7 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
"error.type_mismatch.change_column.headline",
&["table", "column", "src_type", "target_type"],
),
(
"error.type_mismatch.change_column.hint",
&["target_type"],
),
("error.type_mismatch.change_column.hint", &["target_type"]),
(
"error.type_mismatch.insert.headline",
&["value", "expected_type"],
@@ -219,10 +225,7 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
("help.data.explain", &[]),
// ---- Hint panel ambient typing assistance (ADR-0022 §6) ----
("hint.ambient_complete", &[]),
(
"hint.ambient_error_with_usage",
&["message", "usage"],
),
("hint.ambient_error_with_usage", &["message", "usage"]),
("hint.ambient_expected", &["expected"]),
("hint.getting_started", &[]),
("hint.block.heading", &[]),
@@ -404,10 +407,7 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
("hint.cmd.explain_sql.what", &[]),
("hint.cmd.explain_sql.example", &[]),
("hint.cmd.explain_sql.concept", &[]),
(
"hint.ambient_invalid_ident",
&["kind", "found"],
),
("hint.ambient_invalid_ident", &["kind", "found"]),
("hint.ambient_typing_name", &[]),
// Issue #4: introduce the advanced-mode CREATE TABLE element
// slot (`create table T (`) so the otherwise-invisible
@@ -415,10 +415,7 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
("hint.create_table_element", &[]),
("hint.seed_count", &[]),
("hint.value_literal_slot", &[]),
(
"hint.ambient_typing_name_then",
&["next"],
),
("hint.ambient_typing_name_then", &["next"]),
// Per-column-type value-slot hints (ADR-0024 §Phase D).
("hint.value_slot_blob", &[]),
("hint.value_slot_bool", &[]),
@@ -441,7 +438,10 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
("parse.custom.alter_named_unique", &[]),
("parse.custom.bind_type_mismatch", &["found", "expected"]),
("parse.custom.change_column_flags_exclusive", &[]),
("parse.custom.constraint_redundant_on_pk", &["column", "constraint"]),
(
"parse.custom.constraint_redundant_on_pk",
&["column", "constraint"],
),
("parse.custom.create_table_needs_pk", &[]),
("parse.custom.expression_too_deep", &[]),
("parse.custom.insert_form_a_missing_values", &["columns"]),
@@ -576,10 +576,7 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
&["table", "col_count", "col_list", "supplied", "non_auto_csv"],
),
("select.internal_table", &["table"]),
(
"cli.invalid_value",
&["flag", "value", "expected"],
),
("cli.invalid_value", &["flag", "value", "expected"]),
("cli.missing_value", &["flag"]),
("cli.multiple_paths", &["first", "second"]),
("cli.resume_with_path", &[]),
@@ -867,8 +864,7 @@ mod tests {
}
}
let declared: HashSet<&str> =
KEYS_AND_PLACEHOLDERS.iter().map(|(k, _)| *k).collect();
let declared: HashSet<&str> = KEYS_AND_PLACEHOLDERS.iter().map(|(k, _)| *k).collect();
for key in cat.keys() {
if key.starts_with("_test.") {
continue;
@@ -890,9 +886,8 @@ mod tests {
/// Mirror of `tests/engine_vocabulary_audit.rs::FORBIDDEN`,
/// duplicated here so the catalog validator is self-contained
/// (no dependency on the integration-test binary).
const FORBIDDEN_ENGINE_VOCABULARY: &[&str] = &[
"SQLite", "sqlite", "rusqlite", "STRICT", "PRAGMA",
];
const FORBIDDEN_ENGINE_VOCABULARY: &[&str] =
&["SQLite", "sqlite", "rusqlite", "STRICT", "PRAGMA"];
/// Detect a `{name:...}` format-specifier placeholder.
/// Doubled braces `{{` / `}}` are escapes — must skip them.
+2 -2
View File
@@ -34,8 +34,8 @@ pub mod keys;
pub mod translate;
pub use error::{DiagnosticTable, FriendlyError};
pub use format::{catalog, Catalog};
pub use translate::{error_hint_class, FailureContext, Operation, TranslateContext, Verbosity};
pub use format::{Catalog, catalog};
pub use translate::{FailureContext, Operation, TranslateContext, Verbosity, error_hint_class};
// `translate::translate` and `format::translate` are different
// callables — the former is the structured DbError → FriendlyError
+79 -76
View File
@@ -201,11 +201,7 @@ impl TranslateContext {
/// Combine schema-resolved facts with operation and
/// verbosity to build the full translator input.
#[must_use]
pub fn from_facts(
operation: Operation,
verbosity: Verbosity,
facts: FailureContext,
) -> Self {
pub fn from_facts(operation: Operation, verbosity: Verbosity, facts: FailureContext) -> Self {
Self {
operation: Some(operation),
table: facts.table,
@@ -234,15 +230,15 @@ pub fn translate(error: &DbError, ctx: &TranslateContext) -> FriendlyError {
// refusal sites). Catalog entries exist for the typed
// invalid-value cases but the migration sweep
// (ADR-0019 §9) is what wires them. For now, passthrough.
DbError::Unsupported(message) | DbError::InvalidValue(message) => {
passthrough(message)
}
DbError::Unsupported(message) | DbError::InvalidValue(message) => passthrough(message),
DbError::PersistenceFatal { message, .. }
| DbError::RebuildRowFailed { detail: message, .. }
| DbError::RebuildRowFailed {
detail: message, ..
}
| DbError::Io(message) => passthrough(message),
DbError::WorkerGone => passthrough(
"the database worker is no longer available — the application must restart",
),
DbError::WorkerGone => {
passthrough("the database worker is no longer available — the application must restart")
}
};
// Attach the row pinpoint when the runtime resolved one.
// The translator never builds the table itself — it only
@@ -320,11 +316,7 @@ const fn fk_hint_class(ctx: &TranslateContext) -> &'static str {
}
}
fn translate_sqlite(
message: &str,
kind: SqliteErrorKind,
ctx: &TranslateContext,
) -> FriendlyError {
fn translate_sqlite(message: &str, kind: SqliteErrorKind, ctx: &TranslateContext) -> FriendlyError {
// `change column ... --dont-convert` lets the engine
// accept or refuse each cell. Whatever the engine returns
// (constraint, datatype mismatch, …) means "the new type
@@ -392,8 +384,8 @@ fn translate_constraint(message: &str, ctx: &TranslateContext) -> FriendlyError
// ---- UNIQUE -----------------------------------------------------
fn translate_unique(message: &str, ctx: &TranslateContext) -> FriendlyError {
let (table, column) = parse_qualified_target(message)
.unwrap_or_else(|| (ctx_table(ctx), ctx_column(ctx)));
let (table, column) =
parse_qualified_target(message).unwrap_or_else(|| (ctx_table(ctx), ctx_column(ctx)));
let value = ctx_value(ctx);
match ctx.operation {
Some(Operation::Update) => fe(
@@ -405,11 +397,7 @@ fn translate_unique(message: &str, ctx: &TranslateContext) -> FriendlyError {
),
verbose_hint(
ctx,
t!(
"error.unique.update.hint",
table = table,
column = column
),
t!("error.unique.update.hint", table = table, column = column),
),
),
// Default to the INSERT variant — it's the most common
@@ -425,11 +413,7 @@ fn translate_unique(message: &str, ctx: &TranslateContext) -> FriendlyError {
),
verbose_hint(
ctx,
t!(
"error.unique.insert.hint",
table = table,
column = column
),
t!("error.unique.insert.hint", table = table, column = column),
),
),
}
@@ -542,8 +526,8 @@ fn fk_parent_side_update(ctx: &TranslateContext) -> FriendlyError {
// ---- NOT NULL --------------------------------------------------
fn translate_not_null(message: &str, ctx: &TranslateContext) -> FriendlyError {
let (table, column) = parse_qualified_target(message)
.unwrap_or_else(|| (ctx_table(ctx), ctx_column(ctx)));
let (table, column) =
parse_qualified_target(message).unwrap_or_else(|| (ctx_table(ctx), ctx_column(ctx)));
match ctx.operation {
Some(Operation::Update) => fe(
t!(
@@ -576,9 +560,17 @@ fn translate_check(_message: &str, ctx: &TranslateContext) -> FriendlyError {
let column = ctx_column(ctx);
let is_update = matches!(ctx.operation, Some(Operation::Update));
let headline = if is_update {
t!("error.check.update.headline", table = table, column = column)
t!(
"error.check.update.headline",
table = table,
column = column
)
} else {
t!("error.check.insert.headline", table = table, column = column)
t!(
"error.check.insert.headline",
table = table,
column = column
)
};
let hint = ctx.check_rule.as_ref().map_or_else(
|| {
@@ -613,8 +605,7 @@ fn translate_check(_message: &str, ctx: &TranslateContext) -> FriendlyError {
// ---- not_found / already_exists --------------------------------
fn translate_not_found_table(message: &str, ctx: &TranslateContext) -> FriendlyError {
let name = parse_after_colon(message)
.map_or_else(|| ctx_table(ctx), str::to_string);
let name = parse_after_colon(message).map_or_else(|| ctx_table(ctx), str::to_string);
headline_only(t!("error.not_found.table.headline", name = name))
}
@@ -656,17 +647,11 @@ fn translate_already_exists(message: &str, ctx: &TranslateContext) -> FriendlyEr
column = column
));
}
return headline_only(t!(
"error.already_exists.table.headline",
name = name
));
return headline_only(t!("error.already_exists.table.headline", name = name));
}
// No backticks — engine-style "table T already exists".
if let Some(name) = parse_after_word(message, "table") {
return headline_only(t!(
"error.already_exists.table.headline",
name = name
));
return headline_only(t!("error.already_exists.table.headline", name = name));
}
if let Some(name) = parse_after_word(message, "relationship") {
return headline_only(t!(
@@ -696,36 +681,25 @@ fn translate_generic(message: &str, ctx: &TranslateContext) -> FriendlyError {
if lower.contains("misuse of aggregate") {
return headline_only(t!("engine.aggregate_misuse", name = "?"));
}
if lower.contains("group by")
|| lower.contains("must appear in")
{
if lower.contains("group by") || lower.contains("must appear in") {
return headline_only(t!("engine.group_by_required"));
}
if (lower.contains("union")
|| lower.contains("intersect")
|| lower.contains("except"))
if (lower.contains("union") || lower.contains("intersect") || lower.contains("except"))
&& lower.contains("result columns")
{
// Last-resort safety net — the pre-flight pass in 2d.1
// catches this in most cases; if the engine surfaces it
// anyway, route it through the engine-neutral key.
return headline_only(t!(
"engine.compound_arity_mismatch",
op = "set operator"
));
return headline_only(t!("engine.compound_arity_mismatch", op = "set operator"));
}
if lower.contains("scalar subquery") || lower.contains("more than one row") {
return headline_only(t!("engine.scalar_subquery_too_many_rows"));
}
if lower.contains("recursive")
&& (lower.contains("cte") || lower.contains("union"))
{
if lower.contains("recursive") && (lower.contains("cte") || lower.contains("union")) {
return headline_only(t!("engine.recursive_cte_malformed"));
}
let operation = ctx
.operation
.map_or("operation", Operation::keyword);
let operation = ctx.operation.map_or("operation", Operation::keyword);
// F2 (ADR-0035 Amendment 1): when no table is in context, use the
// table-less hint so a contextless `friendly_message()` (replay, undo,
// rebuild, export) never renders a literal `{table}` placeholder.
@@ -789,23 +763,33 @@ fn ctx_table(ctx: &TranslateContext) -> String {
}
fn ctx_column(ctx: &TranslateContext) -> String {
ctx.column.clone().unwrap_or_else(|| "the column".to_string())
ctx.column
.clone()
.unwrap_or_else(|| "the column".to_string())
}
fn ctx_value(ctx: &TranslateContext) -> String {
ctx.value.clone().unwrap_or_else(|| "that value".to_string())
ctx.value
.clone()
.unwrap_or_else(|| "that value".to_string())
}
fn ctx_parent_table(ctx: &TranslateContext) -> String {
ctx.parent_table.clone().unwrap_or_else(|| "the referenced table".to_string())
ctx.parent_table
.clone()
.unwrap_or_else(|| "the referenced table".to_string())
}
fn ctx_parent_column(ctx: &TranslateContext) -> String {
ctx.parent_column.clone().unwrap_or_else(|| "the referenced column".to_string())
ctx.parent_column
.clone()
.unwrap_or_else(|| "the referenced column".to_string())
}
fn ctx_child_table(ctx: &TranslateContext) -> String {
ctx.child_table.clone().unwrap_or_else(|| "the referencing table".to_string())
ctx.child_table
.clone()
.unwrap_or_else(|| "the referencing table".to_string())
}
/// Extract `T.col` from a message like
@@ -847,11 +831,7 @@ fn parse_after_word<'a>(message: &'a str, keyword: &str) -> Option<&'a str> {
let rest = message[pos..].trim_start();
let token_end = rest.find(|c: char| c.is_whitespace()).unwrap_or(rest.len());
let token = rest[..token_end].trim_matches(|c: char| c == '`' || c == '\'');
if token.is_empty() {
None
} else {
Some(token)
}
if token.is_empty() { None } else { Some(token) }
}
#[cfg(test)]
@@ -876,15 +856,24 @@ mod tests {
};
let d = TranslateContext::default;
assert_eq!(
error_hint_class(&sqlite(SqliteErrorKind::NoSuchTable, "no such table: X"), &d()),
error_hint_class(
&sqlite(SqliteErrorKind::NoSuchTable, "no such table: X"),
&d()
),
Some("not_found")
);
assert_eq!(
error_hint_class(&sqlite(SqliteErrorKind::NoSuchColumn, "no such column: X"), &d()),
error_hint_class(
&sqlite(SqliteErrorKind::NoSuchColumn, "no such column: X"),
&d()
),
Some("not_found")
);
assert_eq!(
error_hint_class(&sqlite(SqliteErrorKind::AlreadyExists, "already exists"), &d()),
error_hint_class(
&sqlite(SqliteErrorKind::AlreadyExists, "already exists"),
&d()
),
Some("already_exists")
);
assert_eq!(
@@ -933,13 +922,19 @@ mod tests {
parent_table: Some("Parent".to_string()),
..TranslateContext::default()
};
assert_eq!(error_hint_class(&fk(), &ctx), Some("foreign_key.child_side"));
assert_eq!(
error_hint_class(&fk(), &ctx),
Some("foreign_key.child_side")
);
// child_table populated → parent-side.
let ctx = TranslateContext {
child_table: Some("Child".to_string()),
..TranslateContext::default()
};
assert_eq!(error_hint_class(&fk(), &ctx), Some("foreign_key.parent_side"));
assert_eq!(
error_hint_class(&fk(), &ctx),
Some("foreign_key.parent_side")
);
// No enrichment: operation is the tiebreaker.
assert_eq!(
error_hint_class(&fk(), &ctx_with(Operation::Delete)),
@@ -1049,14 +1044,22 @@ mod tests {
ctx.parent_column = Some("country, code".to_string());
ctx.value = Some("7, 8".to_string());
let f = translate(&err, &ctx);
assert!(f.headline.contains("no parent row"), "child-side: {}", f.headline);
assert!(
f.headline.contains("no parent row"),
"child-side: {}",
f.headline
);
assert!(f.headline.contains("Region"));
assert!(
f.headline.contains("country, code"),
"both parent columns must appear: {}",
f.headline
);
assert!(f.headline.contains("`7, 8`"), "joined value: {}", f.headline);
assert!(
f.headline.contains("`7, 8`"),
"joined value: {}",
f.headline
);
}
#[test]