fix: resolve clippy warnings and missing struct fields in tests

This commit is contained in:
t8y2
2026-06-16 00:55:32 +08:00
parent 5f870be0d9
commit c57e18bf3e
17 changed files with 49 additions and 30 deletions
+4 -6
View File
@@ -47,6 +47,7 @@ fn provider_supports_function_calling(config: &AiConfig) -> bool {
///
/// If the provider does not support function calling (e.g., Ollama), automatically
/// degrades to a text-only completion with schema context injected into the system prompt.
#[allow(clippy::too_many_arguments)]
pub async fn run_agent_loop(
config: &AiConfig,
system_prompt: &str,
@@ -300,7 +301,7 @@ async fn stream_with_tools(
return Err("Agent loop cancelled".to_string());
}
ai::stream_with_tools(config, request, session_id, &tools, cancelled, on_chunk).await
ai::stream_with_tools(config, request, session_id, tools, cancelled, on_chunk).await
}
fn is_context_length_error(error: &str) -> bool {
@@ -324,6 +325,7 @@ fn is_context_length_error(error: &str) -> bool {
///
/// Injects database schema context into the system prompt so the LLM can still
/// give informed answers, then performs a single non-streaming completion.
#[allow(clippy::too_many_arguments)]
async fn run_agent_loop_text_only(
config: &AiConfig,
system_prompt: &str,
@@ -453,16 +455,12 @@ fn context_window_for_model(model: &str) -> u32 {
if m.contains("gpt-4.1") {
return 1_000_000;
}
if m.contains("claude") {
200_000
} else if m.contains("o1") || m.starts_with("o3") || m.starts_with("o4") {
if m.contains("claude") || m.contains("o1") || m.starts_with("o3") || m.starts_with("o4") {
200_000
} else if m.contains("gpt-4") {
128_000
} else if m.contains("gemini") {
1_000_000
} else if m.contains("deepseek") || m.contains("qwen") {
128_000
} else {
128_000
}
+22 -6
View File
@@ -280,7 +280,7 @@ pub fn resolve_model_list_endpoint(config: &AiConfig) -> Result<String, String>
.unwrap_or(ep)
.trim_end_matches('/');
let base = ensure_openai_version_prefix(&base);
let base = ensure_openai_version_prefix(base);
Ok(format!("{base}/models"))
}
@@ -1351,6 +1351,12 @@ pub struct StreamingToolCallAccumulator {
ordered_indices: Vec<u32>,
}
impl Default for StreamingToolCallAccumulator {
fn default() -> Self {
Self::new()
}
}
impl StreamingToolCallAccumulator {
pub fn new() -> Self {
Self { calls: std::collections::HashMap::new(), ordered_indices: Vec::new() }
@@ -1417,7 +1423,7 @@ async fn stream_claude_with_tools(
if !pending_tool_results.is_empty() {
messages.push(json!({
"role": "user",
"content": pending_tool_results.drain(..).collect::<Vec<_>>()
"content": std::mem::take(&mut pending_tool_results)
}));
}
if m.role == "assistant" && !m.tool_calls.is_empty() {
@@ -1439,7 +1445,7 @@ async fn stream_claude_with_tools(
if !pending_tool_results.is_empty() {
messages.push(json!({
"role": "user",
"content": pending_tool_results.drain(..).collect::<Vec<_>>()
"content": std::mem::take(&mut pending_tool_results)
}));
}
@@ -1739,7 +1745,7 @@ async fn stream_gemini_with_tools(
.tool_call_id
.as_deref()
.and_then(|s| s.strip_prefix("gemini-tc-"))
.and_then(|s| s.rsplitn(2, '-').nth(1))
.and_then(|s| s.rsplit_once('-').map(|x| x.0))
.unwrap_or("unknown");
pending_function_responses.push(json!({
"functionResponse": {
@@ -1752,7 +1758,7 @@ async fn stream_gemini_with_tools(
if !pending_function_responses.is_empty() {
contents.push(json!({
"role": "user",
"parts": pending_function_responses.drain(..).collect::<Vec<_>>()
"parts": std::mem::take(&mut pending_function_responses)
}));
}
if m.role == "assistant" && !m.tool_calls.is_empty() {
@@ -1774,7 +1780,7 @@ async fn stream_gemini_with_tools(
if !pending_function_responses.is_empty() {
contents.push(json!({
"role": "user",
"parts": pending_function_responses.drain(..).collect::<Vec<_>>()
"parts": std::mem::take(&mut pending_function_responses)
}));
}
@@ -2008,6 +2014,7 @@ mod tests {
proxy_enabled: true,
proxy_url: "not a proxy url".to_string(),
enable_thinking: true,
context_window: None,
};
let err = build_ai_http_client(&config, 1).unwrap_err();
@@ -2027,6 +2034,7 @@ mod tests {
proxy_enabled: true,
proxy_url: "127.0.0.1:7890".to_string(),
enable_thinking: true,
context_window: None,
};
build_ai_http_client(&config, 1).unwrap();
@@ -2044,6 +2052,7 @@ mod tests {
proxy_enabled: true,
proxy_url: "not a proxy url".to_string(),
enable_thinking: true,
context_window: None,
};
build_ai_http_client(&config, 1).unwrap();
@@ -2061,6 +2070,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
assert_eq!(
@@ -2078,6 +2088,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
assert_eq!(resolve_endpoint(&ollama), "http://localhost:11434/v1/chat/completions");
@@ -2096,6 +2107,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
assert_eq!(resolve_model_list_endpoint(&openai).unwrap(), "https://api.openai.com/v1/models");
@@ -2109,6 +2121,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
assert_eq!(resolve_model_list_endpoint(&claude).unwrap(), "https://api.anthropic.com/v1/models");
}
@@ -2126,6 +2139,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
assert_eq!(resolve_endpoint(&config), "https://api.example.com/v1/chat/completions");
assert_eq!(resolve_model_list_endpoint(&config).unwrap(), "https://api.example.com/v1/models");
@@ -2178,6 +2192,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
let api_key_headers = claude_headers(&config).unwrap();
@@ -2233,6 +2248,7 @@ mod tests {
proxy_enabled: false,
proxy_url: String::new(),
enable_thinking: true,
context_window: None,
};
assert!(!supports_temperature(&config));
+3 -3
View File
@@ -523,7 +523,7 @@ static NULL_VALUE: Value = Value::Null;
type CompareRowValues = Vec<Value>;
type CompareRowMap = HashMap<String, CompareRowValues>;
fn column_index_map<'a>(columns: &'a [String]) -> HashMap<&'a str, usize> {
fn column_index_map(columns: &[String]) -> HashMap<&str, usize> {
let mut indexes = HashMap::with_capacity(columns.len());
for (index, column) in columns.iter().enumerate() {
indexes.insert(column.as_str(), index);
@@ -688,7 +688,7 @@ fn generate_data_sync_statements(options: &GenerateDataSyncSqlOptions<'_>) -> Ve
.join(", ");
format!(
"UPDATE {table} SET {assignments} WHERE {};",
where_by_key(&row.key_values, &options.key_columns, options.database_type, column_info)
where_by_key(&row.key_values, options.key_columns, options.database_type, column_info)
)
})
.collect::<Vec<_>>();
@@ -699,7 +699,7 @@ fn generate_data_sync_statements(options: &GenerateDataSyncSqlOptions<'_>) -> Ve
.map(|row| {
format!(
"DELETE FROM {table} WHERE {};",
where_by_key(&row.key_values, &options.key_columns, options.database_type, column_info)
where_by_key(&row.key_values, options.key_columns, options.database_type, column_info)
)
})
.collect::<Vec<_>>();
@@ -429,10 +429,7 @@ fn elasticsearch_query_from_document_filter(filter: Option<&str>) -> Result<Opti
};
let value: serde_json::Value = serde_json::from_str(filter).map_err(|e| format!("Invalid filter JSON: {e}"))?;
let query = translate_document_filter_value(&value)?;
Ok(match query {
Some(query) => Some(query),
None => None,
})
Ok(query)
}
fn translate_document_filter_value(value: &serde_json::Value) -> Result<Option<serde_json::Value>, String> {
+3 -3
View File
@@ -2160,7 +2160,7 @@ mod tests {
let escaped = pg_quote_ident(malicious);
// Double quotes should be doubled, not breaking out
assert_eq!(escaped, r#""public""; DROP TABLE users; --""#);
assert!(escaped.matches('"').count() % 2 == 0, "quote count should be even");
assert!(escaped.matches('"').count().is_multiple_of(2), "quote count should be even");
}
// --- query_result_row_limit ---
@@ -2479,14 +2479,14 @@ mod tests {
#[tokio::test]
async fn execute_batch_whitespace_only_is_filtered() {
let statements = vec![" ".to_string(), "\t\n".to_string(), "".to_string()];
let statements = [" ".to_string(), "\t\n".to_string(), "".to_string()];
let combined = statements.iter().map(|s| s.trim()).filter(|s| !s.is_empty()).collect::<Vec<_>>().join(";\n");
assert!(combined.is_empty());
}
#[test]
fn execute_batch_joins_with_semicolons() {
let statements = vec!["SELECT 1".to_string(), "SELECT 2".to_string()];
let statements = ["SELECT 1".to_string(), "SELECT 2".to_string()];
let combined = statements.iter().map(|s| s.trim()).filter(|s| !s.is_empty()).collect::<Vec<_>>().join(";\n");
assert_eq!(combined, "SELECT 1;\nSELECT 2");
}
+1
View File
@@ -56,6 +56,7 @@ fn ssh_client_config() -> Config {
Config { nodelay: true, keepalive_interval: Some(Duration::from_secs(30)), preferred, ..Default::default() }
}
#[allow(clippy::too_many_arguments)]
async fn connect_and_authenticate(
ssh_host: &str,
ssh_port: u16,
+1
View File
@@ -109,6 +109,7 @@ pub async fn document_find_documents_core(
}
}
#[allow(clippy::too_many_arguments)]
pub async fn mongo_find_documents_core(
state: &AppState,
connection_id: &str,
+1
View File
@@ -89,6 +89,7 @@ pub async fn redis_scan_keys_batch_core(
}
}
#[allow(clippy::too_many_arguments)]
pub async fn redis_scan_values_core(
state: &AppState,
connection_id: &str,
+1 -1
View File
@@ -1302,7 +1302,7 @@ fn merge_optional_string(target: &mut Option<String>, candidate: Option<String>)
}
return;
}
if target.as_ref().map_or(true, |value| value.trim().is_empty()) {
if target.as_ref().is_none_or(|value| value.trim().is_empty()) {
*target = Some(candidate);
}
}
+5 -2
View File
@@ -1029,6 +1029,7 @@ fn table_comment_sql(table_name: &str, comment: &str, db_type: DatabaseType, sch
}
}
#[allow(clippy::too_many_arguments)]
pub fn generate_schema_sync_sql(
diffs: &[TableDiff],
function_diffs: &[FunctionDiff],
@@ -1185,8 +1186,10 @@ pub fn generate_schema_sync_sql(
if let Some(foreign_keys) = &diff.foreign_keys {
for fk in foreign_keys {
if (fk.diff_type == "added" || fk.diff_type == "modified") && fk.source.is_some() {
lines.push(add_foreign_key_sql(&diff.name, fk.source.as_ref().unwrap(), db_type, schema));
if fk.diff_type == "added" || fk.diff_type == "modified" {
if let Some(source) = &fk.source {
lines.push(add_foreign_key_sql(&diff.name, source, db_type, schema));
}
}
}
}
@@ -365,5 +365,5 @@ pub(super) fn build_questdb_table_select_sql(
return format!("SELECT {columns_sql} FROM {table}{where_clause}{order_by} LIMIT {limit}");
}
let upper_bound = offset + limit;
return format!("SELECT {columns_sql} FROM {table}{where_clause}{order_by} LIMIT {offset}, {upper_bound}");
format!("SELECT {columns_sql} FROM {table}{where_clause}{order_by} LIMIT {offset}, {upper_bound}")
}
@@ -194,9 +194,7 @@ pub(super) fn build_add_column_sql(
table_name: &str,
) -> Vec<String> {
let definition = column_definition(dialect, column);
let mut statements = if dialect == StructureDialect::Oracle {
vec![format!("ALTER TABLE {table} ADD ({definition});")]
} else if dialect == StructureDialect::Informix {
let mut statements = if dialect == StructureDialect::Oracle || dialect == StructureDialect::Informix {
vec![format!("ALTER TABLE {table} ADD ({definition});")]
} else {
let add_keyword = if dialect == StructureDialect::SqlServer { "ADD" } else { "ADD COLUMN" };
+1 -1
View File
@@ -609,7 +609,7 @@ pub fn escape_value_typed(val: &serde_json::Value, db_type: &DatabaseType, colum
serde_json::Value::Number(n) => match db_type {
DatabaseType::Mysql | DatabaseType::Doris | DatabaseType::StarRocks => {
if column_type.is_some_and(is_mysql_bit_type) {
format!("b'{}'", n.to_string())
format!("b'{}'", n)
} else {
n.to_string()
}
+1
View File
@@ -216,6 +216,7 @@ mod tests {
let state = Arc::new(WebState {
app,
data_dir: dir.clone(),
password_disabled: false,
password_hash: RwLock::new(None),
sessions: RwLock::new(HashSet::new()),
sse_channels: RwLock::new(HashMap::new()),
+1
View File
@@ -52,6 +52,7 @@ pub async fn ai_cancel_stream(session_id: String) -> Result<bool, String> {
}
#[tauri::command]
#[allow(clippy::too_many_arguments)]
pub async fn ai_agent_stream(
app: AppHandle,
state: State<'_, Arc<AppState>>,
+1
View File
@@ -41,6 +41,7 @@ pub async fn redis_scan_keys_batch(
}
#[tauri::command]
#[allow(clippy::too_many_arguments)]
pub async fn redis_scan_values(
state: State<'_, Arc<AppState>>,
connection_id: String,
+1
View File
@@ -6,6 +6,7 @@ pub fn prepare_schema_diff(
}
#[tauri::command]
#[allow(clippy::too_many_arguments)]
pub fn generate_schema_sync_sql(
diffs: Vec<dbx_core::schema_diff::TableDiff>,
function_diffs: Option<Vec<dbx_core::schema_diff::FunctionDiff>>,