chore: 修复编译警告和错误

- 修复 Tauri v2 API 兼容性问题(注释掉使用旧 API 的通知功能)
- 清理未使用的导入(18 个)和变量
- 为预留的结构体/trait 添加 #[allow(dead_code)] 属性
- 为测试模块添加模块级别 #![allow(dead_code)] 以保留 proptest 辅助函数
- 修复 proptest 宏外部的文档注释(改为普通注释)
- 删除未使用的测试辅助函数 arb_tool_call_count
- 处理未使用的 Result 返回值(添加 let _ = 前缀)

cargo check --all-targets --all-features 现已通过,无警告
This commit is contained in:
lwmacct
2026-01-11 16:49:43 +08:00
parent 98a04d26da
commit 933b660332
43 changed files with 112 additions and 94 deletions
+4 -1
View File
@@ -36,13 +36,16 @@ docs/prd/
**/.venv/
**/.conda/
# 生成物
src-tauri/gen
# Local env files
.env
.env.*
!.env.example
# IDEs 和 编辑器
# .claude/
.claude/
.playwright-mcp/
# lwmacct preference
+1
View File
@@ -117,3 +117,4 @@ tempfile = "3"
[features]
default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]
notification = [] # 预留特性:系统通知功能
-1
View File
@@ -938,7 +938,6 @@ impl NativeAgentState {
#[cfg(test)]
mod tests {
use super::*;
use crate::agent::parsers::OpenAISSEParser;
#[test]
-5
View File
@@ -740,11 +740,6 @@ mod proptests {
"[a-zA-Z0-9 ]{1,50}".prop_map(|s| s)
}
/// 生成工具调用数量
fn arb_tool_call_count() -> impl Strategy<Value = usize> {
1..=5usize
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
+2 -1
View File
@@ -652,7 +652,7 @@ mod tests {
assert!(end <= 100);
// 指定起始行
let (start, end) = calculate_line_range(100, Some(50), None);
let (start, _end) = calculate_line_range(100, Some(50), None);
assert_eq!(start, 50);
// 指定结束行
@@ -723,6 +723,7 @@ mod tests {
#[cfg(test)]
mod proptests {
#![allow(dead_code)]
use super::*;
use proptest::prelude::*;
use std::fs;
+1
View File
@@ -490,6 +490,7 @@ mod tests {
#[cfg(test)]
mod proptests {
#![allow(dead_code)]
use super::*;
use crate::agent::tools::read_file::ReadFileTool;
use proptest::prelude::*;
+1 -1
View File
@@ -3,7 +3,7 @@
//! 包含 Tauri 应用的主入口函数和命令注册。
use std::sync::Arc;
use tauri::{Emitter, Listener, Manager};
use tauri::Manager;
use crate::commands;
use crate::tray::{TrayIconStatus, TrayManager, TrayStateSnapshot};
@@ -1,4 +1,4 @@
use crate::browser_interceptor::{BrowserInterceptorError, InterceptedUrl, Result};
use crate::browser_interceptor::{InterceptedUrl, Result};
/// Linux 平台的浏览器拦截器
pub struct LinuxInterceptor {
@@ -60,7 +60,7 @@ impl LinuxInterceptor {
impl Drop for LinuxInterceptor {
fn drop(&mut self) {
if self.running {
tokio::runtime::Handle::try_current().map(|handle| {
let _ = tokio::runtime::Handle::try_current().map(|handle| {
handle.block_on(async {
let _ = self.stop().await;
let _ = self.restore_system_defaults().await;
+2
View File
@@ -209,6 +209,7 @@ pub async fn set_auto_launch(app: AppHandle, enabled: bool) -> Result<bool, Stri
/// 配置导出选项
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct ExportOptions {
/// 是否脱敏敏感信息(API 密钥等)
pub redact_secrets: bool,
@@ -251,6 +252,7 @@ pub fn export_config(config: Config, redact_secrets: bool) -> Result<ExportResul
/// 配置导入选项
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct ImportOptions {
/// 是否合并到现有配置(true)或替换(false)
pub merge: bool,
-2
View File
@@ -47,8 +47,6 @@ fn get_local_ip() -> Option<String> {
///
/// 返回所有非回环的 IPv4 地址,过滤掉 VPN 和虚拟网卡
fn get_all_local_ips() -> Vec<String> {
use std::net::Ipv4Addr;
let mut ips = Vec::new();
// 使用 if-addrs crate 获取所有网络接口
@@ -66,6 +66,7 @@ pub struct AuthTypeInfoResponse {
/// 模型家族信息
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
pub struct ModelFamilyResponse {
pub name: String,
pub pattern: String,
+1 -1
View File
@@ -2934,7 +2934,7 @@ pub struct PlaywrightStatus {
/// 获取系统 Chrome 可执行文件路径
fn get_system_chrome_path() -> Option<String> {
let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
let _home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
#[cfg(target_os = "macos")]
{
+6 -6
View File
@@ -274,12 +274,12 @@ mod tests {
}
}
/// **Feature: skills-platform-mvp, Property 2: Installed Skills Discovery**
/// **Validates: Requirements 2.1, 2.2, 2.3**
///
/// *For any* valid ~/.proxycast/skills/ directory containing subdirectories
/// with SKILL.md files, calling `scan_installed_skills()` SHALL return a list
/// containing exactly those subdirectory names.
// **Feature: skills-platform-mvp, Property 2: Installed Skills Discovery**
// **Validates: Requirements 2.1, 2.2, 2.3**
//
// *For any* valid ~/.proxycast/skills/ directory containing subdirectories
// with SKILL.md files, calling `scan_installed_skills()` SHALL return a list
// containing exactly those subdirectory names.
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
+2
View File
@@ -46,6 +46,7 @@ pub trait ConfigObserver: Send + Sync {
}
/// 同步配置观察者 Trait(用于不需要异步的简单观察者)
#[allow(dead_code)]
pub trait SyncConfigObserver: Send + Sync {
/// 观察者名称
fn name(&self) -> &str;
@@ -69,6 +70,7 @@ pub trait SyncConfigObserver: Send + Sync {
}
/// 将同步观察者包装为异步观察者
#[allow(dead_code)]
pub struct SyncObserverWrapper<T: SyncConfigObserver>(pub Arc<T>);
#[async_trait]
+3 -1
View File
@@ -2,6 +2,8 @@
//!
//! 使用 proptest 进行属性测试
#![allow(dead_code)]
use crate::credential::{
BalanceStrategy, Credential, CredentialData, CredentialPool, LoadBalancer,
};
@@ -1861,7 +1863,7 @@ proptest! {
active_count in 1usize..=5usize
) {
// 创建两个管理器:一个立即过期,一个长时间冷却
let expired_config = QuotaExceededConfig {
let _expired_config = QuotaExceededConfig {
switch_project: true,
switch_preview_model: true,
cooldown_seconds: 0, // 立即过期
+2 -2
View File
@@ -609,8 +609,8 @@ mod tests {
mod property_tests {
use super::*;
use crate::flow_monitor::{
FlowAnnotations, FlowMetadata, FlowState, FlowTimestamps, FlowType, Message,
MessageContent, MessageRole, RequestParameters, RoutingInfo,
FlowAnnotations, FlowMetadata, FlowState, FlowTimestamps, FlowType, RequestParameters,
RoutingInfo,
};
use crate::ProviderType;
use chrono::Utc;
+2 -2
View File
@@ -1141,8 +1141,8 @@ mod tests {
mod property_tests {
use super::*;
use crate::flow_monitor::models::{
FlowAnnotations, FlowMetadata, FlowState, FlowTimestamps, FlowType, LLMRequest,
LLMResponse, Message, MessageRole, RequestParameters, TokenUsage,
FlowMetadata, FlowType, LLMRequest, LLMResponse, Message, MessageRole, RequestParameters,
TokenUsage,
};
use crate::ProviderType;
use chrono::Utc;
+2 -4
View File
@@ -915,8 +915,7 @@ pub fn get_filter_help() -> String {
mod tests {
use super::*;
use crate::flow_monitor::models::{
FlowAnnotations, FlowMetadata, FlowTimestamps, FlowType, LLMRequest, LLMResponse,
RequestParameters, TokenUsage,
FlowMetadata, FlowType, LLMRequest, LLMResponse, RequestParameters, TokenUsage,
};
use crate::ProviderType;
@@ -1261,8 +1260,7 @@ mod tests {
mod property_tests {
use super::*;
use crate::flow_monitor::models::{
FlowAnnotations, FlowError, FlowErrorType, FlowMetadata, FlowTimestamps, FlowType,
FunctionCall, LLMRequest, LLMResponse, Message, MessageContent, MessageRole,
FlowError, FlowErrorType, FlowMetadata, FlowType, FunctionCall, LLMRequest, LLMResponse,
RequestParameters, ThinkingContent, TokenUsage, ToolCall,
};
use crate::ProviderType;
+2 -2
View File
@@ -1009,10 +1009,10 @@ mod tests {
#[cfg(test)]
mod property_tests {
#![allow(dead_code)]
use super::*;
use crate::flow_monitor::models::{
FlowAnnotations, FlowError, FlowErrorType, FlowMetadata, FlowTimestamps, FlowType,
FunctionCall, LLMRequest, LLMResponse, Message, MessageContent, MessageRole,
FlowError, FlowErrorType, FlowMetadata, FlowType, FunctionCall, LLMRequest, LLMResponse,
RequestParameters, ThinkingContent, TokenUsage, ToolCall,
};
use crate::ProviderType;
+3 -7
View File
@@ -571,9 +571,7 @@ impl FlowMemoryStore {
#[cfg(test)]
mod tests {
use super::*;
use crate::flow_monitor::models::{
FlowMetadata, FlowTimestamps, LLMRequest, RequestParameters,
};
use crate::flow_monitor::models::{FlowMetadata, LLMRequest, RequestParameters};
/// 创建测试用的 Flow
fn create_test_flow(id: &str, model: &str, provider: ProviderType) -> LLMFlow {
@@ -852,11 +850,9 @@ mod tests {
#[cfg(test)]
mod property_tests {
#![allow(dead_code)]
use super::*;
use crate::flow_monitor::models::{
FlowAnnotations, FlowError, FlowErrorType, FlowMetadata, FlowTimestamps, LLMRequest,
LLMResponse, RequestParameters, ThinkingContent, TokenUsage,
};
use crate::flow_monitor::models::{FlowMetadata, LLMRequest, RequestParameters};
use proptest::prelude::*;
// ========================================================================
@@ -1019,6 +1019,7 @@ mod tests {
#[cfg(test)]
mod property_tests {
#![allow(dead_code)]
use super::*;
use crate::flow_monitor::models::{
FlowMetadata, FlowType, LLMRequest, LLMResponse, RequestParameters, TokenUsage,
+2 -1
View File
@@ -2,10 +2,11 @@
//!
//! 使用 proptest 进行属性测试
#![allow(dead_code)]
use crate::config::RemoteManagementConfig;
use crate::middleware::management_auth::{
clear_auth_failure_state, clear_auth_failure_state_for, ManagementAuthLayer,
ManagementAuthService,
};
use axum::{
body::Body,
+1
View File
@@ -76,6 +76,7 @@ pub struct AnthropicUsage {
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct AnthropicMessagesResponse {
pub id: String,
#[serde(rename = "type")]
+1
View File
@@ -93,6 +93,7 @@ pub struct MachineIdHistory {
/// 机器码操作类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub enum MachineIdOperation {
/// 获取当前机器码
Get,
+1
View File
@@ -443,6 +443,7 @@ impl ProviderAliasConfig {
/// models.dev API 响应中的 Provider 结构
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct ModelsDevProvider {
pub id: String,
pub name: String,
+5 -5
View File
@@ -130,11 +130,11 @@ mod tests {
assert!(first_repo.enabled, "ProxyCast 官方仓库应默认启用");
}
/// Property 1: Default Repositories Include ProxyCast Official (Property-Based Test)
/// For any call to get_default_skill_repos(), the returned list SHALL contain
/// a SkillRepo with owner="proxycast", name="skills", branch="main", and enabled=true,
/// and this repo SHALL be the first item in the list.
/// Validates: Requirements 1.1, 1.2, 1.3
// Property 1: Default Repositories Include ProxyCast Official (Property-Based Test)
// For any call to get_default_skill_repos(), the returned list SHALL contain
// a SkillRepo with owner="proxycast", name="skills", branch="main", and enabled=true,
// and this repo SHALL be the first item in the list.
// Validates: Requirements 1.1, 1.2, 1.3
proptest! {
#[test]
fn prop_default_repos_proxycast_first(_seed in 0u64..1000) {
+2 -1
View File
@@ -312,6 +312,7 @@ mod tests {
/// **验证需求: 2.4, 3.1, 3.2**
#[cfg(test)]
mod property_tests {
#![allow(dead_code)]
use super::*;
use crate::plugin::installer::InstallStage;
use proptest::prelude::*;
@@ -375,7 +376,7 @@ mod property_tests {
"[a-z][a-z0-9_-]{0,99}", // repo
"v[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}", // tag
)
.prop_map(|(owner, repo, tag)| {
.prop_map(|(owner, repo, _tag)| {
format!("{}/@{}", owner, repo)
.replace("/@", &format!("/{}@", repo.chars().next().unwrap_or('r')))
})
+1 -1
View File
@@ -181,7 +181,7 @@ use proptest::prelude::*;
mod property_tests {
use super::*;
use crate::plugin::manager::{PluginManager, PluginManagerConfig};
use std::path::PathBuf;
use tempfile::TempDir;
/// 生成随机的请求 JSON
+5 -2
View File
@@ -5,8 +5,8 @@
use chrono::{Duration, Utc};
use proptest::prelude::*;
use crate::providers::codex::{CodexCredentials, CodexProvider};
use crate::providers::iflow::{IFlowCredentials, IFlowProvider};
use crate::providers::codex::CodexProvider;
use crate::providers::iflow::IFlowProvider;
use crate::providers::vertex::VertexProvider;
/// Generate a random lead time in minutes (1 to 30 minutes)
@@ -22,6 +22,7 @@ fn arb_time_offset_secs() -> impl Strategy<Value = i64> {
/// 生成不会与 lead_time 边界冲突的时间偏移
/// 避免 time_offset_secs 恰好等于 lead_time_mins * 60 的情况
#[allow(dead_code)]
fn arb_time_offset_avoiding_boundary(lead_time_mins: i64) -> impl Strategy<Value = i64> {
let boundary = lead_time_mins * 60;
// 生成不等于边界值的时间偏移
@@ -477,6 +478,7 @@ fn arb_model_name() -> impl Strategy<Value = String> {
}
/// Generate a random exclusion pattern
#[allow(dead_code)]
fn arb_exclusion_pattern() -> impl Strategy<Value = String> {
prop_oneof![
// Exact model names
@@ -491,6 +493,7 @@ fn arb_exclusion_pattern() -> impl Strategy<Value = String> {
}
/// Generate a list of exclusion patterns
#[allow(dead_code)]
fn arb_exclusion_patterns() -> impl Strategy<Value = Vec<String>> {
proptest::collection::vec(arb_exclusion_pattern(), 0..5)
}
+2
View File
@@ -2,6 +2,8 @@
//!
//! 使用 proptest 进行属性测试
#![allow(dead_code)]
use crate::proxy::{ProxyClientFactory, ProxyError, ProxyProtocol};
use proptest::prelude::*;
+1 -2
View File
@@ -4,7 +4,7 @@
use std::path::PathBuf;
use tauri::AppHandle;
use tracing::{debug, error, info, warn};
use tracing::{debug, error, info};
/// 截图错误类型
#[derive(Debug, thiserror::Error)]
@@ -229,7 +229,6 @@ pub fn cleanup_temp_file(path: &PathBuf) {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_temp_path_generation() {
+13 -12
View File
@@ -5,7 +5,7 @@
use mouse_position::mouse_position::Mouse;
use std::path::Path;
use tauri::{AppHandle, Manager, WebviewUrl, WebviewWindowBuilder};
use tracing::{debug, info, warn};
use tracing::{debug, info};
#[cfg(target_os = "macos")]
use cocoa::appkit::{NSColor, NSWindow};
@@ -202,17 +202,18 @@ pub fn open_floating_window(app: &AppHandle, image_path: &Path) -> Result<(), Wi
let (x, y) = calculate_window_position(app);
// 创建悬浮窗口(启用透明)
let window = WebviewWindowBuilder::new(app, FLOATING_WINDOW_LABEL, WebviewUrl::App(url.into()))
.inner_size(WINDOW_WIDTH, WINDOW_HEIGHT)
.position(x, y)
.decorations(false)
.always_on_top(true)
.skip_taskbar(true)
.visible(true)
.focused(true)
.transparent(true)
.build()
.map_err(|e| WindowError::CreateFailed(format!("{}", e)))?;
let _window =
WebviewWindowBuilder::new(app, FLOATING_WINDOW_LABEL, WebviewUrl::App(url.into()))
.inner_size(WINDOW_WIDTH, WINDOW_HEIGHT)
.position(x, y)
.decorations(false)
.always_on_top(true)
.skip_taskbar(true)
.visible(true)
.focused(true)
.transparent(true)
.build()
.map_err(|e| WindowError::CreateFailed(format!("{}", e)))?;
// macOS: 设置窗口和 webview 背景透明
#[cfg(target_os = "macos")]
+2 -1
View File
@@ -785,7 +785,7 @@ mod property_tests {
let response = build_anthropic_response(&model, &parsed);
// 获取响应体
let (parts, body) = response.into_parts();
let (parts, _body) = response.into_parts();
// 验证状态码为 200
prop_assert_eq!(parts.status, StatusCode::OK);
@@ -1073,6 +1073,7 @@ mod property_tests {
// ========================================================================
/// 获取模型名称映射的预期结果
#[allow(dead_code)]
fn get_expected_model_mapping(model: &str) -> &str {
match model {
"gemini-2.5-computer-use-preview-10-2025" => "rev19-uic3-1p",
@@ -273,7 +273,6 @@ impl Default for KiroEventService {
#[cfg(test)]
mod tests {
use super::*;
use tokio::time::{sleep, Duration};
#[tokio::test]
async fn test_credential_status_update_event() {
+2 -2
View File
@@ -8,6 +8,7 @@
#[cfg(test)]
mod tests {
#![allow(dead_code)]
use super::super::*;
use serde_json::json;
use std::fs;
@@ -288,7 +289,6 @@ mod tests {
#[cfg(test)]
mod shell_config_write_tests {
use super::*;
/// **Feature: shell-write, Property 1: 特殊字符转义**
#[test]
@@ -307,7 +307,7 @@ mod tests {
// 这个测试验证特殊字符转义逻辑
// 实际的 write_env_to_shell_config 会写入真实的 shell 配置文件
// 在单元测试中,我们只验证转义逻辑是正确的
for (key, value) in &env_vars {
for (_key, value) in &env_vars {
// 验证值包含特殊字符
assert!(
value.contains('"') || value.contains('\\'),
+27 -22
View File
@@ -256,28 +256,33 @@ impl Default for UpdateCheckService {
/// 发送系统通知(跨平台)
///
/// 使用 Tauri 的通知 API 发送原生系统通知
#[cfg(feature = "notification")]
pub async fn send_update_notification(
app_handle: &tauri::AppHandle,
update_info: &UpdateInfo,
) -> Result<(), String> {
use tauri::api::notification::Notification;
if !update_info.has_update {
return Ok(());
}
let latest = update_info.latest_version.as_deref().unwrap_or("未知版本");
Notification::new(&app_handle.config().tauri.bundle.identifier)
.title("ProxyCast 有新版本可用")
.body(&format!(
"新版本 {} 已发布,当前版本 {}",
latest, update_info.current_version
))
.show()
.map_err(|e| format!("发送通知失败: {}", e))
}
///
/// TODO: 此功能暂时禁用,需要迁移到 Tauri v2 的通知插件 API
/// 参考:https://v2.tauri.app/plugin/notification/
// #[cfg(feature = "notification")]
// pub async fn send_update_notification(
// app_handle: &tauri::AppHandle,
// update_info: &UpdateInfo,
// ) -> Result<(), String> {
// use tauri_plugin_notification::NotificationExt;
//
// if !update_info.has_update {
// return Ok(());
// }
//
// let latest = update_info.latest_version.as_deref().unwrap_or("未知版本");
//
// app_handle
// .notification()
// .builder()
// .title("ProxyCast 有新版本可用")
// .body(&format!(
// "新版本 {} 已发布,当前版本 {}",
// latest, update_info.current_version
// ))
// .show()
// .map_err(|e| format!("发送通知失败: {}", e))
// }
/// 更新检查服务状态包装器(用于 Tauri 状态管理)
pub struct UpdateCheckServiceState(pub Arc<RwLock<UpdateCheckService>>);
+1 -1
View File
@@ -164,7 +164,7 @@ pub fn open_update_window(
let (x, y) = calculate_window_position(app);
let window = WebviewWindowBuilder::new(app, UPDATE_WINDOW_LABEL, WebviewUrl::App(url.into()))
let _window = WebviewWindowBuilder::new(app, UPDATE_WINDOW_LABEL, WebviewUrl::App(url.into()))
.inner_size(WINDOW_WIDTH, WINDOW_HEIGHT)
.position(x, y)
.decorations(false)
+1
View File
@@ -1311,6 +1311,7 @@ mod error_recovery_tests {
#[cfg(test)]
mod property_tests {
#![allow(dead_code)]
use super::*;
use proptest::prelude::*;
+1 -3
View File
@@ -1193,9 +1193,7 @@ mod tests {
#[cfg(test)]
mod property_tests {
use super::*;
use crate::streaming::aws_parser::{
extract_content, extract_tool_calls, serialize_event, AwsEvent,
};
use crate::streaming::aws_parser::{extract_content, serialize_event, AwsEvent};
use proptest::prelude::*;
// ========================================================================
@@ -74,7 +74,7 @@ impl SseResponseTranslator for OpenAiResponseTranslator {
#[cfg(test)]
mod tests {
use super::*;
use crate::stream::{ContentBlockType, StopReason};
use crate::stream::StopReason;
#[test]
fn test_translate_text_delta() {
+2
View File
@@ -1,5 +1,7 @@
//! WebSocket 模块测试
#![allow(dead_code)]
use super::*;
#[test]
+2 -1
View File
@@ -12,11 +12,12 @@ use tempfile::TempDir;
use proxycast_lib::database::dao::api_key_provider::{
ApiKeyEntry, ApiKeyProvider, ApiKeyProviderDao, ApiProviderType, ProviderGroup,
};
use proxycast_lib::database::{init_database, DbConnection};
use proxycast_lib::database::DbConnection;
use proxycast_lib::services::api_key_provider_service::ApiKeyProviderService;
use rusqlite::Connection;
/// 测试上下文
#[allow(dead_code)]
struct TestContext {
pub temp_dir: TempDir,
pub db: DbConnection,
+1
View File
@@ -21,6 +21,7 @@ use proxycast_lib::flow_monitor::{
use std::collections::HashMap;
/// 端到端测试上下文
#[allow(dead_code)]
struct E2ETestContext {
pub temp_dir: TempDir,
pub flow_monitor: Arc<FlowMonitor>,