@esportsplus/typescript
Advanced tools
| import { ts } from '../index.js'; | ||
| import imports from './imports.js'; | ||
| const DIRECTORY_SEPARATOR = /\\/g; | ||
| function applyImports(code, file, intents) { | ||
@@ -47,20 +46,2 @@ for (let i = 0, n = intents.length; i < n; i++) { | ||
| } | ||
| function createUpdatedProgram(originalProgram, fileName, newCode) { | ||
| let options = originalProgram.getCompilerOptions(), originalHost = ts.createCompilerHost(options), originalGetSourceFile = originalHost.getSourceFile.bind(originalHost), originalReadFile = originalHost.readFile.bind(originalHost); | ||
| originalHost.getSourceFile = (name, languageVersion, onError, shouldCreateNewSourceFile) => { | ||
| if (name === fileName || | ||
| name.replace(DIRECTORY_SEPARATOR, '/') === fileName.replace(DIRECTORY_SEPARATOR, '/')) { | ||
| return ts.createSourceFile(name, newCode, languageVersion, true); | ||
| } | ||
| return originalGetSourceFile(name, languageVersion, onError, shouldCreateNewSourceFile); | ||
| }; | ||
| originalHost.readFile = (name) => { | ||
| if (name === fileName || | ||
| name.replace(DIRECTORY_SEPARATOR, '/') === fileName.replace(DIRECTORY_SEPARATOR, '/')) { | ||
| return newCode; | ||
| } | ||
| return originalReadFile(name); | ||
| }; | ||
| return ts.createProgram(originalProgram.getRootFileNames(), options, originalHost, originalProgram); | ||
| } | ||
| function hasPattern(code, patterns) { | ||
@@ -140,3 +121,3 @@ for (let i = 0, n = patterns.length; i < n; i++) { | ||
| } | ||
| let currentCode = code, currentFile = file, currentProgram = program, fileName = file.fileName, transformed = false; | ||
| let checker = program.getTypeChecker(), currentCode = code, currentFile = file, fileName = file.fileName; | ||
| for (let i = 0, n = plugins.length; i < n; i++) { | ||
@@ -148,13 +129,11 @@ let plugin = plugins[i]; | ||
| let { imports, prepend, replacements } = plugin.transform({ | ||
| checker: currentProgram.getTypeChecker(), | ||
| checker, | ||
| code: currentCode, | ||
| program: currentProgram, | ||
| program, | ||
| shared, | ||
| sourceFile: currentFile | ||
| }); | ||
| let pluginChanged = false; | ||
| if (replacements?.length) { | ||
| currentCode = applyIntents(currentCode, currentFile, replacements); | ||
| currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true); | ||
| pluginChanged = true; | ||
| } | ||
@@ -164,3 +143,2 @@ if (prepend?.length) { | ||
| currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true); | ||
| pluginChanged = true; | ||
| } | ||
@@ -170,11 +148,6 @@ if (imports?.length) { | ||
| currentFile = ts.createSourceFile(fileName, currentCode, currentFile.languageVersion, true); | ||
| pluginChanged = true; | ||
| } | ||
| if (pluginChanged) { | ||
| transformed = true; | ||
| currentProgram = createUpdatedProgram(currentProgram, fileName, currentCode); | ||
| } | ||
| } | ||
| return { | ||
| changed: transformed, | ||
| changed: currentCode !== code, | ||
| code: currentCode, | ||
@@ -181,0 +154,0 @@ sourceFile: currentFile |
+1
-1
@@ -42,3 +42,3 @@ { | ||
| "types": "build/index.d.ts", | ||
| "version": "0.28.1", | ||
| "version": "0.28.2", | ||
| "scripts": { | ||
@@ -45,0 +45,0 @@ "build": "tsc && tsc-alias", |
@@ -13,5 +13,2 @@ import type { ImportIntent, Plugin, Replacement, ReplacementIntent, SharedContext } from './types'; | ||
| const DIRECTORY_SEPARATOR = /\\/g; | ||
| function applyImports(code: string, file: ts.SourceFile, intents: ImportIntent[]): string { | ||
@@ -80,47 +77,2 @@ for (let i = 0, n = intents.length; i < n; i++) { | ||
| function createUpdatedProgram( | ||
| originalProgram: ts.Program, | ||
| fileName: string, | ||
| newCode: string | ||
| ): ts.Program { | ||
| let options = originalProgram.getCompilerOptions(), | ||
| originalHost = ts.createCompilerHost(options), | ||
| originalGetSourceFile = originalHost.getSourceFile.bind(originalHost), | ||
| originalReadFile = originalHost.readFile.bind(originalHost); | ||
| originalHost.getSourceFile = ( | ||
| name: string, | ||
| languageVersion: ts.ScriptTarget, | ||
| onError?: (message: string) => void, | ||
| shouldCreateNewSourceFile?: boolean | ||
| ): ts.SourceFile | undefined => { | ||
| if ( | ||
| name === fileName || | ||
| name.replace(DIRECTORY_SEPARATOR, '/') === fileName.replace(DIRECTORY_SEPARATOR, '/') | ||
| ) { | ||
| return ts.createSourceFile(name, newCode, languageVersion, true); | ||
| } | ||
| return originalGetSourceFile(name, languageVersion, onError, shouldCreateNewSourceFile); | ||
| }; | ||
| originalHost.readFile = (name: string): string | undefined => { | ||
| if ( | ||
| name === fileName || | ||
| name.replace(DIRECTORY_SEPARATOR, '/') === fileName.replace(DIRECTORY_SEPARATOR, '/') | ||
| ) { | ||
| return newCode; | ||
| } | ||
| return originalReadFile(name); | ||
| }; | ||
| return ts.createProgram( | ||
| originalProgram.getRootFileNames(), | ||
| options, | ||
| originalHost, | ||
| originalProgram | ||
| ); | ||
| } | ||
| function hasPattern(code: string, patterns: string[]): boolean { | ||
@@ -164,3 +116,2 @@ for (let i = 0, n = patterns.length; i < n; i++) { | ||
| let remove = options.remove ? new Set(options.remove) : null, | ||
| // Collect all non-removed specifiers from existing imports | ||
| specifiers = new Set<string>(); | ||
@@ -182,3 +133,2 @@ | ||
| // Build replacement text - namespace import first, then named imports | ||
| let statements: string[] = []; | ||
@@ -194,3 +144,2 @@ | ||
| // Build replacements - replace first import, remove others | ||
| let replacements: Replacement[] = []; | ||
@@ -230,3 +179,4 @@ | ||
| * Transform source through all plugins sequentially. | ||
| * Each plugin receives fresh AST and TypeChecker with accurate positions. | ||
| * Each plugin receives fresh AST with accurate positions. | ||
| * All plugins share the original program type checker for import resolution. | ||
| */ | ||
@@ -244,7 +194,6 @@ const transform = ( | ||
| let currentCode = code, | ||
| let checker = program.getTypeChecker(), | ||
| currentCode = code, | ||
| currentFile = file, | ||
| currentProgram = program, | ||
| fileName = file.fileName, | ||
| transformed = false; | ||
| fileName = file.fileName; | ||
@@ -259,5 +208,5 @@ for (let i = 0, n = plugins.length; i < n; i++) { | ||
| let { imports, prepend, replacements } = plugin.transform({ | ||
| checker: currentProgram.getTypeChecker(), | ||
| checker, | ||
| code: currentCode, | ||
| program: currentProgram, | ||
| program, | ||
| shared, | ||
@@ -267,4 +216,2 @@ sourceFile: currentFile | ||
| let pluginChanged = false; | ||
| if (replacements?.length) { | ||
@@ -278,3 +225,2 @@ currentCode = applyIntents(currentCode, currentFile, replacements); | ||
| ); | ||
| pluginChanged = true; | ||
| } | ||
@@ -290,3 +236,2 @@ | ||
| ); | ||
| pluginChanged = true; | ||
| } | ||
@@ -302,14 +247,7 @@ | ||
| ); | ||
| pluginChanged = true; | ||
| } | ||
| // Rebuild program with updated source so next plugin gets valid checker | ||
| if (pluginChanged) { | ||
| transformed = true; | ||
| currentProgram = createUpdatedProgram(currentProgram, fileName, currentCode); | ||
| } | ||
| } | ||
| return { | ||
| changed: transformed, | ||
| changed: currentCode !== code, | ||
| code: currentCode, | ||
@@ -322,2 +260,2 @@ sourceFile: currentFile | ||
| export default { transform }; | ||
| export type { CoordinatorResult }; | ||
| export type { CoordinatorResult }; |
58608
-5.66%1500
-5.06%