UNPKG

sicua

Version:

A tool for analyzing project structure and dependencies

280 lines (279 loc) โ€ข 13.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DebugConditionalAnalyzer = void 0; const fs = __importStar(require("fs")); const JSXReturnAnalyzer_1 = require("./scanners/JSXReturnAnalyzer"); const ConditionalParser_1 = require("./parsers/ConditionalParser"); const utils_1 = require("./utils"); /** * Debug utility to analyze conditional rendering patterns and identify duplicates */ class DebugConditionalAnalyzer { constructor() { this.jsxAnalyzer = new JSXReturnAnalyzer_1.JSXReturnAnalyzer(); this.conditionalParser = new ConditionalParser_1.ConditionalParser(); } /** * Analyzes all conditionals in a file and logs detailed information */ debugFileConditionals(filePath) { console.log(`\n๐Ÿ” DEBUG ANALYSIS: ${filePath}`); console.log("=".repeat(80)); try { const content = fs.readFileSync(filePath, "utf-8"); const ast = (0, utils_1.parseFileToAST)(content); if (!ast) { console.log("โŒ Failed to parse AST"); return; } // Get JSX returns from the file const jsxReturns = this.jsxAnalyzer.analyzeAST(ast, content); console.log(`๐Ÿ“Š Found ${jsxReturns.length} JSX return statement(s)`); let totalConditionals = 0; const conditionFrequency = new Map(); jsxReturns.forEach((jsxReturn, returnIndex) => { console.log(`\n๐Ÿ“ JSX Return #${returnIndex + 1}:`); console.log(` Has Conditional: ${jsxReturn.hasConditional}`); console.log(` Position: Line ${jsxReturn.position.line}, Column ${jsxReturn.position.column}`); console.log(` Component References: ${jsxReturn.componentReferences.length}`); if (jsxReturn.hasConditional) { console.log(` Conditional Patterns: ${jsxReturn.conditionalPatterns.length}`); jsxReturn.conditionalPatterns.forEach((pattern, patternIndex) => { totalConditionals++; // Track frequency of each condition const count = conditionFrequency.get(pattern.condition) || 0; conditionFrequency.set(pattern.condition, count + 1); console.log(`\n ๐ŸŽฏ Pattern #${patternIndex + 1}:`); console.log(` Type: ${pattern.type}`); console.log(` Condition: "${pattern.condition}"`); console.log(` Position: Line ${pattern.position.line}, Column ${pattern.position.column}`); console.log(` True Branch Components: ${pattern.trueBranch.length}`); console.log(` False Branch Components: ${pattern.falseBranch?.length || 0}`); // Show component names in branches if (pattern.trueBranch.length > 0) { const trueNames = pattern.trueBranch .map((comp) => comp.name) .join(", "); console.log(` True Branch: [${trueNames}]`); } if (pattern.falseBranch && pattern.falseBranch.length > 0) { const falseNames = pattern.falseBranch .map((comp) => comp.name) .join(", "); console.log(` False Branch: [${falseNames}]`); } }); } }); console.log(`\n๐Ÿ“ˆ SUMMARY FOR ${filePath}:`); console.log(` Total Conditional Patterns: ${totalConditionals}`); console.log(` Unique Conditions: ${conditionFrequency.size}`); if (conditionFrequency.size > 0) { console.log(`\n๐Ÿ”„ CONDITION FREQUENCY:`); Array.from(conditionFrequency.entries()) .sort((a, b) => b[1] - a[1]) .forEach(([condition, count]) => { const status = count > 1 ? "โš ๏ธ DUPLICATE" : "โœ… UNIQUE"; console.log(` ${status} "${condition}" appears ${count} time(s)`); }); } } catch (error) { console.error(`โŒ Error analyzing ${filePath}:`, error); } } /** * Analyzes multiple files and shows global duplication patterns */ debugMultipleFiles(filePaths) { console.log(`\n๐ŸŒ GLOBAL CONDITIONAL ANALYSIS`); console.log("=".repeat(80)); const globalConditionFrequency = new Map(); let globalTotal = 0; filePaths.forEach((filePath) => { try { const content = fs.readFileSync(filePath, "utf-8"); const ast = (0, utils_1.parseFileToAST)(content); if (!ast) return; const jsxReturns = this.jsxAnalyzer.analyzeAST(ast, content); jsxReturns.forEach((jsxReturn) => { if (jsxReturn.hasConditional) { jsxReturn.conditionalPatterns.forEach((pattern) => { globalTotal++; const existing = globalConditionFrequency.get(pattern.condition) || { count: 0, files: [] }; existing.count++; if (!existing.files.includes(filePath)) { existing.files.push(filePath); } globalConditionFrequency.set(pattern.condition, existing); }); } }); } catch (error) { console.warn(`โš ๏ธ Skipped ${filePath}: ${error}`); } }); console.log(`\n๐Ÿ“Š GLOBAL SUMMARY:`); console.log(` Total Conditional Patterns Found: ${globalTotal}`); console.log(` Unique Conditions: ${globalConditionFrequency.size}`); console.log(` Expected Conditionals (if no duplicates): ${globalConditionFrequency.size}`); console.log(` Duplication Factor: ${(globalTotal / globalConditionFrequency.size).toFixed(2)}x`); console.log(`\n๐Ÿ” DETAILED BREAKDOWN:`); Array.from(globalConditionFrequency.entries()) .sort((a, b) => b[1].count - a[1].count) .forEach(([condition, data]) => { const status = data.count > 1 ? "๐Ÿšจ DUPLICATE" : "โœ… UNIQUE"; console.log(`\n ${status} "${condition}"`); console.log(` Appears: ${data.count} time(s)`); console.log(` In files: ${data.files.length}`); if (data.count > 1) { data.files.forEach((file) => { const fileName = file.split(/[/\\]/).pop(); console.log(` - ${fileName}`); }); } }); } /** * Debug complete component flow analysis with proper typing */ debugCompleteFlowAnalysis(appDirectory) { console.log(`\n๐ŸŒ COMPLETE COMPONENT FLOW ANALYSIS DEBUG`); console.log("=".repeat(80)); try { // Import the required modules dynamically to avoid type issues const RouteScanner = require("./scanners/RouteScanner").RouteScanner; const FlowTreeBuilder = require("./builders/FlowTreeBuilder").FlowTreeBuilder; const routeScanner = new RouteScanner(appDirectory); const routes = routeScanner.scanAllRoutes(); console.log(`\n๐Ÿ“‹ Found ${routes.length} routes to analyze`); const flowTreeBuilder = new FlowTreeBuilder(appDirectory.replace("/app", ""), appDirectory.replace("/app", "/src"), appDirectory, [] // Empty components for debug ); let globalConditionalCount = 0; const componentConditionalMap = new Map(); routes.forEach((route, index) => { console.log(`\n๐Ÿ” ANALYZING ROUTE ${index + 1}: ${route.routePath}`); console.log("-".repeat(50)); try { const tree = flowTreeBuilder.buildRouteFlowTree(route); const routeConditionals = tree.componentStats.conditionalRenderCount; console.log(`๐Ÿ“Š Route conditionals: ${routeConditionals}`); console.log(`๐Ÿงฎ Route components: ${tree.componentStats.totalComponents}`); globalConditionalCount += routeConditionals; // Track components and their conditionals this.debugComponentTree(tree.pageComponent, componentConditionalMap, 0); } catch (error) { console.error(`โŒ Error analyzing route ${route.routePath}:`, error); } }); console.log(`\n๐Ÿ“ˆ FINAL SUMMARY:`); console.log(` Total routes: ${routes.length}`); console.log(` Global conditional count: ${globalConditionalCount}`); console.log(` Expected (from debug): 13-20`); console.log(` Multiplication factor: ${(globalConditionalCount / 15).toFixed(2)}x`); console.log(`\n๐Ÿ” COMPONENT BREAKDOWN:`); Array.from(componentConditionalMap.entries()) .sort((a, b) => b[1] - a[1]) .forEach(([component, count]) => { if (count > 0) { console.log(` ${component}: ${count} conditionals`); } }); } catch (error) { console.error(`โŒ Error in complete flow analysis:`, error); } } /** * Debug component tree recursively with proper typing */ debugComponentTree(component, componentMap, depth) { const indent = " ".repeat(depth); const conditionalCount = component.conditionalRenders?.length || 0; console.log(`${indent}๐Ÿ“ฆ ${component.componentName} (${conditionalCount} conditionals)`); // Track in map const existing = componentMap.get(component.componentName) || 0; componentMap.set(component.componentName, existing + conditionalCount); // Process conditional renders if (component.conditionalRenders) { component.conditionalRenders.forEach((conditional, index) => { console.log(`${indent} ๐ŸŽฏ Conditional ${index + 1}: "${conditional.condition}"`); // True branch if (conditional.trueBranch) { conditional.trueBranch.forEach((child) => { this.debugComponentTree(child, componentMap, depth + 2); }); } // False branch if (conditional.falseBranch) { conditional.falseBranch.forEach((child) => { this.debugComponentTree(child, componentMap, depth + 2); }); } }); } // Process regular children if (component.children) { component.children.forEach((child) => { this.debugComponentTree(child, componentMap, depth + 1); }); } } /** * Quick debug for specific test files */ debugTestProject(appDirectory) { const testFiles = [ `${appDirectory}/page.tsx`, // Home page `${appDirectory}/blog/[...slug]/page.tsx`, // Blog page `${appDirectory}/dashboard/page.tsx`, // Dashboard `${appDirectory}/dashboard/analytics/page.tsx`, // Analytics ]; console.log(`๐Ÿงช DEBUGGING TEST PROJECT CONDITIONALS`); console.log("=".repeat(80)); // Analyze each file individually testFiles.forEach((file) => { if (fs.existsSync(file)) { this.debugFileConditionals(file); } }); // Global analysis const existingFiles = testFiles.filter((file) => fs.existsSync(file)); if (existingFiles.length > 0) { this.debugMultipleFiles(existingFiles); } // Now run the complete flow analysis this.debugCompleteFlowAnalysis(appDirectory); } } exports.DebugConditionalAnalyzer = DebugConditionalAnalyzer; // Usage example: // const debugger = new DebugConditionalAnalyzer(); // debugger.debugTestProject("/path/to/your/app"); // debugger.debugFileConditionals("/path/to/specific/file.tsx");