UNPKG

refakts

Version:

TypeScript refactoring tool built for AI coding agents to perform precise refactoring operations via command line instead of requiring complete code regeneration.

162 lines 6.49 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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.VariableLocatorCommand = void 0; const variable_locator_1 = require("../locators/variable-locator"); const location_parser_1 = require("../core/location-parser"); const ast_service_1 = require("../services/ast-service"); const path = __importStar(require("path")); class VariableLocatorCommand { constructor() { this.name = 'variable-locator'; this.description = 'Find variable declarations and all their usages'; this.complete = true; this.astService = new ast_service_1.ASTService(); } async execute(target, options) { const finalOptions = this.processTarget(target, options); this.validateOptions(finalOptions); try { await this.executeLocatorOperation(finalOptions); } catch (error) { this.handleExecutionError(error); } } async executeLocatorOperation(options) { const result = await this.performLocatorOperation(options); this.outputResults(result); } async performLocatorOperation(options) { const location = options.location; const node = await this.findTargetNode(location); const variableName = this.getVariableName(node); return await this.findAndFormatReferences(location, variableName); } async findTargetNode(location) { const node = await this.astService.findNodeByLocation(location); if (!node) { throw new Error('Could not find node at specified location'); } return node; } async findAndFormatReferences(location, variableName) { const locator = new variable_locator_1.VariableLocator(); const result = await locator.findVariableReferences(location.file, variableName); const fileName = path.basename(location.file); return this.formatAsLocations(result, fileName); } handleExecutionError(error) { process.stderr.write(`Error: ${error}\n`); process.exit(1); } validateOptions(options) { if (!options.location) { throw new Error('Location format must be specified'); } } getHelpText() { return '\nExamples:\n refakts variable-locator "[src/file.ts 10:5-10:10]"\n refakts variable-locator "[src/file.ts 3:15-3:20]"'; } processTarget(target, options) { if (location_parser_1.LocationParser.isLocationFormat(target)) { const location = location_parser_1.LocationParser.parseLocation(target); return { ...options, location }; } return { ...options, target }; } formatAsLocations(result, fileName) { const locations = []; this.addDeclarationLocation(result, fileName, locations); this.addUsageLocations(result, fileName, locations); return locations; } addDeclarationLocation(result, fileName, locations) { if (result.declaration) { const decl = result.declaration; locations.push(`[${fileName} ${decl.line}:${decl.column}-${decl.line}:${decl.column + decl.text.length}] ${decl.text}`); } } addUsageLocations(result, fileName, locations) { if (result.usages) { for (const usage of result.usages) { locations.push(`[${fileName} ${usage.line}:${usage.column}-${usage.line}:${usage.column + usage.text.length}] ${usage.text}`); } } } outputResults(results) { // eslint-disable-next-line no-console results.forEach(result => console.log(result)); } getVariableName(node) { return this.isIdentifierNode(node) ? node.getText() : this.extractCandidateNameOrThrow(node); } extractCandidateNameOrThrow(node) { const candidateName = this.extractCandidateName(node); if (!candidateName) { throw new Error('Could not extract variable name from node'); } return candidateName; } isIdentifierNode(node) { return node.getKind() === 75; } extractCandidateName(node) { return this.trySimpleTextExtraction(node) || this.tryVariableDeclarationExtraction(node) || this.tryIdentifierDescendantExtraction(node); } trySimpleTextExtraction(node) { const text = node.getText().trim(); return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(text) ? text : null; } tryVariableDeclarationExtraction(node) { if (node.getKind() === 261) { const symbol = node.getSymbol(); const declarations = symbol?.getDeclarations(); const variableDeclaration = declarations?.[0]; return variableDeclaration ? variableDeclaration.getText() : null; } return null; } tryIdentifierDescendantExtraction(node) { const identifiers = node.getDescendantsOfKind(75); return identifiers.length > 0 ? identifiers[0].getText() : null; } } exports.VariableLocatorCommand = VariableLocatorCommand; //# sourceMappingURL=variable-locator-command.js.map