#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TypeMismatchDiagnostic {
pub location: String,
pub expected: String,
pub found: String,
pub suggestion: String,
}
impl TypeMismatchDiagnostic {
pub fn new(location: &str, expected: &str, found: &str, suggestion: &str) -> Self {
Self {
location: location.to_string(),
expected: expected.to_string(),
found: found.to_string(),
suggestion: suggestion.to_string(),
}
}
pub fn format_error(&self) -> String {
format!(
"类型不匹配:{} 期望 `{}`,但发现 `{}`\n help: {}",
self.location, self.expected, self.found, self.suggestion
)
}
}
pub mod suggestions {
pub const TYPE_MISMATCH_EQ: &str = "请使用 Cast 显式转换,或检查列归属表";
pub const NON_BOOLEAN_LOGIC: &str = "逻辑组合操作要求 Bool 类型,请检查表达式是否为比较操作";
pub const CROSS_TABLE_REFERENCE: &str = "列不属于当前查询的表,请检查列归属表或使用 JOIN";
pub const INVALID_CAST: &str = "该类型转换不受支持,请检查 SqlType 兼容性";
pub const NON_JSON_COLUMN: &str = "JSON 操作符要求列的 SqlType 为 Json,请检查列定义";
}
pub fn strip_quotes(s: &str) -> &str {
if s.starts_with('"') && s.ends_with('"') && s.len() >= 2 {
&s[1..s.len() - 1]
} else {
s
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_diagnostic_location() {
let d = TypeMismatchDiagnostic::new("users.age", "i64", "String", "使用 Cast 转换");
assert_eq!(d.location, "users.age");
}
#[test]
fn test_diagnostic_expected_type() {
let d = TypeMismatchDiagnostic::new("col", "Bool", "i64", "使用 Cast 转换");
assert_eq!(d.expected, "Bool");
}
#[test]
fn test_diagnostic_found_type() {
let d = TypeMismatchDiagnostic::new("col", "Bool", "i64", "使用 Cast 转换");
assert_eq!(d.found, "i64");
}
#[test]
fn test_diagnostic_suggestion() {
let d = TypeMismatchDiagnostic::new("col", "Bool", "i64", "使用 Cast 转换");
assert_eq!(d.suggestion, "使用 Cast 转换");
}
#[test]
fn test_diagnostic_format_error() {
let d = TypeMismatchDiagnostic::new("users.age", "i64", "String", "使用 Cast 转换");
let msg = d.format_error();
assert!(msg.contains("类型不匹配"));
assert!(msg.contains("users.age"));
assert!(msg.contains("i64"));
assert!(msg.contains("String"));
assert!(msg.contains("使用 Cast 转换"));
assert!(msg.contains("help:"));
}
#[test]
fn test_suggestion_type_mismatch_eq() {
assert!(suggestions::TYPE_MISMATCH_EQ.contains("Cast"));
}
#[test]
fn test_suggestion_non_boolean_logic() {
assert!(suggestions::NON_BOOLEAN_LOGIC.contains("Bool"));
}
#[test]
fn test_suggestion_cross_table_reference() {
assert!(suggestions::CROSS_TABLE_REFERENCE.contains("JOIN"));
}
#[test]
fn test_suggestion_invalid_cast() {
assert!(suggestions::INVALID_CAST.contains("类型转换"));
}
#[test]
fn test_suggestion_non_json_column() {
assert!(suggestions::NON_JSON_COLUMN.contains("Json"));
}
#[test]
fn test_strip_quotes_with_quotes() {
assert_eq!(strip_quotes("\"hello\""), "hello");
}
#[test]
fn test_strip_quotes_without_quotes() {
assert_eq!(strip_quotes("hello"), "hello");
}
#[test]
fn test_strip_quotes_empty() {
assert_eq!(strip_quotes(""), "");
}
}