UNPKG

sicua

Version:

A tool for analyzing project structure and dependencies

187 lines (186 loc) 7.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StateAnalysisUtils = void 0; const typescript_1 = __importDefault(require("typescript")); const statePatterns_1 = require("../../constants/statePatterns"); class StateAnalysisUtils { /** * Finds state references within a selector function */ static findStatesInSelector(node) { const states = new Set(); const visit = (n) => { if (typescript_1.default.isPropertyAccessExpression(n)) { const statePath = this.buildStatePath(n); if (statePath && this.isStateAccess(statePath)) { states.add(statePath); } } typescript_1.default.forEachChild(n, visit); }; visit(node); return Array.from(states); } /** * Extracts action type from various action patterns */ static extractActionType(node, findActionCreator) { // Handle object literals (e.g., { type: 'ACTION_TYPE' }) if (typescript_1.default.isObjectLiteralExpression(node)) { const typeProperty = node.properties.find((prop) => typescript_1.default.isPropertyAssignment(prop) && (typescript_1.default.isIdentifier(prop.name) || typescript_1.default.isStringLiteral(prop.name)) && (prop.name.getText() === "type" || prop.name.getText() === '"type"')); if (typeProperty) { return this.extractTypeFromInitializer(typeProperty.initializer); } } // Handle call expressions (action creators) else if (typescript_1.default.isCallExpression(node)) { // Direct string literal type argument if (node.typeArguments?.length === 1) { const typeArg = node.typeArguments[0]; if (typescript_1.default.isLiteralTypeNode(typeArg) && typescript_1.default.isStringLiteral(typeArg.literal)) { return typeArg.literal.text; } } // Handle various action creator patterns const expression = node.expression; // Named action creator: createAction('ACTION_TYPE') if (typescript_1.default.isIdentifier(expression) && findActionCreator) { const actionCreator = findActionCreator(expression.text); if (actionCreator) { return this.extractActionType(actionCreator, findActionCreator); } } // Direct createAction call with string literal else if (typescript_1.default.isIdentifier(expression) && ["createAction", "action"].includes(expression.text) && node.arguments.length > 0) { const firstArg = node.arguments[0]; if (typescript_1.default.isStringLiteral(firstArg)) { return firstArg.text; } } } // Handle string literals and template literals else if (typescript_1.default.isStringLiteral(node)) { return node.text; } else if (typescript_1.default.isTemplateExpression(node)) { // Handle template literals with static content if (node.templateSpans.length === 0) { return node.head.text; } } // Handle type aliases and const declarations else if (typescript_1.default.isTypeAliasDeclaration(node) && typescript_1.default.isLiteralTypeNode(node.type)) { if (typescript_1.default.isStringLiteral(node.type.literal)) { return node.type.literal.text; } } else if (typescript_1.default.isVariableDeclaration(node) && node.initializer) { return this.extractTypeFromInitializer(node.initializer); } return undefined; } static extractTypeFromInitializer(initializer) { // Handle string literals if (typescript_1.default.isStringLiteral(initializer)) { return initializer.text; } // Handle template literals else if (typescript_1.default.isTemplateExpression(initializer)) { if (initializer.templateSpans.length === 0) { return initializer.head.text; } } // Handle property access (e.g., ActionTypes.UPDATE) else if (typescript_1.default.isPropertyAccessExpression(initializer)) { const symbol = typescript_1.default.isIdentifier(initializer.name) ? initializer.name.text : undefined; if (symbol) { return symbol; } } // Handle as expressions else if (typescript_1.default.isAsExpression(initializer)) { return this.extractTypeFromInitializer(initializer.expression); } return undefined; } // Helper to check if a node is likely an action type static isActionType(node) { return this.extractActionType(node) !== undefined; } // Helper to get full action type including namespace if present static getFullActionType(node) { const type = this.extractActionType(node); if (!type) return undefined; // Handle namespaced actions if (typescript_1.default.isPropertyAccessExpression(node)) { const namespace = node.expression.getText(); return `${namespace}.${type}`; } return type; } static buildStatePath(node) { const parts = []; let current = node; while (typescript_1.default.isPropertyAccessExpression(current)) { parts.unshift(current.name.text); current = current.expression; } if (typescript_1.default.isIdentifier(current)) { parts.unshift(current.text); } return parts.join("."); } /* private static isStateAccess(path: string): boolean { return path.startsWith("state.") || this.isKnownStatePattern(path); } */ static isStateAccess(path, storeDefinitions) { const pathLower = path.toLowerCase(); // Check common patterns if (statePatterns_1.STATE_PATTERNS.PREFIXES.has(path)) { return true; } // Check store definitions if available if (storeDefinitions?.size) { const rootPath = path.split('.')[0]; if (storeDefinitions.has(rootPath)) { return true; } // Check if path includes any known state keys for (const store of storeDefinitions.values()) { if (store.initialState && Object.keys(store.initialState).some(key => path.includes(key))) { return true; } } } // Check boolean state patterns if (statePatterns_1.STATE_PATTERNS.BOOLEAN_PREFIXES.has(pathLower.split(/[._]/)[0])) { return true; } // Check for state-related terms return statePatterns_1.STATE_PATTERNS.STATE_TERMS.has(pathLower); } static isKnownStatePattern(path) { // Add common state access patterns here const statePatterns = [ /^(state|store)\./, /^(get|select)/, /Store$/, /State$/, ]; return statePatterns.some((pattern) => pattern.test(path)); } } exports.StateAnalysisUtils = StateAnalysisUtils;