diff --git a/src/index.ts b/src/index.ts index 95ef658..bc41aaa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,6 +38,19 @@ function init() { return namespaceImportPlugin.getCompletionEntryDetails(name, fileName, data.modulePath, info.project); }; + + const getCodeFixesAtPosition = info.languageService.getCodeFixesAtPosition; + info.languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => { + log('getCodeFixesAtPosition', { fileName, start, end, errorCodes, formatOptions, preferences }); + const original = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences); + + const importAction = namespaceImportPlugin.getCodeFixActionByName(fileName, start, end, info); + if (importAction) { + return [importAction, ...original]; + } + + return original; + }; } return { create }; diff --git a/src/lib/import.ts b/src/lib/import.ts index 42ca522..6243378 100644 --- a/src/lib/import.ts +++ b/src/lib/import.ts @@ -6,12 +6,7 @@ type PluginOptions = { }; export function getCompletionEntries(info: ts.server.PluginCreateInfo): ts.CompletionEntry[] { - const options = info.config.options as PluginOptions; - - const currentDir = info.project.getCurrentDirectory(); - const filePaths = options.paths.flatMap((dirPath) => { - return info.project.readDirectory(path.resolve(currentDir, dirPath), ['.ts', '.js']); - }); + const filePaths = getPathsToImport(info.config.options, info.project); return filePaths.map((filePath) => { const name = getFileNameWithoutExt(filePath); @@ -36,27 +31,7 @@ export function getCompletionEntryDetails( modulePath: string, project: ts.server.Project, ): ts.CompletionEntryDetails { - const importPath = transformModulePath(selfPath, modulePath, project); - const text = `import * as ${name} from "${getFilePathWithoutExt(importPath)}";\n`; - const action: CodeFixAction = { - fixName: 'namespace-import', - description: text, - changes: [ - { - fileName: selfPath, - textChanges: [ - { - span: { - start: 0, - length: 0, - }, - newText: text, - }, - ], - }, - ], - commands: [], - }; + const action: CodeFixAction = getCodeFixActionFromPath(name, selfPath, modulePath, project); return { name: name, kind: ScriptElementKind.alias, @@ -66,6 +41,34 @@ export function getCompletionEntryDetails( }; } +export function getCodeFixActionByName( + selfPath: string, + start: number, + end: number, + info: ts.server.PluginCreateInfo, +): CodeFixAction | null { + const name = info.languageService.getProgram()?.getSourceFile(selfPath)?.text.slice(start, end); + if (!name) { + return null; + } + + const filePaths = getPathsToImport(info.config.options, info.project); + const modulePath = filePaths.find((filePath) => getFileNameWithoutExt(filePath) === name); + if (modulePath) { + return getCodeFixActionFromPath(name, selfPath, modulePath, info.project); + } else { + return null; + } +} + +function getPathsToImport(options: PluginOptions, project: ts.server.Project): string[] { + const currentDir = project.getCurrentDirectory(); + + return options.paths.flatMap((dirPath) => { + return project.readDirectory(path.resolve(currentDir, dirPath), ['.ts', '.js']); + }); +} + function getFileNameWithoutExt(filePath: string): string { const ext = path.extname(filePath); return path.basename(filePath, ext); @@ -84,3 +87,32 @@ function transformModulePath(selfPath: string, filePath: string, project: ts.ser return './' + path.relative(path.dirname(selfPath), filePath); } } + +export function getCodeFixActionFromPath( + name: string, + selfPath: string, + modulePath: string, + project: ts.server.Project, +): CodeFixAction { + const importPath = transformModulePath(selfPath, modulePath, project); + const text = `import * as ${name} from "${getFilePathWithoutExt(importPath)}";\n`; + return { + fixName: 'namespace-import', + description: text, + changes: [ + { + fileName: selfPath, + textChanges: [ + { + span: { + start: 0, + length: 0, + }, + newText: text, + }, + ], + }, + ], + commands: [], + }; +}
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: