sicua
Version:
A tool for analyzing project structure and dependencies
163 lines (162 loc) • 6.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TranslationKeyFinder = void 0;
const astUtils_1 = require("../utils/astUtils");
const contextExtractor_1 = require("../extractors/contextExtractor");
/**
* Finds translation keys used in source code with enhanced context
*/
class TranslationKeyFinder {
constructor() {
this.translationKeys = [];
this.analyzedFiles = new Set();
this.contextExtractor = new contextExtractor_1.ContextExtractor();
}
/**
* Finds all translation keys in source files
* @param sourceFiles Map of source files to analyze
* @returns Promise resolving when analysis is complete
*/
async findAllTranslationKeys(sourceFiles) {
// Analyze each source file
for (const [filePath, sourceFile] of sourceFiles.entries()) {
// Skip files that we've already analyzed
if (this.analyzedFiles.has(filePath)) {
continue;
}
// Skip non-TypeScript/JavaScript files
if (!(0, astUtils_1.isTypeScriptFile)(filePath)) {
continue;
}
const results = this.analyzeSourceFile(sourceFile, filePath);
// Add the keys to our collection
this.translationKeys.push(...results.translationKeys);
// Mark as analyzed
this.analyzedFiles.add(filePath);
}
}
/**
* Gets the collected translation keys
* @returns Array of translation keys
*/
getTranslationKeys() {
return this.translationKeys;
}
/**
* Analyzes a source file for translation hooks and calls
* @param sourceFile Source file to analyze
* @param filePath Path to the source file
* @returns Analysis results with hooks and keys
*/
analyzeSourceFile(sourceFile, filePath) {
// Find all translation hooks in the file (e.g., useTranslations)
const hooks = (0, astUtils_1.findTranslationHooksInFile)(sourceFile, filePath);
// Process each hook to find translation keys
const foundKeys = [];
for (const hook of hooks) {
const translationCalls = this.processTranslationHook(hook, sourceFile, filePath);
// Add the keys to our result
foundKeys.push(...translationCalls);
}
return {
hooks,
translationKeys: foundKeys,
};
}
/**
* Processes a translation hook to find translation keys
* @param hook Translation hook to process
* @param sourceFile Source file
* @param filePath File path
* @returns Array of translation keys
*/
processTranslationHook(hook, sourceFile, filePath) {
const { varName, namespace, componentName } = hook;
// Find all translation calls using this hook
const translationCalls = (0, astUtils_1.findTranslationCalls)(sourceFile, varName);
// Process each translation call
return translationCalls.map((call) => this.processTranslationCall(call, namespace, componentName, sourceFile, filePath));
}
/**
* Processes a translation call to create a translation key with usage context
* @param call Translation call
* @param namespace Optional namespace
* @param componentName Component name
* @param sourceFile Source file
* @param filePath File path
* @returns Translation key with usage context
*/
processTranslationCall(call, namespace, componentName, sourceFile, filePath) {
const { keyText, callNode } = { keyText: call.key, callNode: call.node };
// Create the basic translation key
const basicKey = (0, astUtils_1.processTranslationKey)(keyText, namespace, componentName, callNode, sourceFile, filePath);
// Enhance it with additional context
return this.contextExtractor.enhanceKeyWithContext(basicKey, sourceFile);
}
/**
* Groups translation keys by file path
* @returns Map of file paths to arrays of translation keys
*/
groupKeysByFile() {
const keysByFile = new Map();
for (const key of this.translationKeys) {
const existing = keysByFile.get(key.filePath) || [];
existing.push(key);
keysByFile.set(key.filePath, existing);
}
return keysByFile;
}
/**
* Finds files with the most translation keys
* @param limit Maximum number of files to return
* @returns Array of files sorted by key count
*/
findFilesWithMostKeys(limit = 10) {
const keysByFile = this.groupKeysByFile();
return Array.from(keysByFile.entries())
.map(([filePath, keys]) => ({
filePath,
keyCount: keys.length,
keys,
}))
.sort((a, b) => b.keyCount - a.keyCount)
.slice(0, limit);
}
/**
* Finds translation keys in JSX context
* @returns Array of keys used in JSX
*/
findKeysInJSX() {
return this.translationKeys.filter((key) => key.usageContext.isInJSX);
}
/**
* Finds translation keys in conditional rendering
* @returns Array of keys used in conditional rendering
*/
findKeysInConditionals() {
return this.translationKeys.filter((key) => key.usageContext.isInConditional);
}
/**
* Finds translation keys in event handlers
* @returns Array of keys used in event handlers
*/
findKeysInEventHandlers() {
return this.translationKeys.filter((key) => key.usageContext.isInEventHandler);
}
/**
* Groups translation keys by component
* @returns Map of component names to arrays of translation keys
*/
groupKeysByComponent() {
const keysByComponent = new Map();
for (const key of this.translationKeys) {
// Use the parent component from context if available
const componentName = key.usageContext.parentComponent || key.componentName;
const existing = keysByComponent.get(componentName) || [];
existing.push(key);
keysByComponent.set(componentName, existing);
}
return keysByComponent;
}
}
exports.TranslationKeyFinder = TranslationKeyFinder;