UNPKG

@vibe-dev-kit/cli

Version:

Advanced Command-line toolkit that analyzes your codebase and deploys project-aware rules, memories, commands and agents to any AI coding assistant - VDK is the world's first Vibe Development Kit

204 lines (180 loc) 6.34 kB
/** * typescript.js * * Analyzer for TypeScript code to detect naming conventions, * patterns, interfaces, types, and commonly used libraries or frameworks. */ import { TypeScriptParser } from '../utils/typescript-parser.js' import { analyzeJavaScript } from './javascript.js' /** * Analyzes TypeScript code to detect naming conventions and patterns * @param {string} content - TypeScript code content * @param {string} filePath - Path to the file * @returns {Object} Analysis results */ export async function analyzeTypeScript(content, filePath) { try { // First check if this is definitely a TypeScript file const isTypeScriptFile = TypeScriptParser.isTypeScriptFile(filePath) if (!isTypeScriptFile) { // If it's not a TypeScript file, just use the JavaScript analyzer return await analyzeJavaScript(content, filePath) } // For TypeScript files, use regex-based parsing instead of AST parsing // This avoids the issue with acorn parser not understanding TypeScript syntax const jsAnalysis = { variables: [], functions: [], classes: [], components: [], patterns: [], } // Use regex patterns to extract TypeScript constructs safely try { // Extract variable declarations const varPattern = /(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g let match while ((match = varPattern.exec(content)) !== null) { if (match[1]) { jsAnalysis.variables.push(match[1]) } } // Extract function declarations const funcPattern = /(?:function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)|(?:const|let)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*(?:async\s+)?(?:\([^)]*\)\s*=>|\([^)]*\)\s*:\s*[^=]*\s*=>))/g while ((match = funcPattern.exec(content)) !== null) { const funcName = match[1] || match[2] if (funcName) { jsAnalysis.functions.push(funcName) } } // Extract class declarations const classPattern = /class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g while ((match = classPattern.exec(content)) !== null) { if (match[1]) { jsAnalysis.classes.push(match[1]) } } // Extract React components (functional components) const componentPattern = /(?:const|let|var|function)\s+([A-Z][a-zA-Z0-9_$]*)/g while ((match = componentPattern.exec(content)) !== null) { if ( match[1] && (content.includes('JSX.Element') || content.includes('React.FC') || content.includes('</')) ) { jsAnalysis.components.push(match[1]) } } // Detect common patterns if (content.includes('useState') || content.includes('useEffect')) { jsAnalysis.patterns.push('React Hooks') } if (content.includes('async/await') || content.includes('async ')) { jsAnalysis.patterns.push('Async/Await') } } catch (regexError) { // If regex parsing fails, just continue with empty analysis console.warn(`Warning: Regex parsing failed for ${filePath}: ${regexError.message}`) } // Extend with TypeScript-specific analysis const tsAnalysis = { ...jsAnalysis, interfaces: [], types: [], // Additional TypeScript patterns patterns: [...(jsAnalysis.patterns || [])], } // Simple regex-based detection for TypeScript features // This is a simplified approach - a proper TS parser would be better // but would increase complexity significantly // Detect interfaces const interfacePattern = /interface\s+([A-Za-z0-9_]+)/g let match while ((match = interfacePattern.exec(content)) !== null) { if (match[1]) { tsAnalysis.interfaces.push(match[1]) } } // Detect type aliases const typePattern = /type\s+([A-Za-z0-9_]+)/g while ((match = typePattern.exec(content)) !== null) { if (match[1]) { tsAnalysis.types.push(match[1]) } } // Detect decorators (Angular patterns) if ( content.includes('@Component') || content.includes('@NgModule') || content.includes('@Injectable') ) { tsAnalysis.patterns.push('Angular Decorators') } // Detect NestJS patterns if ( content.includes('@Controller') || content.includes('@Injectable') || content.includes('@Module') ) { tsAnalysis.patterns.push('NestJS Decorators') } // Detect TypeORM patterns if ( content.includes('@Entity') || content.includes('@Column') || content.includes('@Repository') ) { tsAnalysis.patterns.push('TypeORM') } // Detect functional patterns const genericPattern = /<[^>]+>/g const genericMatches = content.match(genericPattern) || [] if (genericMatches.length > 5) { tsAnalysis.patterns.push('Heavy Generic Usage') } // Check for type guards if (content.includes(' is ') && content.includes('function') && content.includes(': boolean')) { tsAnalysis.patterns.push('Type Guards') } // Look for utility types if ( content.includes('Partial<') || content.includes('Readonly<') || content.includes('Record<') || content.includes('Pick<') || content.includes('Omit<') ) { tsAnalysis.patterns.push('Utility Types') } // Look for React with TypeScript patterns if ( (content.includes('React.FC') || content.includes('FC<') || content.includes(': React.FC')) && (content.includes('interface') || content.includes('type')) ) { tsAnalysis.patterns.push('React with TypeScript') } // Check for mapped types if (content.includes('keyof') || content.includes('in keyof')) { tsAnalysis.patterns.push('Mapped Types') } // Deduplicate patterns and names tsAnalysis.patterns = [...new Set(tsAnalysis.patterns)] tsAnalysis.interfaces = [...new Set(tsAnalysis.interfaces)] tsAnalysis.types = [...new Set(tsAnalysis.types)] return tsAnalysis } catch (error) { console.error(`Error analyzing TypeScript file: ${filePath}`) console.error(error.message) return { variables: [], functions: [], classes: [], components: [], interfaces: [], types: [], patterns: [], } } }