/** * 一致性检查模块 * * 实现需求-设计-编码三向一致性检查逻辑 */ /** * 需求→设计一致性检查 * * @param {Object} requirements - 需求列表 * @param {Object} design - 设计文档 * @returns {Object} 检查结果 */ export function checkRequirementDesign(requirements, design) { const items = [] let allPassed = true // 如果 requirements 是数组,转换为对象 const reqMap = Array.isArray(requirements) ? requirements.reduce((acc, r, i) => { acc[`R${i + 1}`] = r return acc }, {}) : requirements // 遍历每个需求,检查设计是否覆盖 for (const [reqId, requirement] of Object.entries(reqMap)) { const reqText = typeof requirement === 'string' ? requirement : requirement.description || requirement.text || JSON.stringify(requirement) const isCovered = checkDesignCoverage(reqText, design) items.push({ check: `需求 ${reqId}`, expected: reqText, actual: isCovered ? '已覆盖' : '未覆盖', passed: isCovered }) if (!isCovered) { allPassed = false } } return { type: 'requirement-design', passed: allPassed, items, summary: allPassed ? '需求完全被设计覆盖' : '部分需求未被设计覆盖' } } /** * 设计→编码一致性检查 * * @param {Object} design - 设计文档 * @param {Object} codeChanges - 代码变更 * @returns {Object} 检查结果 */ export function checkDesignCode(design, codeChanges) { const items = [] let allPassed = true // 提取设计中的关键组件/模块 const designComponents = extractDesignComponents(design) // 提取代码变更中的文件/模块 const codeFiles = extractCodeFiles(codeChanges) // 检查每个设计组件是否都有对应代码 for (const component of designComponents) { const isImplemented = codeFiles.some(file => file.name.includes(component.name) || file.path.includes(component.path || component.name) ) items.push({ check: `组件: ${component.name}`, expected: `设计: ${component.description || component.type || '组件'}`, actual: isImplemented ? `已实现: ${component.name}` : '未实现', passed: isImplemented }) if (!isImplemented) { allPassed = false } } return { type: 'design-code', passed: allPassed, items, summary: allPassed ? '设计完全被编码实现' : '部分设计未在编码中实现' } } /** * 需求→编码一致性检查 * * @param {Object} requirements - 需求列表 * @param {Object} codeChanges - 代码变更 * @returns {Object} 检查结果 */ export function checkRequirementCode(requirements, codeChanges) { const items = [] let allPassed = true // 如果 requirements 是数组,转换为对象 const reqMap = Array.isArray(requirements) ? requirements.reduce((acc, r, i) => { acc[`R${i + 1}`] = r return acc }, {}) : requirements // 提取代码实现的功能点 const codeFeatures = extractCodeFeatures(codeChanges) // 检查每个需求是否在代码中实现 for (const [reqId, requirement] of Object.entries(reqMap)) { const reqText = typeof requirement === 'string' ? requirement : requirement.description || requirement.text || JSON.stringify(requirement) const isImplemented = checkCodeImplementation(reqText, codeFeatures) items.push({ check: `需求 ${reqId}`, expected: reqText, actual: isImplemented ? '已实现' : '未实现', passed: isImplemented }) if (!isImplemented) { allPassed = false } } return { type: 'requirement-code', passed: allPassed, items, summary: allPassed ? '需求完全在编码中实现' : '部分需求未在编码中实现' } } /** * 完整的三向一致性检查 * * @param {Object} requirements - 需求列表 * @param {Object} design - 设计文档 * @param {Object} codeChanges - 代码变更 * @returns {Object} 完整检查结果 */ export function runThreeWayCheck(requirements, design, codeChanges) { const requirementDesign = checkRequirementDesign(requirements, design) const designCode = checkDesignCode(design, codeChanges) const requirementCode = checkRequirementCode(requirements, codeChanges) const allPassed = requirementDesign.passed && designCode.passed && requirementCode.passed return { allPassed, requirementDesign, designCode, requirementCode, summary: allPassed ? '三向一致性检查全部通过' : '三向一致性检查未通过', deviations: findDeviations(requirementDesign, designCode, requirementCode) } } /** * 查找偏差 */ function findDeviations(requirementDesign, designCode, requirementCode) { const deviations = [] // 需求→设计偏差 if (!requirementDesign.passed) { deviations.push({ type: 'requirement-design', issues: requirementDesign.items.filter(i => !i.passed) }) } // 设计→编码偏差 if (!designCode.passed) { deviations.push({ type: 'design-code', issues: designCode.items.filter(i => !i.passed) }) } // 需求→编码偏差 if (!requirementCode.passed) { deviations.push({ type: 'requirement-code', issues: requirementCode.items.filter(i => !i.passed) }) } return deviations } /** * 辅助函数:检查设计是否覆盖需求 */ function checkDesignCoverage(requirementText, design) { const designText = typeof design === 'string' ? design : JSON.stringify(design) const reqKeywords = extractKeywords(requirementText) // 至少有一个关键词在设计中被提及 return reqKeywords.some(keyword => designText.toLowerCase().includes(keyword.toLowerCase()) ) } /** * 辅助函数:检查代码是否实现需求 */ function checkCodeImplementation(requirementText, codeFeatures) { const reqKeywords = extractKeywords(requirementText) // 至少有一个关键词在代码特性中被实现 return reqKeywords.some(keyword => codeFeatures.some(feature => feature.toLowerCase().includes(keyword.toLowerCase()) ) ) } /** * 辅助函数:提取关键词 */ function extractKeywords(text) { // 简单的关键词提取:过滤常见停用词 const stopWords = new Set(['的', '了', '是', '在', '和', '与', '或', '但', '如果', '那么', '这样', '那样', 'the', 'a', 'an', 'is', 'are', 'and', 'or', 'but', 'if', 'then', 'this', 'that']) return text .toLowerCase() .split(/[\s,,。.!!??;;::]/) .filter(word => word.length > 1 && !stopWords.has(word)) .slice(0, 5) // 取前5个关键词 } /** * 辅助函数:从设计中提取组件 */ function extractDesignComponents(design) { const components = [] // 如果 design 是字符串,尝试解析 if (typeof design === 'string') { // 简单的提取逻辑:查找常见的组件模式 const patterns = [ /表:\s*(\w+)/g, /接口:\s*(\w+)/g, /模块:\s*(\w+)/g, /组件:\s*(\w+)/g, /文件:\s*([^\s]+)/g ] for (const pattern of patterns) { let match while ((match = pattern.exec(design)) !== null) { components.push({ name: match[1], type: 'unknown', description: match[0] }) } } } else if (typeof design === 'object' && design !== null) { // 如果 design 是对象,直接提取 for (const [key, value] of Object.entries(design)) { if (value && typeof value === 'object' && value.name) { components.push(value) } else if (typeof value === 'string') { components.push({ name: key, type: 'unknown', description: value }) } } } return components } /** * 辅助函数:从代码变更中提取文件 */ function extractCodeFiles(codeChanges) { const files = [] if (typeof codeChanges === 'string') { // 简单的文件路径提取 const lines = codeChanges.split('\n') for (const line of lines) { const match = line.match(/([a-zA-Z0-9_\/]+\.[a-zA-Z0-9]+)/) if (match) { files.push({ name: match[1].split('/').pop(), path: match[1] }) } } } else if (Array.isArray(codeChanges)) { // 如果是数组,假设每个元素都是文件信息 for (const change of codeChanges) { if (typeof change === 'string') { files.push({ name: change.split('/').pop(), path: change }) } else if (change.file || change.path || change.name) { files.push({ name: change.file || change.name || change.path?.split('/').pop(), path: change.path || change.file }) } } } else if (typeof codeChanges === 'object' && codeChanges !== null) { // 如果是对象,提取文件信息 if (codeChanges.files) { return extractCodeFiles(codeChanges.files) } if (codeChanges.changes) { return extractCodeFiles(codeChanges.changes) } } return files } /** * 辅助函数:从代码中提取功能点 */ function extractCodeFeatures(codeChanges) { const features = [] // 提取函数名、类名、变量名等作为功能特征 const files = extractCodeFiles(codeChanges) for (const file of files) { const name = file.name || file.path || '' // 从文件名推断功能 if (name.includes('.')) { const baseName = name.substring(0, name.lastIndexOf('.')) features.push(baseName) } features.push(name) } // 如果 codeChanges 包含 description 或 summary if (typeof codeChanges === 'object' && codeChanges !== null) { if (codeChanges.description) { features.push(codeChanges.description) } if (codeChanges.summary) { features.push(codeChanges.summary) } if (codeChanges.changes) { features.push(codeChanges.changes) } } return features } /** * 导出所有检查函数 */ export default { checkRequirementDesign, checkDesignCode, checkRequirementCode, runThreeWayCheck, findDeviations }