import * as vscode from 'vscode'; import { FileModel, FileEntry } from './model'; // 性能监控类 export class PerformanceMonitor { private extractionTimes: number[] = []; private fileCounts: number[] = []; private functionCounts: number[] = []; // 记录函数提取性能 recordExtraction(timeMs: number, fileCount: number, functionCount: number): void { this.extractionTimes.push(timeMs); this.fileCounts.push(fileCount); this.functionCounts.push(functionCount); } // 获取平均提取时间 getAverageExtractionTime(): number { if (this.extractionTimes.length === 0) return 0; const sum = this.extractionTimes.reduce((a, b) => a + b, 0); return sum / this.extractionTimes.length; } // 获取平均每文件处理时间 getAverageTimePerFile(): number { if (this.fileCounts.length === 0 || this.extractionTimes.length === 0) return 0; const totalTime = this.extractionTimes.reduce((a, b) => a + b, 0); const totalFiles = this.fileCounts.reduce((a, b) => a + b, 0); return totalFiles > 0 ? totalTime / totalFiles : 0; } // 获取性能统计信息 getStats(): { averageExtractionTime: number; averageTimePerFile: number; totalExtractions: number; } { return { averageExtractionTime: this.getAverageExtractionTime(), averageTimePerFile: this.getAverageTimePerFile(), totalExtractions: this.extractionTimes.length }; } // 清除统计数据 clearStats(): void { this.extractionTimes = []; this.fileCounts = []; this.functionCounts = []; } } // 函数信息接口 export interface FunctionInfo { name: string; // 函数名称 filePath: string; // 文件路径 lineNumber: number; // 行号 parameters: string[]; // 参数列表 signature: string; // 函数签名 } // 函数缓存管理类 export class FunctionCacheManager { private functionCache = new Map(); private fileProcessed = new Set(); // 添加函数信息到缓存 addFunctions(filePath: string, functions: FunctionInfo[]): void { this.functionCache.set(filePath, functions); this.fileProcessed.add(filePath); } // 获取文件的函数信息 getFunctions(filePath: string): FunctionInfo[] | undefined { return this.functionCache.get(filePath); } // 检查文件是否已处理 isFileProcessed(filePath: string): boolean { return this.fileProcessed.has(filePath); } // 清除特定文件的缓存 clearFileCache(filePath: string): void { this.functionCache.delete(filePath); this.fileProcessed.delete(filePath); } // 清除所有缓存 clearAllCache(): void { this.functionCache.clear(); this.fileProcessed.clear(); } // 获取缓存统计信息 getCacheStats(): { fileCount: number; functionCount: number } { let functionCount = 0; for (const functions of this.functionCache.values()) { functionCount += functions.length; } return { fileCount: this.functionCache.size, functionCount: functionCount }; } // 获取所有缓存的函数信息 getAllFunctions(): FunctionInfo[] { const allFunctions: FunctionInfo[] = []; for (const functions of this.functionCache.values()) { allFunctions.push(...functions); } return allFunctions; } // 根据函数名称查找函数信息 findFunctionsByName(functionName: string): FunctionInfo[] { const allFunctions = this.getAllFunctions(); return allFunctions.filter(func => func.name === functionName); } // 根据文件路径查找函数信息 findFunctionsByFilePath(filePath: string): FunctionInfo[] { return this.getFunctions(filePath) || []; } } // 函数提取器类 export class FunctionExtractor { private cacheManager: FunctionCacheManager; private isExtracting = false; // 防止重复提取 private performanceMonitor: PerformanceMonitor; constructor() { this.cacheManager = new FunctionCacheManager(); this.performanceMonitor = new PerformanceMonitor(); } // 获取缓存管理器 getCacheManager(): FunctionCacheManager { return this.cacheManager; } // 获取性能监控器 getPerformanceMonitor(): PerformanceMonitor { return this.performanceMonitor; } // 检查是否正在提取函数 isExtractingFunctions(): boolean { return this.isExtracting; } // 从文件内容中提取函数信息 extractFunctionsFromFile(filePath: string, content: string): FunctionInfo[] { const functions: FunctionInfo[] = []; const lines = content.split('\n'); // Squirrel语言函数定义的正则表达式 // 匹配类似: function functionName(param1, param2, ...) const functionRegex = /^\s*function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(([^)]*)\)/; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const match = line.match(functionRegex); if (match) { const functionName = match[1]; const paramsString = match[2]; const parameters = this.parseParameters(paramsString); const functionInfo: FunctionInfo = { name: functionName, filePath: filePath, lineNumber: i + 1, parameters: parameters, signature: `function ${functionName}(${paramsString})` }; functions.push(functionInfo); } } return functions; } // 解析参数字符串 private parseParameters(paramsString: string): string[] { if (!paramsString.trim()) { return []; } // 简单参数解析,按逗号分割 return paramsString.split(',').map(param => param.trim()).filter(param => param.length > 0); } // 批量提取函数信息 async extractFunctionsFromFiles(model: FileModel, filePaths: string[]): Promise { // 防止重复提取 if (this.isExtracting) { console.log('函数提取已在进行中,跳过本次请求'); return; } this.isExtracting = true; console.log(`开始提取 ${filePaths.length} 个文件中的函数信息`); try { // 分批处理文件,避免一次性处理过多文件 const batchSize = 50; for (let i = 0; i < filePaths.length; i += batchSize) { const batch = filePaths.slice(i, i + batchSize); console.log(`正在处理批次 ${Math.floor(i/batchSize) + 1}/${Math.ceil(filePaths.length/batchSize)}: ${batch.length} 个文件`); try { // 并行处理批次中的文件 const promises = batch.map(async (filePath) => { // 检查文件是否已处理过 if (this.cacheManager.isFileProcessed(filePath)) { return; } try { const entry = model.getFileEntry(filePath); if (!entry) { console.warn(`文件 ${filePath} 不存在于文件列表中`); return; } // 如果文件内容尚未加载,则加载内容 let content = entry.content; if (!content) { content = await model.getFileContent(filePath); } if (content) { const functions = this.extractFunctionsFromFile(filePath, content); this.cacheManager.addFunctions(filePath, functions); console.log(`文件 ${filePath} 提取到 ${functions.length} 个函数`); } } catch (error) { console.error(`处理文件 ${filePath} 时出错:`, error); } }); // 等待批次处理完成 await Promise.all(promises); console.log(`批次 ${Math.floor(i/batchSize) + 1} 处理完成`); } catch (batchError) { console.error(`处理批次 ${Math.floor(i/batchSize) + 1} 时出错:`, batchError); } } console.log('所有文件的函数信息提取完成'); } finally { this.isExtracting = false; } } // 提取所有文件的函数信息 async extractAllFunctions(model: FileModel): Promise { const startTime = Date.now(); // 获取所有nut文件路径 const filePaths = model.getAllNutFiles(); console.log(`准备提取 ${filePaths.length} 个nut文件的函数信息`); if (filePaths.length === 0) { console.log('没有nut文件需要处理'); return; } await this.extractFunctionsFromFiles(model, filePaths); // 输出缓存统计信息 const stats = this.cacheManager.getCacheStats(); const endTime = Date.now(); const durationMs = endTime - startTime; const durationSec = durationMs / 1000; // 转换为秒 // 记录性能数据 this.performanceMonitor.recordExtraction(durationMs, filePaths.length, stats.functionCount); console.log(`函数缓存统计: ${stats.fileCount} 个文件, ${stats.functionCount} 个函数`); console.log(`函数提取完成,耗时: ${durationSec.toFixed(2)} 秒`); // 输出性能统计信息 const perfStats = this.performanceMonitor.getStats(); console.log(`性能统计: 平均提取时间 ${perfStats.averageExtractionTime.toFixed(2)}ms, 平均每文件处理时间 ${perfStats.averageTimePerFile.toFixed(2)}ms`); } // 更新特定文件的函数缓存 async updateFileCache(model: FileModel, filePath: string): Promise { console.log(`更新文件 ${filePath} 的函数缓存`); try { // 获取文件内容 const content = await model.getFileContent(filePath); if (content) { // 提取函数信息 const functions = this.extractFunctionsFromFile(filePath, content); // 更新缓存 this.cacheManager.addFunctions(filePath, functions); console.log(`文件 ${filePath} 的函数缓存已更新,提取到 ${functions.length} 个函数`); } else { console.warn(`无法获取文件 ${filePath} 的内容`); } } catch (error) { console.error(`更新文件 ${filePath} 的函数缓存时出错:`, error); } } }