diff --git a/lib/util/edit.ts b/lib/util/edit.ts index ad26a30..a2fd7e5 100644 --- a/lib/util/edit.ts +++ b/lib/util/edit.ts @@ -12,7 +12,12 @@ import { MemoryFileService } from './MemoryFileService.js'; import { findFileUsage } from './findFileUsage.js'; import { parseFile } from './parseFile.js'; import { Output } from './Output.js'; -import * as Export from './export.js'; +import { + WholeExportDeclarationWithFile, + isWholeExportDeclarationWithFile, + isNamedExport, + isWholeExportDeclaration, +} from './export.js'; const transform = ( source: string, @@ -93,7 +98,7 @@ const createLanguageService = ({ projectRoot: string; fileService: FileService; }) => { - return ts.createLanguageService({ + const languageService = ts.createLanguageService({ getCompilationSettings() { return options; }, @@ -119,6 +124,8 @@ const createLanguageService = ({ return fileService.get(name); }, }); + + return languageService; }; const updateExportDeclaration = (code: string, unused: string[]) => { @@ -183,21 +190,41 @@ const getSpecifierPosition = (exportDeclaration: string) => { /** * Retrieves the names of the exports from a whole export declaration. * For each whole export declaration, it will recursively get the names of the exports from the file it points to. - * - * No need to memoize this function because `parseFile` already memoizes the file parsing. */ const deeplyGetExportNames = ({ item, files, fileNames, options, - filesAlreadyVisited = new Set(), }: { - item: Export.WholeExportDeclaration.FileFound; + item: WholeExportDeclarationWithFile; + files: Map; + fileNames: Set; + options: ts.CompilerOptions; +}): string[] => { + const filesAlreadyVisited = new Set(); + + return innerDeeplyGetExportNames({ + item, + files, + fileNames, + options, + filesAlreadyVisited, + }); +}; + +const innerDeeplyGetExportNames = ({ + item, + files, + fileNames, + options, + filesAlreadyVisited, +}: { + item: WholeExportDeclarationWithFile; files: Map; fileNames: Set; options: ts.CompilerOptions; - filesAlreadyVisited?: Set; + filesAlreadyVisited: Set; }): string[] => { if (filesAlreadyVisited.has(item.file)) { return []; @@ -212,12 +239,10 @@ const deeplyGetExportNames = ({ const deepExportNames = parsed.exports .filter( - (v) => - Export.isWholeExportDeclaration(v) && - Export.WholeExportDeclaration.isFileFound(v), + (v) => isWholeExportDeclaration(v) && isWholeExportDeclarationWithFile(v), ) .flatMap((v) => - deeplyGetExportNames({ + innerDeeplyGetExportNames({ item: v, files, fileNames, @@ -227,7 +252,7 @@ const deeplyGetExportNames = ({ ); return parsed.exports - .filter(Export.isNamedExport) + .filter(isNamedExport) .flatMap((v) => v.name) .concat(deepExportNames); }; @@ -475,7 +500,7 @@ const processFile = ({ break; } case 'whole': { - if (!Export.WholeExportDeclaration.isFileFound(item)) { + if (!isWholeExportDeclarationWithFile(item)) { // whole export is directed towards a file that is not in the project break; } @@ -583,11 +608,13 @@ export {};\n`, } if (changes.length === 0) { - return { + const result = { operation: 'edit' as const, content: files.get(targetFile) || '', removedExports: logs, }; + + return result; } let content = applyTextChanges(files.get(targetFile) || '', changes); diff --git a/lib/util/export.ts b/lib/util/export.ts index 1cb5b73..f1d3253 100644 --- a/lib/util/export.ts +++ b/lib/util/export.ts @@ -1,10 +1,181 @@ import ts from 'typescript'; -import { NamedExport } from './export/namedExport.js'; -import { WholeExportDeclaration } from './export/wholeExportDeclaration.js'; +export type ClassDeclaration = { + kind: ts.SyntaxKind.ClassDeclaration; + name: string; + change: { + code: string; + isUnnamedDefaultExport?: boolean; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; -export * as NamedExport from './export/namedExport.js'; -export * as WholeExportDeclaration from './export/wholeExportDeclaration.js'; +export type EnumDeclaration = { + kind: ts.SyntaxKind.EnumDeclaration; + name: string; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; + +export type ExportAssignment = { + kind: ts.SyntaxKind.ExportAssignment; + name: 'default'; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; + +export type FunctionDeclaration = { + kind: ts.SyntaxKind.FunctionDeclaration; + name: string; + change: { + code: string; + isUnnamedDefaultExport?: boolean; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; + +export type InterfaceDeclaration = { + kind: ts.SyntaxKind.InterfaceDeclaration; + name: string; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; + +export type NameExportDeclaration = { + kind: ts.SyntaxKind.ExportDeclaration; + type: 'named'; + name: string[]; + skip: boolean; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; + start: number; +}; + +export type NamespaceExportDeclaration = { + kind: ts.SyntaxKind.ExportDeclaration; + type: 'namespace'; + name: string; + start: number; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; +}; + +export type TypeAliasDeclaration = { + kind: ts.SyntaxKind.TypeAliasDeclaration; + name: string; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; + +export type VariableStatement = { + kind: ts.SyntaxKind.VariableStatement; + name: string[]; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; + skip: boolean; + start: number; +}; + +export type NamedExport = + | ClassDeclaration + | EnumDeclaration + | ExportAssignment + | FunctionDeclaration + | InterfaceDeclaration + | NameExportDeclaration + | NamespaceExportDeclaration + | TypeAliasDeclaration + | VariableStatement; + +type WholeExportDeclarationBase = { + kind: ts.SyntaxKind.ExportDeclaration; + type: 'whole'; + specifier: string; + start: number; + change: { + code: string; + span: { + start: number; + length: number; + }; + }; +}; + +/** + * Whole export when the file is found within the destFiles + */ +export type WholeExportDeclarationWithFile = WholeExportDeclarationBase & { + file: string; +}; + +/** + * Whole export when the file is not found within the destFiles, i.e. the file is not part of the project + */ +export type WholeExportDeclarationWithoutFile = WholeExportDeclarationBase & { + file: null; +}; + +export type WholeExportDeclaration = + | WholeExportDeclarationWithFile + | WholeExportDeclarationWithoutFile; + +export const isWholeExportDeclarationWithFile = ( + exportDeclaration: WholeExportDeclaration, +): exportDeclaration is WholeExportDeclarationWithFile => + exportDeclaration.file !== null; export type Export = NamedExport | WholeExportDeclaration; diff --git a/lib/util/export/namedExport.ts b/lib/util/export/namedExport.ts deleted file mode 100644 index 356447c..0000000 --- a/lib/util/export/namedExport.ts +++ /dev/null @@ -1,141 +0,0 @@ -import ts from 'typescript'; - -export type ClassDeclaration = { - kind: ts.SyntaxKind.ClassDeclaration; - name: string; - change: { - code: string; - isUnnamedDefaultExport?: boolean; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type EnumDeclaration = { - kind: ts.SyntaxKind.EnumDeclaration; - name: string; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type ExportAssignment = { - kind: ts.SyntaxKind.ExportAssignment; - name: 'default'; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type FunctionDeclaration = { - kind: ts.SyntaxKind.FunctionDeclaration; - name: string; - change: { - code: string; - isUnnamedDefaultExport?: boolean; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type InterfaceDeclaration = { - kind: ts.SyntaxKind.InterfaceDeclaration; - name: string; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type NameExportDeclaration = { - kind: ts.SyntaxKind.ExportDeclaration; - type: 'named'; - name: string[]; - skip: boolean; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; - start: number; -}; - -export type NamespaceExportDeclaration = { - kind: ts.SyntaxKind.ExportDeclaration; - type: 'namespace'; - name: string; - start: number; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; -}; - -export type TypeAliasDeclaration = { - kind: ts.SyntaxKind.TypeAliasDeclaration; - name: string; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type VariableStatement = { - kind: ts.SyntaxKind.VariableStatement; - name: string[]; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; - skip: boolean; - start: number; -}; - -export type NamedExport = - | ClassDeclaration - | EnumDeclaration - | ExportAssignment - | FunctionDeclaration - | InterfaceDeclaration - | NameExportDeclaration - | NamespaceExportDeclaration - | TypeAliasDeclaration - | VariableStatement; diff --git a/lib/util/export/wholeExportDeclaration.ts b/lib/util/export/wholeExportDeclaration.ts deleted file mode 100644 index 13794f2..0000000 --- a/lib/util/export/wholeExportDeclaration.ts +++ /dev/null @@ -1,43 +0,0 @@ -import ts from 'typescript'; - -/** - * Whole export when the file is found within the destFiles - */ -export type FileFound = { - kind: ts.SyntaxKind.ExportDeclaration; - type: 'whole'; - file: string; - specifier: string; - start: number; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; -}; - -/** - * Whole export when the file is not found within the destFiles, i.e. the file is not part of the project - */ -export type FileNotFound = { - kind: ts.SyntaxKind.ExportDeclaration; - type: 'whole'; - file: null; - specifier: string; - start: number; - change: { - code: string; - span: { - start: number; - length: number; - }; - }; -}; - -export type WholeExportDeclaration = FileFound | FileNotFound; - -export const isFileFound = ( - exportDeclaration: WholeExportDeclaration, -): exportDeclaration is FileFound => exportDeclaration.file !== null;