autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
140 lines (139 loc) • 5.52 kB
JavaScript
/**
* Go gRPC Enhancement Pack
* 条件: { languages: ['go'], frameworks: ['grpc'] }
*
* 覆盖 gRPC Go 微服务项目:
* - protobuf service 实现
* - Unimplemented*Server 嵌入
* - 流式/一元 RPC 方法
* - interceptor 链
*/
import { EnhancementPack } from './EnhancementPack.js';
class GoGrpcEnhancement extends EnhancementPack {
get id() {
return 'go-grpc';
}
get displayName() {
return 'Go gRPC Enhancement';
}
get conditions() {
return { languages: ['go'], frameworks: ['grpc'] };
}
getExtraDimensions() {
return [
{
id: 'go-grpc-service-scan',
label: 'gRPC Service 分析',
guide: 'gRPC Service 实现分析 — Protobuf 生成代码与手写代码分离、Unimplemented*Server 嵌入、一元/流式方法分布、错误码使用规范',
tierHint: 2,
knowledgeTypes: ['architecture', 'code-pattern'],
skillWorthy: true,
dualOutput: true,
skillMeta: {
name: 'project-go-grpc',
description: 'Go gRPC service implementations, streaming patterns and error code usage (auto-generated by enhancement)',
},
},
{
id: 'go-grpc-interceptor-scan',
label: 'gRPC Interceptor 分析',
guide: 'gRPC Interceptor 链路分析 — UnaryServerInterceptor / StreamServerInterceptor 注册顺序、日志/认证/限流拦截器',
tierHint: 2,
knowledgeTypes: ['architecture'],
skillWorthy: true,
dualOutput: true,
skillMeta: {
name: 'project-go-grpc-interceptors',
description: 'Go gRPC interceptor chain ordering and middleware patterns (auto-generated by enhancement)',
},
},
];
}
getGuardRules() {
return [
{
ruleId: 'go-grpc-unimplemented-embed',
category: 'correctness',
dimension: 'file',
severity: 'warning',
languages: ['go'],
pattern: /Unimplemented\w+Server\b/,
message: 'gRPC service 应嵌入 Unimplemented*Server 以保证前向兼容(新增 RPC 方法时不会编译失败)',
},
{
ruleId: 'go-grpc-status-error',
category: 'correctness',
dimension: 'file',
severity: 'info',
languages: ['go'],
pattern: /fmt\.Errorf|errors\.New/,
message: 'gRPC handler 中应使用 status.Errorf/status.Error 返回标准 gRPC 错误码,而非 fmt.Errorf',
},
];
}
detectPatterns(astSummary) {
const patterns = [];
// ── gRPC Service Implementations ──
for (const cls of astSummary.classes || []) {
if (cls.kind !== 'struct') {
continue;
}
// Structs embedding Unimplemented*Server
if (cls.embeddedTypes?.some((t) => /^Unimplemented\w+Server$/.test(t))) {
patterns.push({
type: 'go-grpc-service-impl',
className: cls.name,
embeds: cls.embeddedTypes.filter((t) => /Unimplemented/.test(t)),
line: cls.line,
confidence: 0.95,
});
}
// Server structs (name ends with Server)
if (/Server$/.test(cls.name) && (cls.fieldCount ?? 0) > 0) {
patterns.push({
type: 'go-grpc-server-struct',
className: cls.name,
line: cls.line,
confidence: 0.6,
});
}
}
// ── gRPC Interfaces (generated *Server interfaces) ──
for (const proto of astSummary.protocols || []) {
if (/Server$/.test(proto.name) && !proto.name.startsWith('Unimplemented')) {
patterns.push({
type: 'go-grpc-service-interface',
className: proto.name,
methods: proto.methods,
line: proto.line,
confidence: 0.8,
});
}
}
// ── Interceptor functions ──
for (const m of astSummary.methods || []) {
if (!m.className && m.isExported) {
const nameLower = m.name.toLowerCase();
if (nameLower.includes('interceptor') || nameLower.includes('middleware')) {
patterns.push({
type: 'go-grpc-interceptor',
methodName: m.name,
line: m.line,
confidence: 0.8,
});
}
}
}
// ── Protobuf imports ──
const pbImports = (astSummary.imports || []).filter((imp) => imp.includes('/pb') || imp.includes('/proto') || imp.includes('google.golang.org/grpc'));
if (pbImports.length > 0) {
patterns.push({
type: 'go-grpc-proto-usage',
importCount: pbImports.length,
confidence: 0.85,
});
}
return patterns;
}
}
export const pack = new GoGrpcEnhancement();