diff --git a/gofaster/app/plugins/modules/trigger-analyzer.js b/gofaster/app/plugins/modules/trigger-analyzer.js index acd173d..9462ae3 100644 --- a/gofaster/app/plugins/modules/trigger-analyzer.js +++ b/gofaster/app/plugins/modules/trigger-analyzer.js @@ -1,5 +1,7 @@ const { readFileSync, existsSync, readdirSync } = require('fs') const { resolve } = require('path') +const parser = require('@babel/parser') +const traverse = require('@babel/traverse').default const AstAnalyzer = require('./ast-analyzer') /** @@ -12,7 +14,7 @@ class TriggerAnalyzer { } /** - * 查找API方法的触发器源 + * 查找API方法的触发器源 - 第一步:第一层触发源分析 * @param {Array} apiMappings - API映射数组 * @returns {Array} 增强的API映射数组 */ @@ -26,30 +28,72 @@ class TriggerAnalyzer { } moduleMapping.apiMappings.forEach(apiMapping => { - const triggerSources = this.findTriggerSourcesForApiMethod( - apiMapping.serviceName, + // 第一步:查找第一层触发源 + const triggerSources = this.findFirstLevelTriggerSources( + moduleMapping.serviceName, // 使用第一层的serviceName apiMapping.apiMethodName, moduleMapping.module ) - if (triggerSources.length > 0) { - enhancedModuleMapping.apiMappings.push({ - ...apiMapping, - triggerSources: triggerSources - }) - } + // 为所有API映射添加triggerSources字段(即使为空) + enhancedModuleMapping.apiMappings.push({ + ...apiMapping, + triggerSources: triggerSources || [] + }) }) - if (enhancedModuleMapping.apiMappings.length > 0) { - enhancedApiMappings.push(enhancedModuleMapping) - } + // 返回所有模块映射(包括没有触发源的) + enhancedApiMappings.push(enhancedModuleMapping) }) return enhancedApiMappings } /** - * 查找API方法的触发器源 + * 查找第一层触发源 - 使用Babel分析真正的调用关系 + * @param {string} serviceName - 服务名称 + * @param {string} apiMethodName - API方法名称 + * @param {string} moduleName - 模块名称 + * @returns {Array} 触发器源数组 + */ + findFirstLevelTriggerSources(serviceName, apiMethodName, moduleName) { + const triggerSources = [] + + try { + // 1. 遍历模块中的所有Vue组件文件 + const modulePath = resolve(__dirname, `../../src/renderer/modules/${moduleName}`) + if (existsSync(modulePath)) { + const files = readdirSync(modulePath, { recursive: true }) + + files.forEach(file => { + if (typeof file === 'string' && file.endsWith('.vue')) { + const filePath = resolve(modulePath, file) + const componentName = this.extractComponentNameFromPath(file) + + // 2. 使用Babel分析Vue组件中的API调用 + const componentTriggerSources = this.analyzeComponentForApiCalls( + filePath, + serviceName, + apiMethodName, + componentName + ) + + triggerSources.push(...componentTriggerSources) + } + }) + } + } catch (error) { + console.warn(`分析模块 ${moduleName} 时出错:`, error.message) + } + + // 去重 + const uniqueTriggerSources = this.deduplicateTriggerSources(triggerSources) + + return uniqueTriggerSources + } + + /** + * 查找API方法的触发器源(保留原方法用于后续扩展) * @param {string} serviceName - 服务名称 * @param {string} apiMethodName - API方法名称 * @param {string} moduleName - 模块名称 @@ -105,17 +149,23 @@ class TriggerAnalyzer { if (existsSync(routeConfigPath)) { const routeContent = readFileSync(routeConfigPath, 'utf-8') - // 简单的路由解析,查找模块相关的路由 - const routeMatches = routeContent.match(new RegExp(`component:\\s*['"]${moduleName}[^'"]*['"]`, 'g')) - if (routeMatches) { - routeMatches.forEach(match => { - const componentMatch = match.match(/component:\s*['"]([^'"]+)['"]/) - if (componentMatch) { - routeComponents.push({ - component: componentMatch[1] - }) - } - }) + // 根据模块名称映射到对应的组件名称 + const moduleToComponentMap = { + 'role-management': 'RoleManagement', + 'user-management': 'UserManagement', + 'system-settings': 'Settings', + 'user-profile': 'UserProfile' + } + + const componentName = moduleToComponentMap[moduleName] + if (componentName) { + // 查找包含该组件的路由 + const routeMatches = routeContent.match(new RegExp(`component:\\s*${componentName}`, 'g')) + if (routeMatches) { + routeComponents.push({ + component: componentName + }) + } } } } catch (error) { @@ -402,6 +452,358 @@ class TriggerAnalyzer { return true }) } + + /** + * 从文件路径提取组件名称 + * @param {string} filePath - 文件路径 + * @returns {string} 组件名称 + */ + extractComponentNameFromPath(filePath) { + const fileName = filePath.split('/').pop().split('\\').pop() + return fileName.replace('.vue', '') + } + + /** + * 分析Vue组件中的API调用 + * @param {string} filePath - 组件文件路径 + * @param {string} serviceName - 服务名称 + * @param {string} apiMethodName - API方法名称 + * @param {string} componentName - 组件名称 + * @returns {Array} 触发源数组 + */ + analyzeComponentForApiCalls(filePath, serviceName, apiMethodName, componentName) { + const triggerSources = [] + + try { + const content = readFileSync(filePath, 'utf-8') + + // 使用Babel解析Vue组件 + const ast = this.parseVueComponent(content) + if (!ast) return triggerSources + + // 查找API调用和函数调用关系 + const apiCalls = this.findApiCallsWithContext(ast, serviceName, apiMethodName) + + // 为每个API调用创建触发源 + apiCalls.forEach(call => { + triggerSources.push({ + component: componentName, + triggerName: call.triggerName || '', + triggerType: call.triggerType || 'function' + }) + }) + + } catch (error) { + console.warn(`分析组件 ${filePath} 时出错:`, error.message) + } + + return triggerSources + } + + /** + * 解析Vue组件内容 + * @param {string} content - 组件内容 + * @returns {Object|null} AST对象 + */ + parseVueComponent(content) { + try { + // 提取