UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

207 lines (206 loc) 8.25 kB
/** * Rust Tokio Async Enhancement Pack * 条件: { languages: ['rust'], frameworks: ['tokio', 'async-std'] } * * 覆盖 Rust 异步运行时生态: * - Tokio runtime (最主流) * - async-std * - 异步任务 spawn / JoinHandle * - Channel (mpsc/oneshot/broadcast/watch) * - 同步原语 (Mutex/RwLock/Semaphore) * - 超时与取消 (select!, timeout) */ import { EnhancementPack } from './EnhancementPack.js'; class RustTokioEnhancement extends EnhancementPack { get id() { return 'rust-tokio'; } get displayName() { return 'Rust Tokio/Async Enhancement'; } get conditions() { return { languages: ['rust'], frameworks: ['tokio', 'async-std'], }; } getExtraDimensions() { return [ { id: 'rust-async-task-scan', label: 'Async Task 分析', guide: 'Rust 异步任务拓扑分析 — tokio::spawn / task::spawn_blocking 使用分布、JoinHandle 收集与 abort 策略、tokio::select! 分支、graceful shutdown 模式', tierHint: 2, knowledgeTypes: ['architecture', 'code-pattern'], skillWorthy: true, dualOutput: true, skillMeta: { name: 'project-rust-async-tasks', description: 'Rust async task spawn/join topology, select branches and shutdown patterns (auto-generated by enhancement)', }, }, { id: 'rust-channel-sync-scan', label: 'Channel/同步原语分析', guide: 'Rust Channel 与同步原语分析 — mpsc/oneshot/broadcast/watch channel 使用、Arc<Mutex>/Arc<RwLock> 共享状态、Semaphore 限流、Notify 事件', tierHint: 2, knowledgeTypes: ['architecture', 'code-pattern'], skillWorthy: true, dualOutput: true, skillMeta: { name: 'project-rust-concurrency', description: 'Rust channel patterns, shared state synchronization and concurrency primitives (auto-generated by enhancement)', }, }, ]; } getGuardRules() { return [ { ruleId: 'rust-tokio-std-mutex', category: 'correctness', dimension: 'file', severity: 'warning', languages: ['rust'], pattern: /std::sync::Mutex|std::sync::RwLock/, message: '在 async 代码中使用 std::sync::Mutex 会阻塞运行时线程,应使用 tokio::sync::Mutex 或 parking_lot::Mutex(如果临界区极短)', }, { ruleId: 'rust-tokio-blocking-in-async', category: 'performance', dimension: 'file', severity: 'warning', languages: ['rust'], pattern: /std::thread::sleep|std::fs::|std::net::TcpStream/, message: 'async 上下文中不应使用阻塞操作,使用 tokio::time::sleep / tokio::fs / tokio::net 或 spawn_blocking()', }, { ruleId: 'rust-tokio-unbounded-channel', category: 'performance', dimension: 'file', severity: 'info', languages: ['rust'], pattern: /unbounded_channel|mpsc::unbounded/, message: 'unbounded channel 在高吞吐场景下可能导致内存无限增长,考虑使用 bounded channel 并处理背压', }, { ruleId: 'rust-tokio-spawn-no-handle', category: 'correctness', dimension: 'file', severity: 'info', languages: ['rust'], pattern: /tokio::spawn\([^)]+\)\s*;/, message: 'tokio::spawn 返回的 JoinHandle 被丢弃 — 任务 panic 不会传播,考虑使用 JoinSet 或 .await handle', }, ]; } detectPatterns(astSummary) { const patterns = []; // ── Async functions (potential task entry points) ── let asyncFnCount = 0; for (const m of astSummary.methods || []) { if (m.isAsync) { asyncFnCount++; } } if (asyncFnCount > 0) { patterns.push({ type: 'rust-async-functions', count: asyncFnCount, confidence: 0.85, }); } // ── Runtime main entry (#[tokio::main]) ── for (const m of astSummary.methods || []) { if (m.name === 'main' && m.isAsync) { patterns.push({ type: 'rust-tokio-main', line: m.line, confidence: 0.95, }); } } // ── Structs wrapping async primitives ── for (const cls of astSummary.classes || []) { if (cls.kind !== 'struct') { continue; } const nameLower = cls.name.toLowerCase(); if (nameLower.includes('worker') || nameLower.includes('executor') || nameLower.includes('scheduler') || nameLower.includes('dispatcher') || nameLower.includes('runtime') || nameLower.includes('pool')) { patterns.push({ type: 'rust-async-worker', className: cls.name, line: cls.line, confidence: 0.7, }); } } // ── Channel / sync wrappers ── for (const cls of astSummary.classes || []) { if (cls.kind !== 'struct') { continue; } const nameLower = cls.name.toLowerCase(); if (nameLower.includes('sender') || nameLower.includes('receiver') || nameLower.includes('channel') || nameLower.includes('notifier') || nameLower.includes('broker') || nameLower.includes('bus')) { patterns.push({ type: 'rust-channel-struct', className: cls.name, line: cls.line, confidence: 0.7, }); } } // ── Trait impls for async patterns ── for (const cls of astSummary.classes || []) { // Look for trait: Future / Stream / Service / Tower Layer if (cls.kind === 'trait_impl') { const traitName = cls.traitName || ''; if (traitName === 'Future' || traitName === 'Stream' || traitName === 'Service' || traitName === 'Layer') { patterns.push({ type: 'rust-async-trait-impl', className: cls.name, traitName, line: cls.line, confidence: 0.85, }); } } } // ── Tokio/async imports ── const asyncImports = (astSummary.imports || []).filter((imp) => imp.includes('tokio') || imp.includes('async_std') || imp.includes('futures') || imp.includes('tower')); if (asyncImports.length > 0) { patterns.push({ type: 'rust-async-ecosystem-usage', importCount: asyncImports.length, confidence: 0.9, }); } // ── Detect common async patterns from lang-rust detectPatterns ── for (const p of astSummary.patterns || []) { if (p.type === 'async-heavy' || p.type === 'unsafe-usage') { patterns.push({ type: `rust-tokio-${p.type}`, confidence: p.confidence || 0.7, }); } } return patterns; } } export const pack = new RustTokioEnhancement();