autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
207 lines (206 loc) • 8.25 kB
JavaScript
/**
* 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();