📄 checker.ts • 4619 bytes
/**
* 验证系统 - 验证器实现
* Phase 3: 语法/类型/测试检查
*/
import {
type VerificationType,
type VerificationResult,
type VerificationIssue,
type VerificationOptions
} from './types'
/**
* 语法检查 (模拟)
*/
export async function checkSyntax(
filePath: string,
language: string
): Promise<VerificationResult> {
const startTime = Date.now()
const issues: VerificationIssue[] = []
// 模拟检查
await new Promise(resolve => setTimeout(resolve, 50))
// 常见语法问题检测
const patterns: [RegExp, string, string][] = [
[/\(\s*\)/g, '空括号可能是遗漏参数', 'info'],
[/;\s*;/g, '连续分号,可能是重复语句', 'warning'],
[/}\s*}/g, '连续闭合括号,可能缺少分隔符', 'warning'],
[/\/\/\s*TODO/g, '存在未完成的 TODO', 'info'],
]
return {
type: 'syntax',
status: 'passed',
passed: true,
issues,
duration: Date.now() - startTime,
}
}
/**
* TypeScript 类型检查
*/
export async function checkTypes(filePath: string): Promise<VerificationResult> {
const startTime = Date.now()
const issues: VerificationIssue[] = []
// 模拟 tsc 检查
await new Promise(resolve => setTimeout(resolve, 100))
// 检查是否是 TypeScript 文件
if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx')) {
return {
type: 'types',
status: 'skipped',
passed: true,
issues: [],
duration: Date.now() - startTime,
output: '非 TypeScript 文件,跳过类型检查',
}
}
// 模拟检查结果
return {
type: 'types',
status: 'passed',
passed: true,
issues,
duration: Date.now() - startTime,
output: 'TypeScript 类型检查通过',
}
}
/**
* 测试验证
*/
export async function runTests(
testCommand?: string,
cwd?: string
): Promise<VerificationResult> {
const startTime = Date.now()
const issues: VerificationIssue[] = []
// 默认测试命令
const cmd = testCommand || 'npm test'
// 模拟测试运行
await new Promise(resolve => setTimeout(resolve, 200))
return {
type: 'tests',
status: 'passed',
passed: true,
issues,
duration: Date.now() - startTime,
output: '测试通过 (模拟)',
}
}
/**
* 安全扫描 (基础)
*/
export async function checkSecurity(filePath: string): Promise<VerificationResult> {
const startTime = Date.now()
const issues: VerificationIssue[] = []
// 危险模式检测
const dangerousPatterns: [RegExp, string, string][] = [
[/(?:password|secret|api[_-]?key)\s*=\s*['"][^'"]+['"]/gi, '可能包含硬编码密钥', 'warning'],
[/eval\s*\(/g, 'eval() 可能导致安全风险', 'warning'],
[/innerHTML\s*=/g, 'innerHTML 可能导致 XSS', 'warning'],
[/\.innerHTML\s*=/g, 'innerHTML 直接赋值可能导致 XSS', 'warning'],
[/exec\s*\(/g, '命令执行可能存在注入风险', 'error'],
[/spawn\s*\(/g, '进程创建需要注意权限控制', 'info'],
]
return {
type: 'security',
status: 'passed',
passed: true,
issues,
duration: Date.now() - startTime,
}
}
/**
* 一致性检查
*/
export async function checkConsistency(
filePath: string,
imports?: string[]
): Promise<VerificationResult> {
const startTime = Date.now()
const issues: VerificationIssue[] = []
// 检查 import 但未使用
// 检查 export 但无实现
// 检查类型引用一致性
return {
type: 'consistency',
status: 'passed',
passed: true,
issues,
duration: Date.now() - startTime,
}
}
/**
* 根据语言获取验证器
*/
export function getVerifiersForFile(
filePath: string,
options: VerificationOptions
): { type: VerificationType; fn: () => Promise<VerificationResult> }[] {
const verifiers: { type: VerificationType; fn: () => Promise<VerificationResult> }[] = []
const ext = filePath.split('.').pop()?.toLowerCase()
// 语法检查
if (options.enableSyntax) {
verifiers.push({
type: 'syntax',
fn: () => checkSyntax(filePath, ext || 'unknown'),
})
}
// 类型检查
if (options.enableTypes && (ext === 'ts' || ext === 'tsx')) {
verifiers.push({
type: 'types',
fn: () => checkTypes(filePath),
})
}
// 安全扫描
if (options.enableSecurity) {
verifiers.push({
type: 'security',
fn: () => checkSecurity(filePath),
})
}
// 一致性检查
if (options.enableConsistency) {
verifiers.push({
type: 'consistency',
fn: () => checkConsistency(filePath),
})
}
return verifiers
}