Skip to main content
Glama
SiroSuzume

MCP ts-morph Refactoring Tools

by SiroSuzume
find-declarations-to-update.ts3.44 kB
import type { SourceFile, ImportDeclaration, ExportDeclaration, } from "ts-morph"; import type { DeclarationToUpdate } from "../types"; import { getTsConfigPaths } from "./ts-morph-project"; import logger from "../../utils/logger"; /** * モジュール指定子が tsconfig で定義されたパスエイリアスを使用しているかチェックする */ function checkIsPathAlias( specifier: string, tsConfigPaths?: Record<string, string[]>, ): boolean { if (!tsConfigPaths) { return false; } return Object.keys(tsConfigPaths).some((aliasKey) => specifier.startsWith(aliasKey.replace(/\*$/, "")), ); } /** * ターゲットファイルを参照するすべての Import/Export 宣言を検索する。 * ts-morph の getReferencingSourceFiles を使用。 * 注意: バレルファイル (例: index.ts) 経由の再エクスポートによる参照は見つけられない可能性がある。 */ export async function findDeclarationsReferencingFile( targetFile: SourceFile, signal?: AbortSignal, ): Promise<DeclarationToUpdate[]> { signal?.throwIfAborted(); const results: DeclarationToUpdate[] = []; const targetFilePath = targetFile.getFilePath(); const project = targetFile.getProject(); const tsConfigPaths = getTsConfigPaths(project); logger.trace( { targetFile: targetFilePath }, "Starting findDeclarationsReferencingFile using getReferencingSourceFiles", ); // ts-morph の組み込みメソッドを使用して参照元ソースファイルを見つける const referencingSourceFiles = targetFile.getReferencingSourceFiles(); logger.trace( { count: referencingSourceFiles.length }, "Found referencing source files via ts-morph", ); const uniqueDeclarations = new Set<ImportDeclaration | ExportDeclaration>(); for (const referencingFile of referencingSourceFiles) { signal?.throwIfAborted(); const referencingFilePath = referencingFile.getFilePath(); try { const declarations = [ ...referencingFile.getImportDeclarations(), ...referencingFile.getExportDeclarations(), ]; for (const declaration of declarations) { signal?.throwIfAborted(); if (uniqueDeclarations.has(declaration)) continue; const moduleSpecifier = declaration.getModuleSpecifier(); if (!moduleSpecifier) continue; // 宣言が *実際に* ターゲットファイルに解決されるか確認する const specifierSourceFile = declaration.getModuleSpecifierSourceFile(); if (specifierSourceFile?.getFilePath() === targetFilePath) { const originalSpecifierText = moduleSpecifier.getLiteralText(); if (originalSpecifierText) { const wasPathAlias = checkIsPathAlias( originalSpecifierText, tsConfigPaths, ); results.push({ declaration, resolvedPath: targetFilePath, referencingFilePath: referencingFilePath, originalSpecifierText, wasPathAlias, }); uniqueDeclarations.add(declaration); logger.trace( { referencingFile: referencingFilePath, specifier: originalSpecifierText, kind: declaration.getKindName(), }, "Found relevant declaration", ); } } } } catch (err) { logger.warn( { file: referencingFilePath, err }, "Error processing referencing file", ); } } logger.trace( { foundCount: results.length }, "Finished findDeclarationsReferencingFile", ); return results; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SiroSuzume/mcp-ts-morph'

If you have feedback or need assistance with the MCP directory API, please join our Discord server