autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
186 lines (185 loc) • 7.38 kB
JavaScript
/**
* Go Web Enhancement Pack
* 条件: { languages: ['go'], frameworks: ['gin', 'echo', 'fiber', 'chi', 'gorilla', 'beego'] }
*
* 覆盖所有主流 Go HTTP 框架:
* - Gin, Echo, Fiber, Chi, Gorilla Mux, Beego
*/
import { EnhancementPack } from './EnhancementPack.js';
class GoWebEnhancement extends EnhancementPack {
get id() {
return 'go-web';
}
get displayName() {
return 'Go Web (Gin/Echo/Fiber/Chi) Enhancement';
}
get conditions() {
return {
languages: ['go'],
frameworks: ['gin', 'echo', 'fiber', 'chi', 'gorilla', 'beego'],
};
}
getExtraDimensions() {
return [
{
id: 'go-handler-scan',
label: 'HTTP Handler 分析',
guide: 'Go HTTP Handler 与 Middleware 链路分析 — handler 签名规范、中间件注册顺序、Context 传播、错误级联',
tierHint: 2,
knowledgeTypes: ['architecture', 'code-pattern'],
skillWorthy: true,
dualOutput: true,
skillMeta: {
name: 'project-go-handlers',
description: 'Go HTTP handler patterns, middleware chains and context propagation (auto-generated by enhancement)',
},
},
{
id: 'go-route-scan',
label: 'API Route 结构',
guide: 'Go 路由结构分析 — 路由分组 (Group)、URI 命名规范、HTTP 方法分布、路由参数与通配符',
tierHint: 2,
knowledgeTypes: ['architecture'],
skillWorthy: true,
dualOutput: true,
skillMeta: {
name: 'project-go-routes',
description: 'Go API route structure, grouping and URI naming conventions (auto-generated by enhancement)',
},
},
];
}
getGuardRules() {
return [
{
ruleId: 'go-handler-abort-return',
category: 'correctness',
dimension: 'file',
severity: 'warning',
languages: ['go'],
pattern: /\.Abort\w*\([^)]*\)[^}]*\n\s*[^}\s/]/,
message: 'Abort/AbortWithStatus 后应立即 return,否则后续逻辑仍会执行',
},
{
ruleId: 'go-no-naked-goroutine',
category: 'correctness',
dimension: 'file',
severity: 'warning',
languages: ['go'],
pattern: /go\s+func\s*\(/,
message: 'HTTP handler 中启动 goroutine 应包含 recover() 防止 panic 导致整个进程崩溃',
},
{
ruleId: 'go-context-first-param',
category: 'style',
dimension: 'file',
severity: 'info',
languages: ['go'],
pattern: /func\s+\w+\([^)]*\)\s*\([^)]*context\.Context/,
message: 'context.Context 应作为函数的第一个参数,而非放在返回值或中间位置',
},
];
}
detectPatterns(astSummary) {
const patterns = [];
// ── Struct-based Handler / Controller ──
for (const cls of astSummary.classes || []) {
if (cls.kind !== 'struct') {
continue;
}
const nameLower = cls.name.toLowerCase();
if (nameLower.includes('handler') ||
nameLower.includes('controller') ||
nameLower.includes('server') ||
nameLower.includes('api')) {
patterns.push({
type: 'go-handler-struct',
className: cls.name,
line: cls.line,
confidence: 0.8,
});
}
}
// ── HTTP Handler Interfaces ──
for (const proto of astSummary.protocols || []) {
if (proto.methods?.includes('ServeHTTP')) {
patterns.push({
type: 'go-http-handler-interface',
className: proto.name,
line: proto.line,
confidence: 0.95,
});
}
}
// ── Handler / Middleware methods ──
for (const m of astSummary.methods || []) {
// Exported methods on structs — likely handlers
if (m.className && m.isExported && !m.isClassMethod) {
const nameLower = m.name.toLowerCase();
if (nameLower.startsWith('get') ||
nameLower.startsWith('post') ||
nameLower.startsWith('put') ||
nameLower.startsWith('delete') ||
nameLower.startsWith('patch') ||
nameLower.startsWith('handle') ||
nameLower.startsWith('list') ||
nameLower.startsWith('create') ||
nameLower.startsWith('update') ||
nameLower.startsWith('remove')) {
patterns.push({
type: 'go-handler-method',
className: m.className,
methodName: m.name,
line: m.line,
confidence: 0.7,
});
}
}
// Middleware pattern: package-level function returning HandlerFunc-like
if (!m.className && m.isClassMethod && m.isExported) {
const nameLower = m.name.toLowerCase();
if (nameLower.includes('middleware') ||
nameLower.includes('logger') ||
nameLower.includes('recovery') ||
nameLower.includes('cors') ||
nameLower.includes('auth') ||
nameLower.includes('ratelimit') ||
nameLower.includes('timeout')) {
patterns.push({
type: 'go-middleware',
methodName: m.name,
line: m.line,
confidence: 0.75,
});
}
}
}
// ── Engine / Router struct (framework core) ──
for (const cls of astSummary.classes || []) {
if (cls.kind !== 'struct') {
continue;
}
if (/^(?:Engine|Router|App|Server|Mux|Group)$/.test(cls.name)) {
patterns.push({
type: 'go-router-core',
className: cls.name,
line: cls.line,
confidence: 0.85,
});
}
}
// ── Concurrency in web context ──
// goroutine + channel patterns from lang-go.js
for (const p of astSummary.patterns || []) {
if (p.type === 'goroutine' && (p.count ?? 0) > 0) {
patterns.push({
type: 'go-web-concurrency',
goroutineCount: p.count,
confidence: 0.7,
});
}
}
return patterns;
}
}
export const pack = new GoWebEnhancement();