From 5ed26b39da14ceb0d75613548f905c08d081ad63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Mon, 12 Feb 2018 10:55:19 +0100 Subject: [PATCH 1/8] fix(code-outline): Show icons for parsed code outline --- .vscodeignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscodeignore b/.vscodeignore index 8615a93..2d93dde 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -9,7 +9,7 @@ prepare-release.js config/** test/** src/** -!src/extension/assets/** +!src/assets/** tsconfig.json tslint.json coverage/** From d772b7ab9be31284e2ae1f4867b1249886c61eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 14 Feb 2018 08:34:47 +0100 Subject: [PATCH 2/8] test: add tests for import and other features (#405) --- README.md | 7 +- package.json | 2 + src/configuration/imports-config.ts | 7 +- src/declarations/declaration-manager.ts | 5 +- src/declarations/workspace-declarations.ts | 7 +- src/import-organizer/import-grouping/index.ts | 8 - .../index.ts => imports/import-appender.ts} | 86 +- .../import-group-identifier-invalid-error.ts} | 0 .../import-grouping/import-group-keyword.ts} | 0 .../import-grouping/import-group-order.ts} | 0 .../import-group-setting-parser.ts} | 14 +- .../import-grouping/import-group.ts} | 2 +- src/imports/import-grouping/index.ts | 8 + .../import-grouping/keyword-import-group.ts} | 6 +- .../import-grouping/regex-import-group.ts} | 4 +- .../import-grouping/remain-import-group.ts} | 4 +- .../import-manager.ts | 0 src/imports/import-organizer.ts | 89 ++ .../import-quick-pick-item.ts | 0 src/imports/index.ts | 2 + src/ioc-symbols.ts | 2 +- src/ioc.ts | 5 +- src/typescript-hero.ts | 2 +- src/utilities/utility-functions.ts | 46 +- .../extension/managers/ImportManagerFile.ts | 5 - .../MultiRootIndices.test.ts | 6 - test/_old/multi-root-workspace-tests/index.ts | 44 - .../helpers/DeclarationIndexHelpers.test.ts | 298 ----- .../common/helpers/ImportHelpers.test.ts | 75 -- .../DocumentSymbolStructureExtension.test.ts | 99 -- .../extensions/ImportResolveExtension.test.ts | 481 -------- .../ImportGroupSettingParser.test.ts | 76 -- .../KeywordImportGroup.test.ts | 180 --- .../import-grouping/RegexImportGroup.test.ts | 102 -- .../import-grouping/RemainImportGroup.test.ts | 73 -- .../extension/managers/ImportManager.test.ts | 1002 ----------------- .../utilities/utilityFunctions.test.ts | 56 - test/_old/single-workspace-tests/index.ts | 44 - test/etc/workspace_1/declarations/barrel.ts | 2 + .../declarations/build/build-file.ts | 1 + .../declarations/declarations-for-barrel-1.ts | 8 + .../declarations/declarations-for-barrel-2.ts | 6 + .../declarations/declarations-for-index.ts | 8 + .../declarations/default-export.ts | 1 + .../declarations/default-multi-export.ts | 2 + .../declarations/default-unnamed-export.ts | 1 + test/etc/workspace_1/declarations/index.ts | 3 + .../declarations/multi-declarations.ts | 24 + .../workspace_1/declarations/not-indexed.js | 0 .../workspace_1/declarations/not-indexed.txt | 0 .../imports}/import-grouping/imports.ts | 0 .../imports/import-manager-file.ts | 5 + .../imports/import-manager-file.tsx} | 6 +- .../utilities/imports-for-specifier-sort.ts} | 0 .../workspace_2/declarations/declarations.ts | 1 + test/etc/workspace_2/main.ts | 11 - .../workspace_3/declarations/declarations.ts | 1 + test/etc/workspace_3/main.ts | 11 - .../node_modules/@types/my-module/index.d.ts | 3 + .../node_modules/node-module/index.d.ts | 1 + test/etc/workspace_3/package.json | 8 + .../workspace-declarations.multi.test.ts.snap | 77 ++ .../workspace-declarations.test.ts.snap | 792 +++++++++++++ .../declaration-manager.multi.test.ts | 71 ++ .../declaration-manager.single.test.ts | 153 +++ .../workspace-declarations.multi.test.ts | 67 ++ .../workspace-declarations.test.ts | 184 +++ .../__snapshots__/import-manager.test.ts.snap | 480 ++++++++ .../import-quick-pick-item.test.ts.snap | 35 + test/tests/imports/import-appender.test.ts | 0 .../import-group-setting-parser.test.ts.snap | 57 + .../keyword-import-group.test.ts.snap | 70 ++ .../regex-import-group.test.ts.snap | 28 + .../remain-import-group.test.ts.snap | 32 + .../import-group-setting-parser.test.ts | 65 ++ .../keyword-import-group.test.ts | 177 +++ .../regex-import-group.test.ts | 109 ++ .../remain-import-group.test.ts | 75 ++ test/tests/imports/import-manager.test.ts | 448 ++++++++ test/tests/imports/import-organizer.test.ts | 0 .../imports/import-quick-pick-item.test.ts | 26 + test/tests/setup.ts | 16 + .../utility-functions.test.ts.snap | 61 + .../tests/utilities/utility-functions.test.ts | 118 ++ 84 files changed, 3391 insertions(+), 2700 deletions(-) delete mode 100644 src/import-organizer/import-grouping/index.ts rename src/{import-organizer/index.ts => imports/import-appender.ts} (72%) rename src/{import-organizer/import-grouping/ImportGroupIdentifierInvalidError.ts => imports/import-grouping/import-group-identifier-invalid-error.ts} (100%) rename src/{import-organizer/import-grouping/ImportGroupKeyword.ts => imports/import-grouping/import-group-keyword.ts} (100%) rename src/{import-organizer/import-grouping/ImportGroupOrder.ts => imports/import-grouping/import-group-order.ts} (100%) rename src/{import-organizer/import-grouping/ImportGroupSettingParser.ts => imports/import-grouping/import-group-setting-parser.ts} (82%) rename src/{import-organizer/import-grouping/ImportGroup.ts => imports/import-grouping/import-group.ts} (95%) create mode 100644 src/imports/import-grouping/index.ts rename src/{import-organizer/import-grouping/KeywordImportGroup.ts => imports/import-grouping/keyword-import-group.ts} (93%) rename src/{import-organizer/import-grouping/RegexImportGroup.ts => imports/import-grouping/regex-import-group.ts} (93%) rename src/{import-organizer/import-grouping/RemainImportGroup.ts => imports/import-grouping/remain-import-group.ts} (89%) rename src/{import-organizer => imports}/import-manager.ts (100%) create mode 100644 src/imports/import-organizer.ts rename src/{import-organizer => imports}/import-quick-pick-item.ts (100%) create mode 100644 src/imports/index.ts delete mode 100644 test/_old/_workspace/extension/managers/ImportManagerFile.ts delete mode 100644 test/_old/multi-root-workspace-tests/MultiRootIndices.test.ts delete mode 100644 test/_old/multi-root-workspace-tests/index.ts delete mode 100644 test/_old/single-workspace-tests/common/helpers/DeclarationIndexHelpers.test.ts delete mode 100644 test/_old/single-workspace-tests/common/helpers/ImportHelpers.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/managers/ImportManager.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/utilities/utilityFunctions.test.ts delete mode 100644 test/_old/single-workspace-tests/index.ts create mode 100644 test/etc/workspace_1/declarations/barrel.ts create mode 100644 test/etc/workspace_1/declarations/build/build-file.ts create mode 100644 test/etc/workspace_1/declarations/declarations-for-barrel-1.ts create mode 100644 test/etc/workspace_1/declarations/declarations-for-barrel-2.ts create mode 100644 test/etc/workspace_1/declarations/declarations-for-index.ts create mode 100644 test/etc/workspace_1/declarations/default-export.ts create mode 100644 test/etc/workspace_1/declarations/default-multi-export.ts create mode 100644 test/etc/workspace_1/declarations/default-unnamed-export.ts create mode 100644 test/etc/workspace_1/declarations/index.ts create mode 100644 test/etc/workspace_1/declarations/multi-declarations.ts create mode 100644 test/etc/workspace_1/declarations/not-indexed.js create mode 100644 test/etc/workspace_1/declarations/not-indexed.txt rename test/{_old/_workspace/extension => etc/workspace_1/imports}/import-grouping/imports.ts (100%) create mode 100644 test/etc/workspace_1/imports/import-manager-file.ts rename test/{_old/_workspace/extension/managers/ImportManagerFile.tsx => etc/workspace_1/imports/import-manager-file.tsx} (64%) rename test/{_old/_workspace/extension/utilities/importsForSpecifierSort.ts => etc/workspace_1/utilities/imports-for-specifier-sort.ts} (100%) create mode 100644 test/etc/workspace_2/declarations/declarations.ts delete mode 100644 test/etc/workspace_2/main.ts create mode 100644 test/etc/workspace_3/declarations/declarations.ts delete mode 100644 test/etc/workspace_3/main.ts create mode 100644 test/etc/workspace_3/node_modules/@types/my-module/index.d.ts create mode 100644 test/etc/workspace_3/node_modules/node-module/index.d.ts create mode 100644 test/etc/workspace_3/package.json create mode 100644 test/tests/declarations/__snapshots__/workspace-declarations.multi.test.ts.snap create mode 100644 test/tests/declarations/__snapshots__/workspace-declarations.test.ts.snap create mode 100644 test/tests/declarations/declaration-manager.multi.test.ts create mode 100644 test/tests/declarations/declaration-manager.single.test.ts create mode 100644 test/tests/declarations/workspace-declarations.multi.test.ts create mode 100644 test/tests/declarations/workspace-declarations.test.ts create mode 100644 test/tests/imports/__snapshots__/import-manager.test.ts.snap create mode 100644 test/tests/imports/__snapshots__/import-quick-pick-item.test.ts.snap create mode 100644 test/tests/imports/import-appender.test.ts create mode 100644 test/tests/imports/import-grouping/__snapshots__/import-group-setting-parser.test.ts.snap create mode 100644 test/tests/imports/import-grouping/__snapshots__/keyword-import-group.test.ts.snap create mode 100644 test/tests/imports/import-grouping/__snapshots__/regex-import-group.test.ts.snap create mode 100644 test/tests/imports/import-grouping/__snapshots__/remain-import-group.test.ts.snap create mode 100644 test/tests/imports/import-grouping/import-group-setting-parser.test.ts create mode 100644 test/tests/imports/import-grouping/keyword-import-group.test.ts create mode 100644 test/tests/imports/import-grouping/regex-import-group.test.ts create mode 100644 test/tests/imports/import-grouping/remain-import-group.test.ts create mode 100644 test/tests/imports/import-manager.test.ts create mode 100644 test/tests/imports/import-organizer.test.ts create mode 100644 test/tests/imports/import-quick-pick-item.test.ts create mode 100644 test/tests/utilities/__snapshots__/utility-functions.test.ts.snap create mode 100644 test/tests/utilities/utility-functions.test.ts diff --git a/README.md b/README.md index a7a6ce4..ff53b30 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,16 @@ If you'd like to buy me a beer :-) ## Features at a glance -Here is a brief list, of what TypeScript Hero is capable of (more at the end): +Here is a brief list, of what TypeScript Hero is capable of (more in the wiki): - Sort and organize your imports (sort and remove unused) - Code outline view of your open TS / TSX document +- Add import to the document or add an import that is under the cursor to the document ## Known Issues Please visit [the issue list](https://github.com/buehler/typescript-hero/issues) :-) + +## Documentation + +Visit the wiki pages here: [Typescript Hero Wiki](https://github.com/buehler/typescript-hero/wiki) diff --git a/package.json b/package.json index c3da71e..36d9fc8 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,8 @@ "clean": "del-cli ./out ./coverage", "build": "npm run clean && tsc -p ./config/tsconfig.build.json", "develop": "npm run clean && tsc -p .", + "develop:test-single": "npm run clean && tsc -p ./config/tsconfig.test-single-workspace.json --watch", + "develop:test-multi": "npm run clean && tsc -p ./config/tsconfig.test-multi-workspace.json --watch", "lint": "tslint -c ./tslint.json -p ./config/tsconfig.build.json", "test:single-workspace": "npm run lint && npm run clean && tsc -p ./config/tsconfig.test-single-workspace.json && node ./node_modules/vscode/bin/test", "test:multi-workspace": "npm run lint && npm run clean && tsc -p ./config/tsconfig.test-multi-workspace.json && node ./node_modules/vscode/bin/test", diff --git a/src/configuration/imports-config.ts b/src/configuration/imports-config.ts index dc371d3..ab52ea8 100644 --- a/src/configuration/imports-config.ts +++ b/src/configuration/imports-config.ts @@ -1,11 +1,6 @@ import { Uri, workspace } from 'vscode'; -import { - ImportGroup, - ImportGroupSetting, - ImportGroupSettingParser, - RemainImportGroup, -} from '../import-organizer/import-grouping'; +import { ImportGroup, ImportGroupSetting, ImportGroupSettingParser, RemainImportGroup } from '../imports/import-grouping'; const sectionKey = 'typescriptHero.imports'; diff --git a/src/declarations/declaration-manager.ts b/src/declarations/declaration-manager.ts index c8133ba..c84f3e2 100644 --- a/src/declarations/declaration-manager.ts +++ b/src/declarations/declaration-manager.ts @@ -126,14 +126,15 @@ export default class DeclarationManager implements Disposable { this.activeWorkspaces--; } if (this.activeWorkspaces <= 0) { + this.activeWorkspaces = 0; this.logger.debug('[DeclarationManager] All workspaces are done syncing.'); this.statusBarItem.text = ResolverState.ok; } } - private createWorkspace(folder: WorkspaceFolder): void { + private createWorkspace(folder: WorkspaceFolder): Promise { this.workspaces[folder.uri.fsPath] = new WorkspaceDeclarations(folder); this.workspaces[folder.uri.fsPath].workspaceStateChanged(state => this.workspaceStateChanged(state)); - this.workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + return this.workspaces[folder.uri.fsPath].initialize(); } } diff --git a/src/declarations/workspace-declarations.ts b/src/declarations/workspace-declarations.ts index 2f8c736..b187200 100644 --- a/src/declarations/workspace-declarations.ts +++ b/src/declarations/workspace-declarations.ts @@ -49,7 +49,6 @@ export default class WorkspaceDeclarations implements Disposable { { workspace: this.folder.uri.fsPath }, ); this.disposables.push(this._workspaceStateChanged); - this.initialize(); } public dispose(): void { @@ -60,10 +59,12 @@ export default class WorkspaceDeclarations implements Disposable { for (const disposable of this.disposables) { disposable.dispose(); } - this._index.reset(); + if (this._index) { + this._index.reset(); + } } - private async initialize(): Promise { + public async initialize(): Promise { const profiler = this.logger.startTimer(); this._workspaceStateChanged.fire(WorkspaceDeclarationsState.Syncing); diff --git a/src/import-organizer/import-grouping/index.ts b/src/import-organizer/import-grouping/index.ts deleted file mode 100644 index bc2f2ba..0000000 --- a/src/import-organizer/import-grouping/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './ImportGroup'; -export * from './ImportGroupKeyword'; -export * from './ImportGroupOrder'; -export * from './KeywordImportGroup'; -export * from './RegexImportGroup'; -export * from './RemainImportGroup'; -export * from './ImportGroupSettingParser'; -export * from './ImportGroupIdentifierInvalidError'; diff --git a/src/import-organizer/index.ts b/src/imports/import-appender.ts similarity index 72% rename from src/import-organizer/index.ts rename to src/imports/import-appender.ts index d34116a..cbb60fe 100644 --- a/src/import-organizer/index.ts +++ b/src/imports/import-appender.ts @@ -3,7 +3,6 @@ import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; import { commands, ExtensionContext, window, workspace } from 'vscode'; import Activatable from '../activatable'; -import Configuration from '../configuration'; import DeclarationManager from '../declarations/declaration-manager'; import iocSymbols, { ImportManagerProvider } from '../ioc-symbols'; import { Logger } from '../utilities/logger'; @@ -13,21 +12,17 @@ import ImportQuickPickItem from './import-quick-pick-item'; type DeclarationsForImportOptions = { cursorSymbol: string, documentSource: string, documentPath: string }; @injectable() -export default class ImportOrganizer implements Activatable { +export class ImportAppender implements Activatable { constructor( @inject(iocSymbols.extensionContext) private context: ExtensionContext, @inject(iocSymbols.logger) private logger: Logger, - @inject(iocSymbols.configuration) private config: Configuration, @inject(iocSymbols.importManager) private importManagerProvider: ImportManagerProvider, @inject(iocSymbols.declarationManager) private declarationManager: DeclarationManager, @inject(iocSymbols.parser) private parser: TypescriptParser, ) { } public setup(): void { - this.logger.debug('[ImportOrganizer] Setting up ImportOrganizer.'); - this.context.subscriptions.push( - commands.registerTextEditorCommand('typescriptHero.imports.organize', () => this.organizeImports()), - ); + this.logger.debug('[ImportAppender] Setting up ImportAppender.'); this.context.subscriptions.push( commands.registerTextEditorCommand('typescriptHero.index.addImport', () => this.addImport()), ); @@ -37,71 +32,18 @@ export default class ImportOrganizer implements Activatable { () => this.addImportUnderCursor(), ), ); - this.context.subscriptions.push( - workspace.onWillSaveTextDocument((event) => { - if (!this.config.imports.organizeOnSave(event.document.uri)) { - this.logger.debug( - '[ImportOrganizer] OrganizeOnSave is deactivated through config', - ); - return; - } - if (this.config.parseableLanguages().indexOf(event.document.languageId) < 0) { - this.logger.debug( - '[ImportOrganizer] OrganizeOnSave not possible for given language', - { language: event.document.languageId }, - ); - return; - } - - this.logger.info( - '[ImportOrganizer] OrganizeOnSave for file', - { file: event.document.fileName }, - ); - event.waitUntil( - this.importManagerProvider(event.document).then(manager => manager.organizeImports().calculateTextEdits()), - ); - }), - ); } public start(): void { - this.logger.info('[ImportOrganizer] Starting up ImportOrganizer.'); + this.logger.info('[ImportAppender] Starting up ImportAppender.'); } public stop(): void { - this.logger.info('[ImportOrganizer] Stopping ImportOrganizer.'); + this.logger.info('[ImportAppender] Stopping ImportAppender.'); } public dispose(): void { - this.logger.debug('[ImportOrganizer] Disposing ImportOrganizer.'); - } - - /** - * Organizes the imports of the actual document. Sorts and formats them correctly. - * - * @private - * @returns {Promise} - * - * @memberof ImportResolveExtension - */ - private async organizeImports(): Promise { - if (!window.activeTextEditor) { - return; - } - try { - this.logger.debug( - '[ImportOrganizer] Organize the imports in the document', - { file: window.activeTextEditor.document.fileName }, - ); - const ctrl = await this.importManagerProvider(window.activeTextEditor.document); - await ctrl.organizeImports().commit(); - } catch (e) { - this.logger.error( - '[ImportOrganizer] Imports could not be organized, error: %s', - e, - { file: window.activeTextEditor.document.fileName }, - ); - } + this.logger.debug('[ImportAppender] Disposing ImportAppender.'); } /** @@ -129,14 +71,14 @@ export default class ImportOrganizer implements Activatable { ); if (selectedItem) { this.logger.info( - '[ImportOrganizer] Add import to document', + '[ImportAppender] Add import to document', { specifier: selectedItem.declarationInfo.declaration.name, library: selectedItem.declarationInfo.from }, ); this.addImportToDocument(selectedItem.declarationInfo); } } catch (e) { this.logger.error( - '[ImportOrganizer] Import could not be added to document', + '[ImportAppender] Import could not be added to document', { file: window.activeTextEditor.document.fileName, error: e.toString() }, ); window.showErrorMessage('The import cannot be completed, there was an error during the process.'); @@ -163,7 +105,7 @@ export default class ImportOrganizer implements Activatable { } try { const selectedSymbol = this.getSymbolUnderCursor(); - this.logger.debug('[ImportOrganizer] Add import for symbol under cursor', { selectedSymbol }); + this.logger.debug('[ImportAppender] Add import for symbol under cursor', { selectedSymbol }); if (!!!selectedSymbol) { return; } @@ -175,7 +117,7 @@ export default class ImportOrganizer implements Activatable { if (resolveItems.length < 1) { this.logger.info( - '[ImportOrganizer] The symbol was not found or is already imported', + '[ImportAppender] The symbol was not found or is already imported', { selectedSymbol }, ); window.showInformationMessage( @@ -183,7 +125,7 @@ export default class ImportOrganizer implements Activatable { ); } else if (resolveItems.length === 1 && resolveItems[0].declaration.name === selectedSymbol) { this.logger.info( - '[ImportOrganizer] Add import to document', + '[ImportAppender] Add import to document', { specifier: resolveItems[0].declaration.name, library: resolveItems[0].from, @@ -196,7 +138,7 @@ export default class ImportOrganizer implements Activatable { ); if (selectedItem) { this.logger.info( - '[ImportOrganizer] Add import to document', + '[ImportAppender] Add import to document', { specifier: selectedItem.declarationInfo.declaration.name, library: selectedItem.declarationInfo.from, @@ -207,7 +149,7 @@ export default class ImportOrganizer implements Activatable { } } catch (e) { this.logger.error( - '[ImportOrganizer] Import could not be added to document.', + '[ImportAppender] Import could not be added to document.', { file: window.activeTextEditor.document.fileName, error: e.toString() }, ); window.showErrorMessage('The import cannot be completed, there was an error during the process.'); @@ -239,7 +181,7 @@ export default class ImportOrganizer implements Activatable { } this.logger.debug( - '[ImportOrganizer] Calculate possible imports for document', + '[ImportAppender] Calculate possible imports for document', { cursorSymbol, file: documentPath }, ); @@ -303,7 +245,7 @@ export default class ImportOrganizer implements Activatable { */ private showCacheWarning(): void { this.logger.warn( - '[ImportOrganizer] Index was not ready or not index for this file found', + '[ImportAppender] Index was not ready or not index for this file found', ); window.showWarningMessage('Please wait a few seconds longer until the symbol cache has been build.'); } diff --git a/src/import-organizer/import-grouping/ImportGroupIdentifierInvalidError.ts b/src/imports/import-grouping/import-group-identifier-invalid-error.ts similarity index 100% rename from src/import-organizer/import-grouping/ImportGroupIdentifierInvalidError.ts rename to src/imports/import-grouping/import-group-identifier-invalid-error.ts diff --git a/src/import-organizer/import-grouping/ImportGroupKeyword.ts b/src/imports/import-grouping/import-group-keyword.ts similarity index 100% rename from src/import-organizer/import-grouping/ImportGroupKeyword.ts rename to src/imports/import-grouping/import-group-keyword.ts diff --git a/src/import-organizer/import-grouping/ImportGroupOrder.ts b/src/imports/import-grouping/import-group-order.ts similarity index 100% rename from src/import-organizer/import-grouping/ImportGroupOrder.ts rename to src/imports/import-grouping/import-group-order.ts diff --git a/src/import-organizer/import-grouping/ImportGroupSettingParser.ts b/src/imports/import-grouping/import-group-setting-parser.ts similarity index 82% rename from src/import-organizer/import-grouping/ImportGroupSettingParser.ts rename to src/imports/import-grouping/import-group-setting-parser.ts index 5ed4b5d..d8bcf22 100644 --- a/src/import-organizer/import-grouping/ImportGroupSettingParser.ts +++ b/src/imports/import-grouping/import-group-setting-parser.ts @@ -1,10 +1,10 @@ -import { ImportGroup } from './ImportGroup'; -import { ImportGroupIdentifierInvalidError } from './ImportGroupIdentifierInvalidError'; -import { ImportGroupKeyword } from './ImportGroupKeyword'; -import { ImportGroupOrder } from './ImportGroupOrder'; -import { KeywordImportGroup } from './KeywordImportGroup'; -import { RegexImportGroup } from './RegexImportGroup'; -import { RemainImportGroup } from './RemainImportGroup'; +import { ImportGroup } from './import-group'; +import { ImportGroupIdentifierInvalidError } from './import-group-identifier-invalid-error'; +import { ImportGroupKeyword } from './import-group-keyword'; +import { ImportGroupOrder } from './import-group-order'; +import { KeywordImportGroup } from './keyword-import-group'; +import { RegexImportGroup } from './regex-import-group'; +import { RemainImportGroup } from './remain-import-group'; /** * Inserted setting that is contained in the settings.json of .vscode. diff --git a/src/import-organizer/import-grouping/ImportGroup.ts b/src/imports/import-grouping/import-group.ts similarity index 95% rename from src/import-organizer/import-grouping/ImportGroup.ts rename to src/imports/import-grouping/import-group.ts index afd9b6b..84059d7 100644 --- a/src/import-organizer/import-grouping/ImportGroup.ts +++ b/src/imports/import-grouping/import-group.ts @@ -1,6 +1,6 @@ import { Import } from 'typescript-parser'; -import { ImportGroupOrder } from './ImportGroupOrder'; +import { ImportGroupOrder } from './import-group-order'; /** * Interface for an import group. A group contains a list of imports that are grouped and sorted diff --git a/src/imports/import-grouping/index.ts b/src/imports/import-grouping/index.ts new file mode 100644 index 0000000..46709e3 --- /dev/null +++ b/src/imports/import-grouping/index.ts @@ -0,0 +1,8 @@ +export * from './import-group'; +export * from './import-group-identifier-invalid-error'; +export * from './import-group-keyword'; +export * from './import-group-order'; +export * from './import-group-setting-parser'; +export * from './keyword-import-group'; +export * from './regex-import-group'; +export * from './remain-import-group'; diff --git a/src/import-organizer/import-grouping/KeywordImportGroup.ts b/src/imports/import-grouping/keyword-import-group.ts similarity index 93% rename from src/import-organizer/import-grouping/KeywordImportGroup.ts rename to src/imports/import-grouping/keyword-import-group.ts index a575c36..e446990 100644 --- a/src/import-organizer/import-grouping/KeywordImportGroup.ts +++ b/src/imports/import-grouping/keyword-import-group.ts @@ -1,9 +1,9 @@ import { Import, StringImport } from 'typescript-parser'; import { importSort } from '../../utilities/utility-functions'; -import { ImportGroup } from './ImportGroup'; -import { ImportGroupKeyword } from './ImportGroupKeyword'; -import { ImportGroupOrder } from './ImportGroupOrder'; +import { ImportGroup } from './import-group'; +import { ImportGroupKeyword } from './import-group-keyword'; +import { ImportGroupOrder } from './import-group-order'; /** * Importgroup for keywords. Uses "Modules", "Plains", "Workspace" as a keyword and processes the corresponding imports. diff --git a/src/import-organizer/import-grouping/RegexImportGroup.ts b/src/imports/import-grouping/regex-import-group.ts similarity index 93% rename from src/import-organizer/import-grouping/RegexImportGroup.ts rename to src/imports/import-grouping/regex-import-group.ts index e4314e3..ee63ac6 100644 --- a/src/import-organizer/import-grouping/RegexImportGroup.ts +++ b/src/imports/import-grouping/regex-import-group.ts @@ -1,8 +1,8 @@ import { Import, StringImport } from 'typescript-parser'; import { importSort } from '../../utilities/utility-functions'; -import { ImportGroup } from './ImportGroup'; -import { ImportGroupOrder } from './ImportGroupOrder'; +import { ImportGroup } from './import-group'; +import { ImportGroupOrder } from './import-group-order'; /** * Importgroup that processes all imports that match a certain regex (the lib name). diff --git a/src/import-organizer/import-grouping/RemainImportGroup.ts b/src/imports/import-grouping/remain-import-group.ts similarity index 89% rename from src/import-organizer/import-grouping/RemainImportGroup.ts rename to src/imports/import-grouping/remain-import-group.ts index 3c3fc85..55bb10d 100644 --- a/src/import-organizer/import-grouping/RemainImportGroup.ts +++ b/src/imports/import-grouping/remain-import-group.ts @@ -1,8 +1,8 @@ import { Import, StringImport } from 'typescript-parser'; import { importSort } from '../../utilities/utility-functions'; -import { ImportGroup } from './ImportGroup'; -import { ImportGroupOrder } from './ImportGroupOrder'; +import { ImportGroup } from './import-group'; +import { ImportGroupOrder } from './import-group-order'; /** * Importgroup that processes all imports. Should be used if other groups don't process the import. diff --git a/src/import-organizer/import-manager.ts b/src/imports/import-manager.ts similarity index 100% rename from src/import-organizer/import-manager.ts rename to src/imports/import-manager.ts diff --git a/src/imports/import-organizer.ts b/src/imports/import-organizer.ts new file mode 100644 index 0000000..8067d22 --- /dev/null +++ b/src/imports/import-organizer.ts @@ -0,0 +1,89 @@ +import { inject, injectable } from 'inversify'; +import { commands, ExtensionContext, window, workspace } from 'vscode'; + +import Activatable from '../activatable'; +import Configuration from '../configuration'; +import iocSymbols, { ImportManagerProvider } from '../ioc-symbols'; +import { Logger } from '../utilities/logger'; + +@injectable() +export class ImportOrganizer implements Activatable { + constructor( + @inject(iocSymbols.extensionContext) private context: ExtensionContext, + @inject(iocSymbols.logger) private logger: Logger, + @inject(iocSymbols.configuration) private config: Configuration, + @inject(iocSymbols.importManager) private importManagerProvider: ImportManagerProvider, + ) { } + + public setup(): void { + this.logger.debug('[ImportOrganizer] Setting up ImportOrganizer.'); + this.context.subscriptions.push( + commands.registerTextEditorCommand('typescriptHero.imports.organize', () => this.organizeImports()), + ); + this.context.subscriptions.push( + workspace.onWillSaveTextDocument((event) => { + if (!this.config.imports.organizeOnSave(event.document.uri)) { + this.logger.debug( + '[ImportOrganizer] OrganizeOnSave is deactivated through config', + ); + return; + } + if (this.config.parseableLanguages().indexOf(event.document.languageId) < 0) { + this.logger.debug( + '[ImportOrganizer] OrganizeOnSave not possible for given language', + { language: event.document.languageId }, + ); + return; + } + + this.logger.info( + '[ImportOrganizer] OrganizeOnSave for file', + { file: event.document.fileName }, + ); + event.waitUntil( + this.importManagerProvider(event.document).then(manager => manager.organizeImports().calculateTextEdits()), + ); + }), + ); + } + + public start(): void { + this.logger.info('[ImportOrganizer] Starting up ImportOrganizer.'); + } + + public stop(): void { + this.logger.info('[ImportOrganizer] Stopping ImportOrganizer.'); + } + + public dispose(): void { + this.logger.debug('[ImportOrganizer] Disposing ImportOrganizer.'); + } + + /** + * Organizes the imports of the actual document. Sorts and formats them correctly. + * + * @private + * @returns {Promise} + * + * @memberof ImportResolveExtension + */ + private async organizeImports(): Promise { + if (!window.activeTextEditor) { + return; + } + try { + this.logger.debug( + '[ImportOrganizer] Organize the imports in the document', + { file: window.activeTextEditor.document.fileName }, + ); + const ctrl = await this.importManagerProvider(window.activeTextEditor.document); + await ctrl.organizeImports().commit(); + } catch (e) { + this.logger.error( + '[ImportOrganizer] Imports could not be organized, error: %s', + e, + { file: window.activeTextEditor.document.fileName }, + ); + } + } +} diff --git a/src/import-organizer/import-quick-pick-item.ts b/src/imports/import-quick-pick-item.ts similarity index 100% rename from src/import-organizer/import-quick-pick-item.ts rename to src/imports/import-quick-pick-item.ts diff --git a/src/imports/index.ts b/src/imports/index.ts new file mode 100644 index 0000000..ccb56c0 --- /dev/null +++ b/src/imports/index.ts @@ -0,0 +1,2 @@ +export { ImportAppender } from './import-appender'; +export { ImportOrganizer } from './import-organizer'; diff --git a/src/ioc-symbols.ts b/src/ioc-symbols.ts index f21b3ec..9a3b95d 100644 --- a/src/ioc-symbols.ts +++ b/src/ioc-symbols.ts @@ -1,7 +1,7 @@ import { TypescriptCodeGenerator } from 'typescript-parser'; import { TextDocument, Uri } from 'vscode'; -import ImportManager from './import-organizer/import-manager'; +import ImportManager from './imports/import-manager'; export default { activatables: Symbol('activatables'), diff --git a/src/ioc.ts b/src/ioc.ts index 2bb6d76..336d66f 100644 --- a/src/ioc.ts +++ b/src/ioc.ts @@ -8,8 +8,8 @@ import Activatable from './activatable'; import CodeOutline from './code-outline'; import Configuration from './configuration'; import DeclarationManager from './declarations/declaration-manager'; -import ImportOrganizer from './import-organizer'; -import ImportManager from './import-organizer/import-manager'; +import { ImportAppender, ImportOrganizer } from './imports'; +import ImportManager from './imports/import-manager'; import iocSymbols, { ImportManagerProvider, TypescriptCodeGeneratorFactory } from './ioc-symbols'; import TypescriptHero from './typescript-hero'; import winstonLogger, { Logger } from './utilities/logger'; @@ -23,6 +23,7 @@ ioc.bind(TypescriptHero).to(TypescriptHero).inSingletonScope(); // Activatables ioc.bind(iocSymbols.activatables).to(CodeOutline).inSingletonScope(); ioc.bind(iocSymbols.activatables).to(ImportOrganizer).inSingletonScope(); +ioc.bind(iocSymbols.activatables).to(ImportAppender).inSingletonScope(); // Configuration ioc.bind(iocSymbols.configuration).to(Configuration).inSingletonScope(); diff --git a/src/typescript-hero.ts b/src/typescript-hero.ts index 17c7f92..b9fc192 100644 --- a/src/typescript-hero.ts +++ b/src/typescript-hero.ts @@ -2,7 +2,7 @@ import { inject, injectable, multiInject } from 'inversify'; import { Generatable, GENERATORS, TypescriptCodeGenerator, TypescriptGenerationOptions } from 'typescript-parser'; import Activatable from './activatable'; -import { KeywordImportGroup, RegexImportGroup, RemainImportGroup } from './import-organizer/import-grouping'; +import { KeywordImportGroup, RegexImportGroup, RemainImportGroup } from './imports/import-grouping'; import iocSymbols from './ioc-symbols'; import { Logger } from './utilities/logger'; diff --git a/src/utilities/utility-functions.ts b/src/utilities/utility-functions.ts index 502df54..5e7fb5a 100644 --- a/src/utilities/utility-functions.ts +++ b/src/utilities/utility-functions.ts @@ -1,33 +1,33 @@ import { basename, join, normalize, parse, relative } from 'path'; import { ScriptKind } from 'typescript'; import { - ClassDeclaration, - ConstructorDeclaration, - Declaration, - DeclarationInfo, - DefaultDeclaration, - EnumDeclaration, - ExternalModuleImport, - FunctionDeclaration, - GetterDeclaration, - Import, - InterfaceDeclaration, - MethodDeclaration, - ModuleDeclaration, - NamedImport, - NamespaceImport, - ParameterDeclaration, - PropertyDeclaration, - SetterDeclaration, - StringImport, - SymbolSpecifier, - TypeAliasDeclaration, - VariableDeclaration, + ClassDeclaration, + ConstructorDeclaration, + Declaration, + DeclarationInfo, + DefaultDeclaration, + EnumDeclaration, + ExternalModuleImport, + FunctionDeclaration, + GetterDeclaration, + Import, + InterfaceDeclaration, + MethodDeclaration, + ModuleDeclaration, + NamedImport, + NamespaceImport, + ParameterDeclaration, + PropertyDeclaration, + SetterDeclaration, + StringImport, + SymbolSpecifier, + TypeAliasDeclaration, + VariableDeclaration, } from 'typescript-parser'; import { toPosix } from 'typescript-parser/utilities/PathHelpers'; import { CompletionItemKind, Position, TextEditor } from 'vscode'; -import { ImportGroup, RegexImportGroup } from '../import-organizer/import-grouping'; +import { ImportGroup, RegexImportGroup } from '../imports/import-grouping'; /** * String-Sort function. diff --git a/test/_old/_workspace/extension/managers/ImportManagerFile.ts b/test/_old/_workspace/extension/managers/ImportManagerFile.ts deleted file mode 100644 index f0fb2e6..0000000 --- a/test/_old/_workspace/extension/managers/ImportManagerFile.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Class1 } from '../../server/indices'; - -export class MyCoding { - constructor(private class1: Class1) { } -} diff --git a/test/_old/multi-root-workspace-tests/MultiRootIndices.test.ts b/test/_old/multi-root-workspace-tests/MultiRootIndices.test.ts deleted file mode 100644 index 5d02a97..0000000 --- a/test/_old/multi-root-workspace-tests/MultiRootIndices.test.ts +++ /dev/null @@ -1,6 +0,0 @@ - -describe('Multi root indices', () => { - - it('should be tested; will be done as soon as the feature is default enabled.'); - -}); diff --git a/test/_old/multi-root-workspace-tests/index.ts b/test/_old/multi-root-workspace-tests/index.ts deleted file mode 100644 index 9956ef9..0000000 --- a/test/_old/multi-root-workspace-tests/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -import 'reflect-metadata'; - -import { ExtensionContext, Memento } from 'vscode'; - -import { Container } from '../../src/extension/IoC'; -import { iocSymbols } from '../../src/extension/IoCSymbols'; - -// tslint:disable - -// -// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING -// -// This file is providing the test runner to use when running extension tests. -// By default the test runner in use is Mocha based. -// -// You can provide your own test runner if you want to override it by exporting -// a function run(testRoot: string, clb: (error:Error) => void) that the extension -// host can call to run the tests. The test runner is expected to use console.log -// to report the results back to the caller. When the tests are finished, return -// a possible error to the callback or null if none. - -class ContextMock implements ExtensionContext { - subscriptions: { dispose(): any }[] = []; - workspaceState: Memento; - globalState: Memento; - extensionPath: string = ''; - storagePath: string = ''; - asAbsolutePath(): string { - return ''; - } -} - -Container.bind(iocSymbols.extensionContext).toConstantValue(new ContextMock()); - -const testRunner = require('vscode/lib/testrunner'); - -// You can directly control Mocha options by uncommenting the following lines -// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info -testRunner.configure({ - ui: 'bdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results -}); - -module.exports = testRunner; diff --git a/test/_old/single-workspace-tests/common/helpers/DeclarationIndexHelpers.test.ts b/test/_old/single-workspace-tests/common/helpers/DeclarationIndexHelpers.test.ts deleted file mode 100644 index 467b746..0000000 --- a/test/_old/single-workspace-tests/common/helpers/DeclarationIndexHelpers.test.ts +++ /dev/null @@ -1,298 +0,0 @@ -import * as chai from 'chai'; -import { renameSync } from 'fs'; -import { join } from 'path'; -import { - ClassDeclaration, - DeclarationIndex, - DefaultDeclaration, - ExternalModuleImport, - NamedImport, - NamespaceImport, - SymbolSpecifier, - TypescriptParser, -} from 'typescript-parser'; -import { workspace } from 'vscode'; - -import { ExtensionConfig } from '../../../../src/common/config'; -import { - findFiles, - getAbsolutLibraryName, - getDeclarationsFilteredByImports, - getRelativeLibraryName, -} from '../../../../src/common/helpers'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; - -const should = chai.should(); - -describe('DeclarationIndexHelpers', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - const documentPath = join(rootPath, 'foobar.ts'); - - describe('getDeclarationsFilteredByImports()', () => { - - let index: DeclarationIndex; - - before(async () => { - const parser = Container.get(iocSymbols.typescriptParser); - index = new DeclarationIndex(parser, rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'typings/globals/body-parser/index.d.ts', - ), - join( - rootPath, - 'server/indices/MyClass.ts', - ), - join( - rootPath, - 'server/indices/defaultExport/multiExport.ts', - ), - ], - ); - }); - - it('should return the whole list if no imports are specified', () => { - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [], rootPath); - result.length.should.equal(18); - should.exist(result.find(d => d.declaration.name === 'Class1')); - should.exist(result.find(d => d.declaration.name === 'bodyParser')); - should.exist(result.find(d => d.declaration.name === 'MultiExportClass')); - should.exist(result.find(d => d.declaration.name === 'multiExport')); - }); - - it('should filter out declarations that are namespace imported', () => { - const imp = new NamespaceImport('body-parser', 'bodyParser'); - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [imp], rootPath); - result.filter(d => d.from === 'body-parser').length.should.equal(0); - }); - - it('should filter out declarations that are module imported', () => { - const imp = new ExternalModuleImport('body-parser', 'bodyParser'); - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [imp], rootPath); - result.filter(d => d.from === 'body-parser').length.should.equal(0); - }); - - it('should filter out a specifier from a named import', () => { - const imp = new NamedImport('/server/indices/MyClass'); - imp.specifiers.push(new SymbolSpecifier('Class1')); - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [imp], rootPath); - should.not.exist(result.find(d => d.declaration.name === 'Class1')); - should.exist(result.find(d => d.declaration.name === 'Class2')); - }); - - it('should filter out an aliased specifier from a named import', () => { - const imp = new NamedImport('/server/indices/MyClass'); - imp.specifiers.push(new SymbolSpecifier('Class1', 'FooBar')); - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [imp], rootPath); - should.not.exist(result.find(d => d.declaration.name === 'Class1')); - should.exist(result.find(d => d.declaration.name === 'Class2')); - }); - - it('should filter out the default declaration from a named import', () => { - const imp = new NamedImport('/server/indices/defaultExport/multiExport'); - imp.defaultAlias = 'multiExport'; - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [imp], rootPath); - should.exist( - result.find(d => d.declaration instanceof ClassDeclaration && d.declaration.name === 'MultiExportClass'), - ); - should.not.exist( - result.find(d => d.declaration instanceof DefaultDeclaration && d.declaration.name === 'multiExport'), - ); - }); - - it('should filter out a declaration from a file with a default and a normal export', () => { - const imp = new NamedImport('/server/indices/defaultExport/multiExport'); - imp.specifiers.push(new SymbolSpecifier('MultiExportClass')); - const result = getDeclarationsFilteredByImports(index.declarationInfos, documentPath, [imp], rootPath); - should.not.exist( - result.find(d => d.declaration instanceof ClassDeclaration && d.declaration.name === 'MultiExportClass'), - ); - should.exist( - result.find(d => d.declaration instanceof DefaultDeclaration && d.declaration.name === 'multiExport'), - ); - }); - - }); - - describe('getAbsolutLibraryName()', () => { - - it('should not contain any \\', () => { - const path = getAbsolutLibraryName('./server/indices/MyClass', documentPath, rootPath); - path.should.not.contain('\\'); - }); - - it('should calculate the correct absolute workspace path', () => { - const path = getAbsolutLibraryName('./server/indices/MyClass', documentPath, rootPath); - path.should.equal('/server/indices/MyClass'); - }); - - it('should return the library name if not a workspace file', () => { - const path = getAbsolutLibraryName('body-parser', documentPath, rootPath); - path.should.equal('body-parser'); - }); - - it('should return the library name if the root path is not set', () => { - const path = getAbsolutLibraryName('./server/indices/MyClass', documentPath); - path.should.equal('./server/indices/MyClass'); - }); - - }); - - describe('getRelativeLibraryName()', () => { - - it('should not contain any \\', () => { - const path = getRelativeLibraryName('/server/indices/MyClass', documentPath, rootPath); - path.should.not.contain('\\'); - }); - - it('should prepend a relative path from the same directory with ./', () => { - const path = getRelativeLibraryName('/server/indices/MyClass', documentPath, rootPath); - path.should.equal('./server/indices/MyClass'); - }); - - it('should calculate the correct relative workspace path', () => { - const path = getRelativeLibraryName('/server/indices/MyClass', documentPath, rootPath); - path.should.equal('./server/indices/MyClass'); - }); - - it('should calculate the correct relative workspace path 2', () => { - const otherDoc = join(rootPath, 'extension', 'managers', 'ClassManagerFile.ts'); - const path = getRelativeLibraryName('/server/indices/MyClass', otherDoc, rootPath); - path.should.equal('../../server/indices/MyClass'); - }); - - it('should return the library name if not a workspace file', () => { - const path = getRelativeLibraryName('body-parser', documentPath, rootPath); - path.should.equal('body-parser'); - }); - - it('should return the library name if the root path is not set', () => { - const path = getRelativeLibraryName('/server/indices/MyClass', documentPath); - path.should.equal('/server/indices/MyClass'); - }); - - }); - - describe('findFiles()', () => { - - let config: ExtensionConfig; - const workfolder = workspace.workspaceFolders![0]; - - beforeEach(() => { - config = { - resolver: { - workspaceIgnorePatterns: [ - '**/build/**/*', - '**/dist/**/*', - '**/out/**/*', - ], - moduleIgnorePatterns: [ - '**/node_modules/**/*', - ], - resolverModeFileGlobs: [ - '**/*.ts', - '**/*.tsx', - '**/*.js', - '**/*.jsx', - ], - }, - } as any as ExtensionConfig; - }); - - it('should find all relevant file in the workspace (*.ts)', async () => { - config.resolver.resolverModeFileGlobs = config.resolver.resolverModeFileGlobs.filter(o => o.indexOf('ts') >= 0); - const result = await findFiles(config, workfolder); - result.length.should.equal(51); - (result.every(file => file.endsWith('.ts') || file.endsWith('.tsx'))).should.be.true; - result.should.contain(join(rootPath, 'typings/globals/body-parser/index.d.ts')); - result.should.contain(join(rootPath, 'foobar.ts')); - result.should.contain(join(rootPath, 'common/ts-parsing/class.ts')); - result.should.contain(join(rootPath, 'extension/extensions/codeActionExtension/empty.ts')); - result.should.contain(join(rootPath, 'node_modules/@types/node/index.d.ts')); - result.should.contain(join(rootPath, 'node_modules/fancy-library/index.d.ts')); - result.should.contain(join(rootPath, 'node_modules/some-lib/dist/SomeDeclaration.d.ts')); - }); - - it('should find all relevant file in the workspace (*.js)', async () => { - config.resolver.resolverModeFileGlobs = config.resolver.resolverModeFileGlobs.filter(o => o.indexOf('js') >= 0); - const result = await findFiles(config, workfolder); - result.length.should.equal(10); - result.should.contain(join(rootPath, 'extension/extensions/importResolveExtension/addImportToDocument.js')); - result.should.contain(join(rootPath, 'extension/extensions/importResolveExtension/jsfile.js')); - result.should.contain(join(rootPath, 'extension/extensions/importResolveExtension/jsxfile.jsx')); - result.should.not.contain(join(rootPath, 'common/ts-parsing/class.ts')); - result.should.not.contain(join(rootPath, 'extension/extensions/codeActionExtension/empty.ts')); - result.should.contain(join(rootPath, 'node_modules/@types/node/index.d.ts')); - result.should.contain(join(rootPath, 'node_modules/fancy-library/index.d.ts')); - result.should.contain(join(rootPath, 'node_modules/some-lib/dist/SomeDeclaration.d.ts')); - result.should.contain(join(rootPath, 'typings/globals/body-parser/index.d.ts')); - }); - - it('should find all relevant file in the workspace (*.ts & *.js)', async () => { - const result = await findFiles(config, workfolder); - result.length.should.equal(54); - result.should.contain(join(rootPath, 'extension/extensions/importResolveExtension/addImportToDocument.js')); - result.should.contain(join(rootPath, 'extension/extensions/importResolveExtension/jsfile.js')); - result.should.contain(join(rootPath, 'extension/extensions/importResolveExtension/jsxfile.jsx')); - result.should.contain(join(rootPath, 'foobar.ts')); - result.should.contain(join(rootPath, 'common/ts-parsing/class.ts')); - result.should.contain(join(rootPath, 'common/ts-parsing/class.ts')); - result.should.contain(join(rootPath, 'extension/extensions/codeActionExtension/empty.ts')); - result.should.contain(join(rootPath, 'node_modules/@types/node/index.d.ts')); - result.should.contain(join(rootPath, 'node_modules/fancy-library/index.d.ts')); - result.should.contain(join(rootPath, 'typings/globals/body-parser/index.d.ts')); - }); - - it('should not contain build, out or dist files', async () => { - const result = await findFiles(config, workfolder); - result.should.not.contain(join(rootPath, 'build/app.js')); - result.should.not.contain(join(rootPath, 'build/app.d.ts')); - result.should.not.contain(join(rootPath, 'out/out.js')); - result.should.not.contain(join(rootPath, 'out/out.d.ts')); - }); - - it('should contain build files when configured otherwise', async () => { - config.resolver.workspaceIgnorePatterns = []; - const result = await findFiles(config, workfolder); - result.should.contain(join(rootPath, 'build/app.js')); - result.should.contain(join(rootPath, 'build/app.d.ts')); - result.should.contain(join(rootPath, 'out/out.js')); - result.should.contain(join(rootPath, 'out/out.d.ts')); - }); - - it('should not contain certain files of the modules when configured as such', async () => { - config.resolver.moduleIgnorePatterns = [ - '**/dist/**/*', - ]; - const result = await findFiles(config, workfolder); - result.should.not.contain(join(rootPath, 'node_modules/some-lib/dist/SomeDeclaration.d.ts')); - }); - - describe('without package.json', () => { - - const packageJson = join(rootPath, 'package.json'); - const packageJsonNew = join(rootPath, 'package-new.json'); - - before(() => { - renameSync(packageJson, packageJsonNew); - }); - - after(() => { - renameSync(packageJsonNew, packageJson); - }); - - it('should not contain node_modules when package.json is not present', async () => { - const result = await findFiles(config, workfolder); - result.should.not.contain(join(rootPath, 'node_modules/@types/node/index.d.ts')); - result.should.not.contain(join(rootPath, 'node_modules/fancy-library/index.d.ts')); - }); - - }); - - }); - -}); diff --git a/test/_old/single-workspace-tests/common/helpers/ImportHelpers.test.ts b/test/_old/single-workspace-tests/common/helpers/ImportHelpers.test.ts deleted file mode 100644 index 781d69a..0000000 --- a/test/_old/single-workspace-tests/common/helpers/ImportHelpers.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as chai from 'chai'; - -import { getImportInsertPosition } from '../../../../src/common/helpers'; - -chai.should(); - -class MockDocument { - constructor(private documentText: string) { } - - public getText(): string { - return this.documentText; - } -} - -describe('ImportHelpers', () => { - - describe('getImportInsertPosition', () => { - - it('should return top position if no editor is specified', () => { - const pos = getImportInsertPosition(undefined); - pos.character.should.equal(0); - pos.line.should.equal(0); - }); - - it('should return the top position if empty file', () => { - const pos = getImportInsertPosition({ - document: new MockDocument(''), - } as any); - pos.character.should.equal(0); - pos.line.should.equal(0); - }); - - it('should return correct position for commented file', () => { - const pos = getImportInsertPosition({ - document: new MockDocument(' // This is a file header\nStart of file\n'), - } as any); - pos.character.should.equal(0); - pos.line.should.equal(1); - }); - - it('should return correct position for use strict', () => { - const pos = getImportInsertPosition({ - document: new MockDocument(`'use strict'\nStart of file\n`), - } as any); - pos.character.should.equal(0); - pos.line.should.equal(1); - }); - - it('should return correct position for jsdoc comment open', () => { - const pos = getImportInsertPosition({ - document: new MockDocument('/** start of a jsdoc\n'), - } as any); - pos.character.should.equal(0); - pos.line.should.equal(1); - }); - - it('should return correct position for jsdoc comment line', () => { - const pos = getImportInsertPosition({ - document: new MockDocument(' * jsdoc line\n'), - } as any); - pos.character.should.equal(0); - pos.line.should.equal(1); - }); - - it('should return correct position for jsdoc comment close', () => { - const pos = getImportInsertPosition({ - document: new MockDocument('*/\n'), - } as any); - pos.character.should.equal(0); - pos.line.should.equal(1); - }); - - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts b/test/_old/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts deleted file mode 100644 index 827a5f1..0000000 --- a/test/_old/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { join } from 'path'; -import { TypescriptParser } from 'typescript-parser'; -import * as vscode from 'vscode'; - -import { ConfigFactory } from '../../../../src/common/factories'; -import { DocumentSymbolStructureExtension } from '../../../../src/extension/extensions/DocumentSymbolStructureExtension'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { BaseStructureTreeItem } from '../../../../src/extension/provider-items/document-structure/BaseStructureTreeItem'; -import { - DeclarationStructureTreeItem, -} from '../../../../src/extension/provider-items/document-structure/DeclarationStructureTreeItem'; -import { - DisabledStructureTreeItem, -} from '../../../../src/extension/provider-items/document-structure/DisabledStructureTreeItem'; -import { - ImportsStructureTreeItem, -} from '../../../../src/extension/provider-items/document-structure/ImportsStructureTreeItem'; -import { - NotParseableStructureTreeItem, -} from '../../../../src/extension/provider-items/document-structure/NotParseableStructureTreeItem'; -import { Logger } from '../../../../src/extension/utilities/winstonLogger'; - - -describe('DocumentSymbolStructureExtension', () => { - - const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - let extension: DocumentSymbolStructureExtension; - const file = join( - rootPath, - 'extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts', - ); - - before(async () => { - const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.logger); - const parser = Container.get(iocSymbols.typescriptParser); - const config = Container.get(iocSymbols.configuration); - - extension = new DocumentSymbolStructureExtension(ctx, logger, config, parser); - }); - - beforeEach(async () => { - const document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - }); - - afterEach(async () => { - await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - }); - - it('should return an empty array if no active window is set', async () => { - await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - - const elements = await extension.getChildren() as BaseStructureTreeItem[]; - elements.should.have.lengthOf(0); - }); - - it('should return a "file not parsable" if it is no ts file', async () => { - const file = join( - rootPath, - 'extension/extensions/documentSymbolStructureExtension/notParsable.txt', - ); - const txtDocument = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(txtDocument); - - const elements = await extension.getChildren() as BaseStructureTreeItem[]; - elements[0].should.be.instanceof(NotParseableStructureTreeItem); - - await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - }); - - it('should return a "not enabled" if the part is disabled via config', async () => { - const config = vscode.workspace.getConfiguration('typescriptHero'); - - try { - await config.update('codeOutline.enabled', false); - const elements = await extension.getChildren() as BaseStructureTreeItem[]; - elements[0].should.be.instanceof(DisabledStructureTreeItem); - } finally { - await config.update('codeOutline.enabled', true); - } - }); - - it('should return the document code structure for a valid file', async () => { - const elements = await extension.getChildren() as BaseStructureTreeItem[]; - - elements[0].should.be.instanceof(ImportsStructureTreeItem); - elements[1].should.be.instanceof(DeclarationStructureTreeItem); - elements[2].should.be.instanceof(DeclarationStructureTreeItem); - - elements[1].label.should.equal('Yay'); - elements[2].label.should.equal('ArrList'); - - elements[2].getChildren().should.have.lengthOf(1); - elements[2].getChildren()[0].label.should.equal('method(param: T): T'); - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts b/test/_old/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts deleted file mode 100644 index 7692492..0000000 --- a/test/_old/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts +++ /dev/null @@ -1,481 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import * as sinon from 'sinon'; -import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; -import * as vscode from 'vscode'; - -import { ConfigFactory } from '../../../../src/common/factories'; -import { ImportResolveExtension } from '../../../../src/extension/extensions/ImportResolveExtension'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; -import { Logger } from '../../../../src/extension/utilities/winstonLogger'; - -chai.should(); - - -describe('TypeScript Mode: ImportResolveExtension', () => { - - const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - let extension: any; - - before(async () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.ts', - ); - const document = await vscode.workspace.openTextDocument(file); - - await vscode.window.showTextDocument(document); - - const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.logger); - const config = Container.get(iocSymbols.configuration); - const parser = Container.get(iocSymbols.typescriptParser); - const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - - const index = new DeclarationIndex(parser, rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'typings/globals/body-parser/index.d.ts', - ), - join( - rootPath, - 'server/indices/MyClass.ts', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/sub1/sub2/sub3/subFile.ts', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/sameDirectory.ts', - ), - ], - ); - - fakeMapper.getIndexForFile = sinon.spy(() => index); - - extension = new ImportResolveExtension(ctx, logger, parser, fakeMapper); - }); - - describe('addImportToDocument', () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.ts', - ); - let document: vscode.TextDocument; - - before(async () => { - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('shoud write a module / namespace import correctly', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'bodyParser', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import * as bodyParser from 'body-parser';\n`); - }); - - it('shoud write a named import correctly', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'Class1', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import { Class1 } from '../../../server/indices/MyClass';\n`); - }); - - it('shoud update a named import correcty', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'Class', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - await extension.addImportToDocument(items[1]); - document.getText().should.equal(`import { Class1, Class2 } from '../../../server/indices/MyClass';\n`); - }); - - it('shoud use the correct relative path', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'Class1', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.match(/\.\.\/\.\.\/\.\.\/server\/indices/); - }); - - it('shoud only use forward slashes', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'SubFileLevel3', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.not.match(/\\/); - }); - - it('shoud use ./ for same directory files', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'AddImportSameDirectory', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.match(/\.\/sameDirectory/); - }); - - }); - - describe('organizeImports', () => { - - const file = join(rootPath, 'extension/extensions/importResolveExtension/organizeImports.ts'); - let document: vscode.TextDocument; - let documentText: string; - - before(async () => { - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - documentText = document.getText(); - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new vscode.Position(0, 0), documentText); - }); - }); - - it('shoud remove unused imports', async () => { - await extension.organizeImports(); - document.getText().should.not.match(/Class1/); - }); - - it('shoud order string imports to the top', async () => { - await extension.organizeImports(); - document.lineAt(0).text.should.equal(`import 'foo-bar';`); - }); - - it('shoud order libraries by name', async () => { - await extension.organizeImports(); - document.lineAt(2).text.should.match(/resourceIndex/); - document.lineAt(3).text.should.match(/subfolderstructure/); - }); - - it('shoud order specifiers by name', async () => { - await extension.organizeImports(); - document.lineAt(2).text.should.match(/ExportAlias.*FancierLibraryClass/); - }); - - }); - - describe('organizeImports with exports', () => { - - const file = join(rootPath, 'extension/extensions/importResolveExtension/organizeImportsWithExports.ts'); - let document: vscode.TextDocument; - let documentText: string; - - before(async () => { - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - documentText = document.getText(); - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new vscode.Position(0, 0), documentText); - }); - }); - - it('shoud remove unused imports', async () => { - await extension.organizeImports(); - document.getText().should.not.match(/notUsed/); - }); - - it('shoud not remove the used import beneath an export', async () => { - await extension.organizeImports(); - document.lineAt(0).text.should.equal(`import { moduleFunc } from 'SomeModule';`); - }); - - }); - -}); - -describe('JavaScript Mode: ImportResolveExtension', () => { - - const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - let extension: any; - - before(async () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.js', - ); - const document = await vscode.workspace.openTextDocument(file); - - await vscode.window.showTextDocument(document); - - const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.logger); - const config = Container.get(iocSymbols.configuration); - const parser = Container.get(iocSymbols.typescriptParser); - const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - - const index = new DeclarationIndex(parser, rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'typings/globals/body-parser/index.d.ts', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/jsfile.js', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/jsxfile.jsx', - ), - ], - ); - - fakeMapper.getIndexForFile = sinon.spy(() => index); - - extension = new ImportResolveExtension(ctx, logger, parser, fakeMapper); - }); - - describe('addImportToDocument', () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.js', - ); - let document: vscode.TextDocument; - - before(async () => { - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('shoud write a module / namespace import correctly', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'bodyParser', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import * as bodyParser from 'body-parser';\n`); - }); - - it('shoud write a named import correctly', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'JSFoobar', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import { JSFoobar } from './jsfile';\n`); - }); - - it('shoud update a named import correcty', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'JSX', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - await extension.addImportToDocument(items[1]); - document.getText().should.equal(`import { JSXClass, JSXFunction } from './jsxfile';\n`); - }); - - }); - -}); - -describe('Mixed Mode: ImportResolveExtension', () => { - - const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - let extension: any; - - before(async () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.ts', - ); - const document = await vscode.workspace.openTextDocument(file); - - await vscode.window.showTextDocument(document); - - const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.logger); - const config = Container.get(iocSymbols.configuration); - const parser = Container.get(iocSymbols.typescriptParser); - const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - - const index = new DeclarationIndex(parser, rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'typings/globals/body-parser/index.d.ts', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/jsfile.js', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/jsxfile.jsx', - ), - join( - rootPath, - 'extension/extensions/importResolveExtension/sameDirectory.ts', - ), - ], - ); - - fakeMapper.getIndexForFile = sinon.spy(() => index); - - extension = new ImportResolveExtension(ctx, logger, parser, fakeMapper); - }); - - describe('addImportToDocument in .js file', () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.js', - ); - let document: vscode.TextDocument; - - before(async () => { - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('shoud write a module / namespace import correctly', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'bodyParser', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import * as bodyParser from 'body-parser';\n`); - }); - - it('shoud write a named import correctly (JS)', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'JSFoobar', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import { JSFoobar } from './jsfile';\n`); - }); - - it('shoud write a named import correctly (TS)', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'AddImportSameDirectory', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import { AddImportSameDirectory } from './sameDirectory';\n`); - }); - - }); - - describe('addImportToDocument in .ts file', () => { - const file = join( - rootPath, - 'extension/extensions/importResolveExtension/addImportToDocument.ts', - ); - let document: vscode.TextDocument; - - before(async () => { - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('shoud write a module / namespace import correctly', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'bodyParser', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import * as bodyParser from 'body-parser';\n`); - }); - - it('shoud write a named import correctly (JS)', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'JSFoobar', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import { JSFoobar } from './jsfile';\n`); - }); - - it('shoud write a named import correctly (TS)', async () => { - const items = await extension.getDeclarationsForImport({ - cursorSymbol: 'AddImportSameDirectory', - documentSource: '', - docuemntPath: document.fileName, - }); - await extension.addImportToDocument(items[0]); - document.getText().should.equal(`import { AddImportSameDirectory } from './sameDirectory';\n`); - }); - - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts b/test/_old/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts deleted file mode 100644 index 2f981c3..0000000 --- a/test/_old/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as chai from 'chai'; - -import { - ImportGroupIdentifierInvalidError, - ImportGroupKeyword, - ImportGroupSettingParser, - KeywordImportGroup, - RegexImportGroup, -} from '../../../../src/extension/import-grouping'; - -chai.should(); - -describe('ImportGroupSettingParser', () => { - - it('should parse a simple keyword', () => { - const result = ImportGroupSettingParser.parseSetting('Workspace') as KeywordImportGroup; - - result.keyword.should.equal(ImportGroupKeyword.Workspace); - result.order.should.equal('asc'); - }); - - it('should parse a simple regex', () => { - const result = ImportGroupSettingParser.parseSetting('/foobar/') as RegexImportGroup; - - result.regex.should.equal('/foobar/'); - result.order.should.equal('asc'); - }); - - it('should parse a complex keyword pattern', () => { - const result = ImportGroupSettingParser.parseSetting({ - identifier: 'Workspace', - order: 'desc', - }) as KeywordImportGroup; - - result.keyword.should.equal(ImportGroupKeyword.Workspace); - result.order.should.equal('desc'); - }); - - it('should parse a complex regex pattern', () => { - const result = ImportGroupSettingParser.parseSetting({ - identifier: '/foobar/', - order: 'desc', - }) as RegexImportGroup; - - result.regex.should.equal('/foobar/'); - result.order.should.equal('desc'); - }); - - it('should throw on non found keyword and regex', () => { - const fn = () => ImportGroupSettingParser.parseSetting('whatever'); - - fn.should.throw(ImportGroupIdentifierInvalidError); - }); - - it('should parse a regex with "or"', () => { - const result = ImportGroupSettingParser.parseSetting('/angular|react/'); - - result.should.be.an.instanceof(RegexImportGroup); - (result as RegexImportGroup).regex.should.equal('/angular|react/'); - }); - - it('should parse a regex with "@"', () => { - const result = ImportGroupSettingParser.parseSetting('/@angular/'); - - result.should.be.an.instanceof(RegexImportGroup); - (result as RegexImportGroup).regex.should.equal('/@angular/'); - }); - - it('should parse a complex regex', () => { - const result = ImportGroupSettingParser.parseSetting('/(@angular|react)/core/(.*)/'); - - result.should.be.an.instanceof(RegexImportGroup); - (result as RegexImportGroup).regex.should.equal('/(@angular|react)/core/(.*)/'); - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts b/test/_old/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts deleted file mode 100644 index 29c82f2..0000000 --- a/test/_old/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import { File, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { workspace } from 'vscode'; - -import { TypescriptCodeGeneratorFactory } from '../../../../src/common/factories'; -import { ImportGroupKeyword, KeywordImportGroup } from '../../../../src/extension/import-grouping'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; - -chai.should(); - - -describe('KeywordImportGroup', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - let file: File; - let importGroup: KeywordImportGroup; - let generator: TypescriptCodeGenerator; - - before(async () => { - const parser = Container.get(iocSymbols.typescriptParser); - generator = Container.get(iocSymbols.generatorFactory)(); - file = await parser.parseFile( - join( - rootPath, - 'extension/import-grouping/imports.ts', - ), - rootPath, - ); - }); - - describe(`keyword "Modules"`, () => { - - beforeEach(() => { - importGroup = new KeywordImportGroup(ImportGroupKeyword.Modules); - }); - - it('should process a module import', () => { - importGroup.processImport(file.imports[4]).should.be.true; - }); - - it('should not process a plain import', () => { - importGroup.processImport(file.imports[0]).should.be.false; - }); - - it('should not process a workspace import', () => { - importGroup.processImport(file.imports[2]).should.be.false; - }); - - it('should correctly process a list of imports', () => { - file.imports.map(i => importGroup.processImport(i)).should.deep.equal([false, false, false, false, true, true]); - }); - - it('should generate the correct typescript (asc)', () => { - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import { AnotherModuleFoo } from 'anotherLib';\n` + - `import { ModuleFoobar } from 'myLib';\n`, - ); - }); - - it('should generate the correct typescript (desc)', () => { - (importGroup as any).order = 'desc'; - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import { ModuleFoobar } from 'myLib';\n` + - `import { AnotherModuleFoo } from 'anotherLib';\n`, - ); - }); - - }); - - describe(`keyword "Plains"`, () => { - - beforeEach(() => { - importGroup = new KeywordImportGroup(ImportGroupKeyword.Plains); - }); - - it('should not process a module import', () => { - importGroup.processImport(file.imports[4]).should.be.false; - }); - - it('should process a plain import', () => { - importGroup.processImport(file.imports[0]).should.be.true; - }); - - it('should not process a workspace import', () => { - importGroup.processImport(file.imports[2]).should.be.false; - }); - - it('should correctly process a list of imports', () => { - file.imports.map(i => importGroup.processImport(i)).should.deep.equal([true, true, false, false, false, false]); - }); - - it('should generate the correct typescript (asc)', () => { - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import './workspaceSideEffectLib';\n` + - `import 'sideEffectLib';\n`, - ); - }); - - it('should generate the correct typescript (desc)', () => { - (importGroup as any).order = 'desc'; - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import 'sideEffectLib';\n` + - `import './workspaceSideEffectLib';\n`, - ); - }); - - }); - - describe(`keyword "Workspace"`, () => { - - beforeEach(() => { - importGroup = new KeywordImportGroup(ImportGroupKeyword.Workspace); - }); - - it('should not process a module import', () => { - importGroup.processImport(file.imports[4]).should.be.false; - }); - - it('should not process a plain import', () => { - importGroup.processImport(file.imports[0]).should.be.false; - }); - - it('should process a workspace import', () => { - importGroup.processImport(file.imports[2]).should.be.true; - }); - - it('should correctly process a list of imports', () => { - file.imports.map(i => importGroup.processImport(i)).should.deep.equal([false, false, true, true, false, false]); - }); - - it('should generate the correct typescript (asc)', () => { - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import { AnotherFoobar } from './anotherFile';\n` + - `import { Foobar } from './myFile';\n`, - ); - }); - - it('should generate the correct typescript (desc)', () => { - (importGroup as any).order = 'desc'; - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import { Foobar } from './myFile';\n` + - `import { AnotherFoobar } from './anotherFile';\n`, - ); - }); - - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts b/test/_old/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts deleted file mode 100644 index 49e88c5..0000000 --- a/test/_old/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import { File, NamedImport, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { workspace } from 'vscode'; - -import { TypescriptCodeGeneratorFactory } from '../../../../src/common/factories'; -import { RegexImportGroup } from '../../../../src/extension/import-grouping'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; - -chai.should(); - -describe('RegexImportGroup', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - let file: File; - let importGroup: RegexImportGroup; - let generator: TypescriptCodeGenerator; - - before(async () => { - const parser = Container.get(iocSymbols.typescriptParser); - generator = Container.get(iocSymbols.generatorFactory)(); - file = await parser.parseFile( - join( - rootPath, - 'extension/import-grouping/imports.ts', - ), - rootPath, - ); - }); - - beforeEach(() => { - importGroup = new RegexImportGroup(`/Lib/`); - }); - - it('should process a matching import', () => { - importGroup.processImport(file.imports[0]).should.be.true; - }); - - it('should not process a not matching import', () => { - importGroup.processImport(file.imports[2]).should.be.false; - }); - - it('should correctly process a list of imports', () => { - file.imports.map(i => importGroup.processImport(i)).should.deep.equal([true, true, false, false, true, true]); - }); - - it('should generate the correct typescript (asc)', () => { - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import './workspaceSideEffectLib';\n` + - `import 'sideEffectLib';\n` + - `import { AnotherModuleFoo } from 'anotherLib';\n` + - `import { ModuleFoobar } from 'myLib';\n`, - ); - }); - - it('should generate the correct typescript (desc)', () => { - (importGroup as any).order = 'desc'; - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import 'sideEffectLib';\n` + - `import './workspaceSideEffectLib';\n` + - `import { ModuleFoobar } from 'myLib';\n` + - `import { AnotherModuleFoo } from 'anotherLib';\n`, - ); - }); - - it('should work with regex "or" conditions', () => { - const group = new RegexImportGroup('/angular|react/'); - const imp = new NamedImport('@angular'); - const imp2 = new NamedImport('@react/core'); - - group.processImport(imp).should.be.true; - group.processImport(imp2).should.be.true; - }); - - it('should work with regex containing an "@"', () => { - const group = new RegexImportGroup('/@angular/'); - const imp = new NamedImport('@angular'); - - group.processImport(imp).should.be.true; - }); - - it('should work with slash separated regex', () => { - const group = new RegexImportGroup('/@angular/http/'); - const imp = new NamedImport('@angular/http'); - const imp2 = new NamedImport('@angular/core/component'); - - group.processImport(imp).should.be.true; - group.processImport(imp2).should.be.false; - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts b/test/_old/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts deleted file mode 100644 index 647b9e9..0000000 --- a/test/_old/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import { File, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { workspace } from 'vscode'; - -import { TypescriptCodeGeneratorFactory } from '../../../../src/common/factories'; -import { RemainImportGroup } from '../../../../src/extension/import-grouping'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; - -chai.should(); - -describe('RemainImportGroup', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - let file: File; - let importGroup: RemainImportGroup; - let generator: TypescriptCodeGenerator; - - before(async () => { - const parser = Container.get(iocSymbols.typescriptParser); - generator = Container.get(iocSymbols.generatorFactory)(); - file = await parser.parseFile( - join( - rootPath, - 'extension/import-grouping/imports.ts', - ), - rootPath, - ); - }); - - beforeEach(() => { - importGroup = new RemainImportGroup(); - }); - - it('should process all imports', () => { - file.imports.map(i => importGroup.processImport(i)).should.deep.equal([true, true, true, true, true, true]); - }); - - it('should generate the correct typescript (asc)', () => { - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import './workspaceSideEffectLib';\n` + - `import 'sideEffectLib';\n` + - `import { AnotherFoobar } from './anotherFile';\n` + - `import { Foobar } from './myFile';\n` + - `import { AnotherModuleFoo } from 'anotherLib';\n` + - `import { ModuleFoobar } from 'myLib';\n`, - ); - }); - - it('should generate the correct typescript (desc)', () => { - (importGroup as any).order = 'desc'; - for (const imp of file.imports) { - if (importGroup.processImport(imp)) { - continue; - } - } - generator.generate(importGroup as any).should.equal( - `import 'sideEffectLib';\n` + - `import './workspaceSideEffectLib';\n` + - `import { ModuleFoobar } from 'myLib';\n` + - `import { AnotherModuleFoo } from 'anotherLib';\n` + - `import { Foobar } from './myFile';\n` + - `import { AnotherFoobar } from './anotherFile';\n`, - ); - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/managers/ImportManager.test.ts b/test/_old/single-workspace-tests/extension/managers/ImportManager.test.ts deleted file mode 100644 index dc600b5..0000000 --- a/test/_old/single-workspace-tests/extension/managers/ImportManager.test.ts +++ /dev/null @@ -1,1002 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import * as sinon from 'sinon'; -import sinonChai = require('sinon-chai'); -import { DeclarationIndex, File, NamedImport } from 'typescript-parser'; -import { Position, Range, TextDocument, window, workspace } from 'vscode'; - -import { findFiles } from '../../../../src/common/helpers'; -import { VscodeExtensionConfig } from '../../../../src/extension/config/VscodeExtensionConfig'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { ImportManager } from '../../../../src/extension/managers'; - -const should = chai.should(); -chai.use(sinonChai); - -/** - * Mock window input box. - * - * @param {string} returnValue - * @returns {sinon.SinonStub} - */ -function mockInputBox(returnValue: string): sinon.SinonStub { - return sinon.stub(window, 'showInputBox').callsFake(() => { - return Promise.resolve(returnValue); - }); -} - -/** - * Restore window. - * - * @param {sinon.SinonStub} stub - */ -function restoreInputBox(stub: sinon.SinonStub): void { - stub.restore(); -} - -describe('ImportManager', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - const file = join(rootPath, 'extension/managers/ImportManagerFile.ts'); - let document: TextDocument; - let documentText: string; - let index: DeclarationIndex; - let files: string[]; - - before(async () => { - const config = new VscodeExtensionConfig(workspace.workspaceFolders![0].uri); - files = await findFiles(config, workspace.workspaceFolders![0]); - - index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); - await index.buildIndex(files); - - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - - documentText = document.getText(); - }); - - afterEach(async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new Position(0, 0), documentText); - }); - - }); - - describe('static create()', () => { - - it('should create a document controller', async () => { - const ctrl = await ImportManager.create(document); - ctrl.should.be.an.instanceof(ImportManager); - }); - - it('should parse the document', async () => { - const ctrl = await ImportManager.create(document); - (ctrl as any).parsedDocument.should.be.an.instanceof(File); - }); - - it('should add an import proxy for a named import', async () => { - const ctrl = await ImportManager.create(document); - const imps = (ctrl as any).parsedDocument.imports; - - imps[0].should.be.an.instanceof(NamedImport); - should.not.exist(imps[0].defaultAlias); - }); - - it('should add an import proxy for a default import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.replace( - new Range( - new Position(0, 0), - new Position(1, 0), - ), - `import myDefaultExportedFunction from '../defaultExport/lateDefaultExportedElement';\n`, - ); - }); - - const ctrl = await ImportManager.create(document); - const imps = (ctrl as any).parsedDocument.imports; - - imps[0].should.be.an.instanceof(NamedImport); - imps[0].defaultAlias.should.equal('myDefaultExportedFunction'); - }); - - it('should add multiple import proxies', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(0, 0), - `import myDefaultExportedFunction from '../defaultExport/lateDefaultExportedElement';\n`, - ); - }); - - const ctrl = await ImportManager.create(document); - const imps = (ctrl as any).parsedDocument.imports; - - imps[0].should.be.an.instanceof(NamedImport); - imps[0].defaultAlias.should.equal('myDefaultExportedFunction'); - imps[1].should.be.an.instanceof(NamedImport); - should.not.exist(imps[1].defaultAlias); - }); - - it('should not add a proxy for a namespace import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.replace( - new Range( - new Position(0, 0), - new Position(1, 0), - ), - `import * as bodyParser from 'body-parser';\n`, - ); - }); - - const ctrl = await ImportManager.create(document); - const imps = (ctrl as any).parsedDocument.imports; - - imps.should.have.lengthOf(1); - imps[0].should.not.be.an.instanceof(NamedImport); - }); - - it('should not add a proxy for an external import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.replace( - new Range( - new Position(0, 0), - new Position(1, 0), - ), - `import bodyParser = require('body-parser');\n`, - ); - }); - - const ctrl = await ImportManager.create(document); - const imps = (ctrl as any).parsedDocument.imports; - - imps.should.have.lengthOf(1); - imps[0].should.not.be.an.instanceof(NamedImport); - }); - - it('should not add a proxy for a string import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.replace( - new Range( - new Position(0, 0), - new Position(1, 0), - ), - `import 'body-parser';\n`, - ); - }); - - const ctrl = await ImportManager.create(document); - const imps = (ctrl as any).parsedDocument.imports; - - imps.should.have.lengthOf(1); - imps[0].should.not.be.an.instanceof(NamedImport); - }); - - }); - - describe('addDeclarationImport()', () => { - - it('should add a normal import to the document', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'NotBarelExported'); - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports.should.have.lengthOf(2); - (ctrl as any).imports[1].libraryName.should.equal('../../server/indices/NotBarelExported'); - (ctrl as any).imports[1].specifiers[0].specifier.should.equal('NotBarelExported'); - }); - - it('should add a module import to the import index', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.from === 'body-parser'); - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports.should.have.lengthOf(2); - (ctrl as any).imports[1].libraryName.should.equal('body-parser'); - (ctrl as any).imports[1].should.not.be.an.instanceof(NamedImport); - }); - - it('should add a default import to the import index.', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find( - o => o.declaration.name === 'myDefaultExportedFunction', - ); - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports.should.have.lengthOf(2); - (ctrl as any).imports[1].libraryName.should.equal( - '../../server/indices/defaultExport/lateDefaultExportedElement', - ); - (ctrl as any).imports[1].defaultAlias.should.equal('myDefaultExportedFunction'); - }); - - it('should add multiple imports to the import index', async () => { - const ctrl = await ImportManager.create(document); - const declarations = index.declarationInfos.filter(o => o.declaration.name === 'FancierLibraryClass'); - ctrl.addDeclarationImport(declarations[0]).addDeclarationImport(declarations[1]); - - (ctrl as any).imports.should.have.lengthOf(2); - (ctrl as any).imports[0].specifiers[1].specifier.should.equal('FancierLibraryClass'); - (ctrl as any).imports[1].libraryName.should.equal('fancy-library/FancierLibraryClass'); - (ctrl as any).imports[1].specifiers[0].specifier.should.equal('FancierLibraryClass'); - }); - - it('should add an import to an existing import index item', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'Class3'); - - ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); - - (ctrl as any).imports.should.have.lengthOf(1); - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class1'); - (ctrl as any).imports[0].specifiers[1].specifier.should.equal('Class2'); - (ctrl as any).imports[0].specifiers[2].specifier.should.equal('Class3'); - }); - - it('should not add the same specifier twice', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports.should.have.lengthOf(1); - (ctrl as any).imports[0].specifiers.should.have.lengthOf(2); - - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports[0].specifiers.should.have.lengthOf(2); - }); - - it('should add a normal import to a group', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'NotBarelExported'); - - // Import group 4 in single-workspace test settings is "Workspace" - (ctrl as any).importGroups[4].imports.should.have.lengthOf(1); - - ctrl.addDeclarationImport(declaration!); - - // Import group 4 in single-workspace test settings is "Workspace" - (ctrl as any).importGroups[4].imports.should.have.lengthOf(2); - }); - - it('should add an import to an existing import group', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'Class3'); - - // Import group 4 in single-workspace test settings is "Workspace" - (ctrl as any).importGroups[4].imports.should.have.lengthOf(1); - - ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); - - // Import group 4 in single-workspace test settings is "Workspace" - (ctrl as any).importGroups[4].imports.should.have.lengthOf(1); - }); - - }); - - describe('addMissingImports()', () => { - - it('should add a missing imports to the import index', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert(new Position(5, 0), `const foobar = new Class2();\n`); - }); - const ctrl = await ImportManager.create(document); - ctrl.addMissingImports(index); - - (ctrl as any).imports.should.have.lengthOf(1); - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class1'); - (ctrl as any).imports[0].specifiers[1].specifier.should.equal('Class2'); - }); - - it('should add multiple missing imports for a document', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(5, 0), - `const foobar = new Class2();\nconst foobaz = new Class3();` + - `\nconst barbaz = new NotBarelExported();\n`, - ); - }); - const ctrl = await ImportManager.create(document); - ctrl.addMissingImports(index); - - (ctrl as any).imports.should.have.lengthOf(2); - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class1'); - (ctrl as any).imports[0].specifiers[1].specifier.should.equal('Class2'); - (ctrl as any).imports[0].specifiers[2].specifier.should.equal('Class3'); - (ctrl as any).imports[1].libraryName.should.equal('../../server/indices/NotBarelExported'); - (ctrl as any).imports[1].specifiers[0].specifier.should.equal('NotBarelExported'); - }); - - it('should create a user decision specifier if multiple delcarations are found', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(5, 0), - `const foobar = new FancierLibraryClass();\n`, - ); - }); - const ctrl = await ImportManager.create(document); - ctrl.addMissingImports(index); - - (ctrl as any).imports.should.have.lengthOf(1); - (ctrl as any).userImportDecisions['FancierLibraryClass'].should.be.an('array').with.lengthOf(2); - }); - - }); - - describe('organizeImports()', () => { - - it('should remove an unused import', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'myComponent'); - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports.should.have.lengthOf(2); - (ctrl as any).imports[1].specifiers[0].specifier.should.equal('myComponent'); - - ctrl.organizeImports(); - - (ctrl as any).imports.should.have.lengthOf(1); - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class1'); - }); - - it('should remove an unused import from a group', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'myComponent'); - ctrl.addDeclarationImport(declaration!); - - // Import group 4 in single-workspace test settings is "Workspace" - (ctrl as any).importGroups[4].imports.should.have.lengthOf(2); - - ctrl.organizeImports(); - - // Import group 4 in single-workspace test settings is "Workspace" - (ctrl as any).importGroups[4].imports.should.have.lengthOf(1); - }); - - it('should remove an unused specifier from an import', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - ctrl.addDeclarationImport(declaration!); - - (ctrl as any).imports[0].specifiers.should.have.lengthOf(2); - - ctrl.organizeImports(); - - (ctrl as any).imports[0].specifiers.should.have.lengthOf(1); - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class1'); - }); - - it('should not remove a string import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(0, 0), - `import 'my-string-import';\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports.should.have.lengthOf(2); - - ctrl.organizeImports(); - - (ctrl as any).imports.should.have.lengthOf(2); - }); - - it('should order imports alphabetically', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(1, 0), - `import { AddImportSameDirectory } from '../../../server/indices';\n`, - ); - builder.insert(new Position(6, 0), `const foo = AddImportSameDirectory;\n`); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports[0].libraryName.should.equal('../../server/indices'); - - ctrl.organizeImports(); - - (ctrl as any).imports[0].libraryName.should.equal('../../../server/indices'); - }); - - it('should order string imports before normal imports', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert(new Position(1, 0), `import 'foobar';\n`); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports[0].libraryName.should.not.equal('foobar'); - - ctrl.organizeImports(); - - (ctrl as any).imports[0].libraryName.should.equal('foobar'); - }); - - it('should order specifiers alphabetically', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.replace( - document.lineAt(0).rangeIncludingLineBreak, - `import { Class2, Class1 } from '../resourceIndex';`, - ); - builder.insert(new Position(5, 0), `const foo = new Class2();\n`); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class2'); - - ctrl.organizeImports(); - - (ctrl as any).imports[0].specifiers[0].specifier.should.equal('Class1'); - }); - - it('should remove an unused default import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert( - new Position(0, 0), - `import DefaultImport from '../foobar';\n\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports[0].defaultAlias.should.equal('DefaultImport'); - - ctrl.organizeImports(); - - (ctrl as any).imports.should.have.lengthOf(0); - }); - - it('should not remove a used default import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert( - new Position(0, 0), - `import DefaultImport from '../foobar';\n\nlet foobar = DefaultImport();\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports[0].defaultAlias.should.equal('DefaultImport'); - - ctrl.organizeImports(); - - (ctrl as any).imports[0].defaultAlias.should.equal('DefaultImport'); - }); - - it('should remove a nonused import in a namespace', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert( - new Position(0, 0), - `import { Class1 } from '../foobar';\n\nnamespace WellHello {\n\n}\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports.should.have.lengthOf(1); - ctrl.organizeImports(); - (ctrl as any).imports.should.have.lengthOf(0); - }); - - it('should remove a nonused import in a module', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert( - new Position(0, 0), - `import { Class1 } from '../foobar';\n\module WellHello {\n\n}\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports.should.have.lengthOf(1); - ctrl.organizeImports(); - (ctrl as any).imports.should.have.lengthOf(0); - }); - - it('should not remove a reference that is encapsuled in a namespace', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert( - new Position(0, 0), - `import { Class1 } from '../foobar';\n\nnamespace WellHello {\n let a: Class1;\n}\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports.should.have.lengthOf(1); - ctrl.organizeImports(); - (ctrl as any).imports.should.have.lengthOf(1); - }); - - it('should not remove a reference that is encapsuled in a module', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert( - new Position(0, 0), - `import { Class1 } from '../foobar';\n\nmodule WellHello {\n let a: Class1;\n}\n`, - ); - }); - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports.should.have.lengthOf(1); - ctrl.organizeImports(); - (ctrl as any).imports.should.have.lengthOf(1); - }); - - it('should honor regex groups even if they appear later than keyword groups', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(0, 0), - ` - import mainFx from 'some-regular-module' - import { CoolerStuff, CoolerTitle } from 'cooler-library/items' - import CoolLib from 'cool-library' - import React, { Component } from 'react' - - import '../plain.ts' - `.replace(/\n[ \t]+/g, '\n') - ); - // Ensure imports are not stripped because they’re unused - builder.insert( - new Position(12, 0), - 'console.log(mainFx, CoolerStuff, CoolerTitle, CoolLib, React, Component)\n' - ) - }); - const ctrl = await ImportManager.create(document); - - await ctrl.organizeImports().commit(); - const names = (ctrl as any).imports.map((l) => l.libraryName) - names.should.deep.equal(['../plain.ts', 'react', 'some-regular-module', 'cool-library', 'cooler-library/items', '../../server/indices']) - }); - - describe('resolver.organizeSortsByFirstSpecifier: true', () => { - before(async () => { - const config = workspace.getConfiguration('typescriptHero'); - await config.update('resolver.organizeSortsByFirstSpecifier', true); - }); - - after(async () => { - const config = workspace.getConfiguration('typescriptHero'); - await config.update('resolver.organizeSortsByFirstSpecifier', false); - }); - - it('should sort imports by first specifier/alias', async () => { - const demoSource = ` - import { Foobar, Genero } from 'someLib'; - import { AnotherFoobar } from 'someOtherLib'; - import ModuleFoobar from 'myLib'; - import { AnotherModuleFoo as MuchFurtherSorted } from 'anotherLib'; - - console.log(AnotherFoobar, Foobar, Genero, ModuleFoobar, MuchFurtherSorted) - `.replace(/\n[ \t]+/g, '\n').trim(); - - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new Position(0, 0), demoSource); - }); - - const ctrl = await ImportManager.create(document); - - (ctrl as any).imports[0].libraryName.should.equal('someLib'); - - ctrl.organizeImports(); - - (ctrl as any).imports.map((i) => i.libraryName).should.deep.equal([ - 'someOtherLib', // { AnotherFoobar } - 'someLib', // { Foobar, Genero } - 'myLib', // ModuleFoobar - 'anotherLib', // { AnotherModuleFoo as MuchFurtherSorted } - ]); - }) - }) - }); - - describe('commit()', () => { - - it('should not touch anything if nothing changed', async () => { - const ctrl = await ImportManager.create(document); - - await window.activeTextEditor!.edit((builder) => { - builder.replace( - document.lineAt(0).rangeIncludingLineBreak, - `import {Class1} from '../resourceIndex';`, - ); - }); - - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals(`import {Class1} from '../resourceIndex';`); - }); - - it('should add a single new import to the document top', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'NotBarelExported'); - ctrl.addDeclarationImport(declaration!); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals( - `import { NotBarelExported } from '../../server/indices/NotBarelExported';`, - ); - }); - - it('should add two new imports to the document top', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'NotBarelExported'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'isString'); - - ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals( - `import { NotBarelExported } from '../../server/indices/NotBarelExported';`, - ); - document.lineAt(1).text.should.equals( - `import { isString } from '../../server/indices/HelperFunctions';`, - ); - }); - - it('should add three new imports to the document top', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'NotBarelExported'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'isString'); - const declaration3 = index.declarationInfos.find(o => o.declaration.name === 'myComponent'); - - ctrl.addDeclarationImport(declaration!) - .addDeclarationImport(declaration2!) - .addDeclarationImport(declaration3!); - - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals( - `import { NotBarelExported } from '../../server/indices/NotBarelExported';`, - ); - document.lineAt(1).text.should.equals( - `import { isString } from '../../server/indices/HelperFunctions';`, - ); - document.lineAt(2).text.should.equals( - `import { myComponent } from '../../server/indices/MyReactTemplate';`, - ); - }); - - it('should add a single new module import to the document top', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.from === 'body-parser'); - ctrl.addDeclarationImport(declaration!); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals(`import * as bodyParser from 'body-parser';`); - }); - - it('should add a single default import to the document top', async () => { - const stub = mockInputBox('DEFAULT_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find( - o => o.declaration.name === 'myDefaultExportedFunction', - ); - ctrl.addDeclarationImport(declaration!); - (await ctrl.commit()).should.be.true; - - stub.should.not.be.called; - document.lineAt(0).text.should.equals( - `import myDefaultExportedFunction from '../../server/indices/defaultExport/lateDefaultExportedElement';`, - ); - } finally { - restoreInputBox(stub); - } - }); - - it('should add a single aliased named import when names are conflicting', async () => { - const stub = mockInputBox('ALIASED_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - const declarations = index.declarationInfos.filter(o => o.declaration.name === 'FancierLibraryClass'); - ctrl.addDeclarationImport(declarations[0]).addDeclarationImport(declarations[1]); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equal( - `import { FancierLibraryClass } from 'fancy-library/FancierLibraryClass';`, - ); - document.lineAt(1).text.should.equal( - `import { Class1, FancierLibraryClass as ALIASED_IMPORT } from '../../server/indices';`, - ); - } finally { - restoreInputBox(stub); - } - }); - - it('should add a specifier to an existing import', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - ctrl.addDeclarationImport(declaration!); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals(`import { Class1, Class2 } from '../../server/indices';`); - }); - - it('should add multiple specifier to an existing import', async () => { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'Class3'); - - ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals(`import { Class1, Class2, Class3 } from '../../server/indices';`); - }); - - it('should add a specifier with a default (first) and a normal (second) import to the doc', async () => { - const stub = mockInputBox('DEFAULT_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'multiExport'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'MultiExportClass'); - - try { - ctrl.addDeclarationImport(declaration!); - ctrl.addDeclarationImport(declaration2!); - } catch (e) { - console.log(e); - } - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equals( - `import multiExport, { MultiExportClass } ` + - `from '../../server/indices/defaultExport/multiExport';`, - ); - } finally { - restoreInputBox(stub); - } - }); - - it('should add a specifier to an import and a new import', async () => { - const ctrl = await ImportManager.create(document); - const declaration1 = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'myComponent'); - - await ctrl.addDeclarationImport(declaration1!) - .addDeclarationImport(declaration2!) - .commit(); - - document.lineAt(0).text.should.equals( - `import { myComponent } from '../../server/indices/MyReactTemplate';`, - ); - document.lineAt(1).text.should.equals(`import { Class1, Class2 } from '../../server/indices';`); - }); - - it('should convert a default import when a normal specifier is added', async () => { - const stub = mockInputBox('DEFAULT_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - let declaration = index.declarationInfos.find(o => o.declaration.name === 'multiExport'); - await ctrl.addDeclarationImport(declaration!).commit(); - - document.lineAt(0).text.should.equals( - `import multiExport from '../../server/indices/defaultExport/multiExport';`, - ); - - declaration = index.declarationInfos.find(o => o.declaration.name === 'MultiExportClass'); - await ctrl.addDeclarationImport(declaration!).commit(); - - document.lineAt(0).text.should.equals( - `import multiExport, { MultiExportClass } ` + - `from '../../server/indices/defaultExport/multiExport';`, - ); - } finally { - restoreInputBox(stub); - } - }); - - it('should convert a normal import when a default specifier is added', async () => { - const stub = mockInputBox('DEFAULT_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - let declaration = index.declarationInfos.find(o => o.declaration.name === 'MultiExportClass'); - await ctrl.addDeclarationImport(declaration!).commit(); - - document.lineAt(0).text.should.equals( - `import { MultiExportClass } from '../../server/indices/defaultExport/multiExport';`, - ); - - declaration = index.declarationInfos.find(o => o.declaration.name === 'multiExport'); - ctrl.addDeclarationImport(declaration!); - await ctrl.commit(); - - document.lineAt(0).text.should.equals( - `import multiExport, { MultiExportClass } ` + - `from '../../server/indices/defaultExport/multiExport';`, - ); - } finally { - restoreInputBox(stub); - } - }); - - it('should render the optimized import', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert(new Position(5, 0), 'const foobar = new Class2();\n'); - }); - - const ctrl = await ImportManager.create(document); - const declaration1 = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'MultiExportClass'); - - await ctrl.addDeclarationImport(declaration1!) - .addDeclarationImport(declaration2!) - .commit(); - - document.lineAt(0).text.should.equals( - `import { MultiExportClass } from '../../server/indices/defaultExport/multiExport';`, - ); - document.lineAt(1).text.should.equals( - `import { Class1, Class2 } from '../../server/indices';`, - ); - - await ctrl.organizeImports().commit(); - - document.lineAt(0).text.should.equals( - `import { Class1, Class2 } from '../../server/indices';`, - ); - document.lineAt(1).text.should.equals(''); - }); - - it('should render sorted imports when optimizing', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert( - new Position(0, 0), - `import { MultiExportClass } from '../../server/indices/defaultExport/multiExport';\n`, - ); - builder.insert(new Position(5, 0), 'const foobar = new MultiExportClass();\n'); - }); - const ctrl = await ImportManager.create(document); - - await ctrl.organizeImports().commit(); - - document.lineAt(1).text.should.equals( - `import { MultiExportClass } from '../../server/indices/defaultExport/multiExport';`, - ); - document.lineAt(0).text.should.equals( - `import { Class1 } from '../../server/indices';`, - ); - }); - - it('should render sorted specifiers when optimizing', async () => { - await window.activeTextEditor!.edit((builder) => { - builder.insert(new Position(0, 9), 'Class2, '); - builder.insert(new Position(5, 0), 'const foobar = new Class2();\n'); - }); - const ctrl = await ImportManager.create(document); - - await ctrl.organizeImports().commit(); - - document.lineAt(0).text.should.equals( - `import { Class1, Class2 } from '../../server/indices';`, - ); - }); - - describe('resolver.promptForSpecifiers: false', () => { - - before(async () => { - const config = workspace.getConfiguration('typescriptHero'); - await config.update('resolver.promptForSpecifiers', false); - }); - - after(async () => { - const config = workspace.getConfiguration('typescriptHero'); - await config.update('resolver.promptForSpecifiers', true); - }); - - it('should not ask for a default alias', async () => { - const stub = mockInputBox('DEFAULT_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'multiExport'); - await ctrl.addDeclarationImport(declaration!).commit(); - - document.lineAt(0).text.should.equals( - `import multiExport from '../../server/indices/defaultExport/multiExport';`, - ); - - stub.should.not.be.called; - } finally { - restoreInputBox(stub); - } - }); - - it('should not ask for an alias on duplicate specifiers', async () => { - const stub = mockInputBox('ALIASED_IMPORT'); - try { - const ctrl = await ImportManager.create(document); - const declarations = index.declarationInfos.filter(o => o.declaration.name === 'FancierLibraryClass'); - ctrl.addDeclarationImport(declarations[0]).addDeclarationImport(declarations[1]); - (await ctrl.commit()).should.be.true; - - document.lineAt(0).text.should.equal( - `import { FancierLibraryClass } from 'fancy-library/FancierLibraryClass';`, - ); - document.lineAt(1).text.should.equal( - `import { Class1, FancierLibraryClass } from '../../server/indices';`, - ); - - stub.should.not.be.called; - } finally { - restoreInputBox(stub); - } - }); - - }); - - }); - -}); - -describe('ImportManager with .tsx files', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - const file = join(rootPath, 'extension/managers/ImportManagerFile.tsx'); - let document: TextDocument; - let documentText: string; - let index: DeclarationIndex; - let files: string[]; - - before(async () => { - const config = new VscodeExtensionConfig(workspace.workspaceFolders![0].uri); - files = await findFiles(config, workspace.workspaceFolders![0]); - - index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); - await index.buildIndex(files); - - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - - documentText = document.getText(); - }); - - afterEach(async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new Position(0, 0), documentText); - }); - - }); - - it('should not remove "react" since it is ignored in config', async () => { - const ctrl = await ImportManager.create(document); - ctrl.organizeImports(); - - (ctrl as any).imports.should.have.lengthOf(1); - (ctrl as any).imports[0].libraryName.should.equal('react'); - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/utilities/utilityFunctions.test.ts b/test/_old/single-workspace-tests/extension/utilities/utilityFunctions.test.ts deleted file mode 100644 index 2f20ba2..0000000 --- a/test/_old/single-workspace-tests/extension/utilities/utilityFunctions.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as chai from 'chai'; -import { Container } from '../../../../src/extension/IoC'; -import { TypescriptParser } from 'typescript-parser'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { join } from 'path'; -import { workspace } from 'vscode'; - -import { KeywordImportGroup, ImportGroupKeyword, RegexImportGroup } from '../../../../src/extension/import-grouping'; -import { importGroupSortForPrecedence, importSortByFirstSpecifier } from '../../../../src/extension/utilities/utilityFunctions'; - -chai.should(); - -describe('utilityFunctions', () => { - describe('importGroupSortForPrecedence', () => { - it('should prioritize regexes, leaving original order untouched besides that', () => { - const initialList = [ - new KeywordImportGroup(ImportGroupKeyword.Modules), - new KeywordImportGroup(ImportGroupKeyword.Plains), - new RegexImportGroup("/cool-library/"), - new RegexImportGroup("/cooler-library/"), - new KeywordImportGroup(ImportGroupKeyword.Workspace), - ] - const expectedList = initialList.slice(2, 4) - .concat(initialList.slice(0, 2)) - .concat(initialList.slice(4)) - - importGroupSortForPrecedence(initialList).should.deep.equal(expectedList, - 'Regex Import Groups should appear first (and that should be the only change)') - }); - }); - - describe('importSortByFirstSpecifier', () => { - const parser = Container.get(iocSymbols.typescriptParser); - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - - it('should sort according to first specifier/alias, falling back to module path', async () => { - const file = await parser.parseFile( - join( - rootPath, - 'extension/utilities/importsForSpecifierSort.ts', - ), - rootPath, - ); - - const result = [...file.imports].sort(importSortByFirstSpecifier); - result.map((i) => i.libraryName).should.deep.equal([ - './anotherFile', // { AnotherFoobar } - 'coolEffectLib', // 'coolEffectLib' - './myFile', // { Foobar, Genero } - 'myLib', // ModuleFoobar - 'anotherLib', // { AnotherModuleFoo as MuchFurtherSorted } - './workspaceSideEffectLib', // './workspaceSideEffectLib - ]); - }); - }); -}); diff --git a/test/_old/single-workspace-tests/index.ts b/test/_old/single-workspace-tests/index.ts deleted file mode 100644 index 9956ef9..0000000 --- a/test/_old/single-workspace-tests/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -import 'reflect-metadata'; - -import { ExtensionContext, Memento } from 'vscode'; - -import { Container } from '../../src/extension/IoC'; -import { iocSymbols } from '../../src/extension/IoCSymbols'; - -// tslint:disable - -// -// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING -// -// This file is providing the test runner to use when running extension tests. -// By default the test runner in use is Mocha based. -// -// You can provide your own test runner if you want to override it by exporting -// a function run(testRoot: string, clb: (error:Error) => void) that the extension -// host can call to run the tests. The test runner is expected to use console.log -// to report the results back to the caller. When the tests are finished, return -// a possible error to the callback or null if none. - -class ContextMock implements ExtensionContext { - subscriptions: { dispose(): any }[] = []; - workspaceState: Memento; - globalState: Memento; - extensionPath: string = ''; - storagePath: string = ''; - asAbsolutePath(): string { - return ''; - } -} - -Container.bind(iocSymbols.extensionContext).toConstantValue(new ContextMock()); - -const testRunner = require('vscode/lib/testrunner'); - -// You can directly control Mocha options by uncommenting the following lines -// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info -testRunner.configure({ - ui: 'bdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results -}); - -module.exports = testRunner; diff --git a/test/etc/workspace_1/declarations/barrel.ts b/test/etc/workspace_1/declarations/barrel.ts new file mode 100644 index 0000000..d8697eb --- /dev/null +++ b/test/etc/workspace_1/declarations/barrel.ts @@ -0,0 +1,2 @@ +export * from './declarations-for-barrel-1'; +export * from './declarations-for-barrel-2'; diff --git a/test/etc/workspace_1/declarations/build/build-file.ts b/test/etc/workspace_1/declarations/build/build-file.ts new file mode 100644 index 0000000..e628601 --- /dev/null +++ b/test/etc/workspace_1/declarations/build/build-file.ts @@ -0,0 +1 @@ +export class WorkspaceIgnored { } diff --git a/test/etc/workspace_1/declarations/declarations-for-barrel-1.ts b/test/etc/workspace_1/declarations/declarations-for-barrel-1.ts new file mode 100644 index 0000000..7c107fd --- /dev/null +++ b/test/etc/workspace_1/declarations/declarations-for-barrel-1.ts @@ -0,0 +1,8 @@ +export class ClassForBarrel1 { } +export class ClassForBarrel2 { } +export class ClassForBarrel3 { } +export class ClassForBarrel4 { } +export class ClassForBarrel5 { } +export interface InterfaceForBarrel1 { } +export interface InterfaceForBarrel2 { } +export interface InterfaceForBarrel3 { } diff --git a/test/etc/workspace_1/declarations/declarations-for-barrel-2.ts b/test/etc/workspace_1/declarations/declarations-for-barrel-2.ts new file mode 100644 index 0000000..418dd50 --- /dev/null +++ b/test/etc/workspace_1/declarations/declarations-for-barrel-2.ts @@ -0,0 +1,6 @@ +export const constForBarrel1 = ''; +export const constForBarrel2 = ''; +export const constForBarrel3 = ''; +export const constForBarrel4 = ''; +export const constForBarrel5 = ''; +export enum EnumForBarrel { } diff --git a/test/etc/workspace_1/declarations/declarations-for-index.ts b/test/etc/workspace_1/declarations/declarations-for-index.ts new file mode 100644 index 0000000..1112b45 --- /dev/null +++ b/test/etc/workspace_1/declarations/declarations-for-index.ts @@ -0,0 +1,8 @@ +export class ClassForIndex1 { } +export class ClassForIndex2 { } +export class ClassForIndex3 { } +export class ClassForIndex4 { } +export class ClassForIndex5 { } +export interface InterfaceForIndex1 { } +export interface InterfaceForIndex2 { } +export interface InterfaceForIndex3 { } diff --git a/test/etc/workspace_1/declarations/default-export.ts b/test/etc/workspace_1/declarations/default-export.ts new file mode 100644 index 0000000..5868ddf --- /dev/null +++ b/test/etc/workspace_1/declarations/default-export.ts @@ -0,0 +1 @@ +export default class DefaultExportedClass { } diff --git a/test/etc/workspace_1/declarations/default-multi-export.ts b/test/etc/workspace_1/declarations/default-multi-export.ts new file mode 100644 index 0000000..71f4a1a --- /dev/null +++ b/test/etc/workspace_1/declarations/default-multi-export.ts @@ -0,0 +1,2 @@ +export interface InterfaceInDefaultMultiExport { } +export default class DefaultMultiExport { } diff --git a/test/etc/workspace_1/declarations/default-unnamed-export.ts b/test/etc/workspace_1/declarations/default-unnamed-export.ts new file mode 100644 index 0000000..0b1f950 --- /dev/null +++ b/test/etc/workspace_1/declarations/default-unnamed-export.ts @@ -0,0 +1 @@ +export default class { } diff --git a/test/etc/workspace_1/declarations/index.ts b/test/etc/workspace_1/declarations/index.ts new file mode 100644 index 0000000..cf4de75 --- /dev/null +++ b/test/etc/workspace_1/declarations/index.ts @@ -0,0 +1,3 @@ +export * from './declarations-for-index'; + +export class ClassInIndex { } diff --git a/test/etc/workspace_1/declarations/multi-declarations.ts b/test/etc/workspace_1/declarations/multi-declarations.ts new file mode 100644 index 0000000..b70ac50 --- /dev/null +++ b/test/etc/workspace_1/declarations/multi-declarations.ts @@ -0,0 +1,24 @@ +export interface Interface { + method1(): void; + method2(str: string): number; +} + +export class Class { + public prop: string; + + public aMethod(str: string): T { + return null as T; + } + + private bMethod(): void { } +} + +export let exportedVariable = ''; + +export const exportedConstant = ''; + +export enum Enum { + a, + b, + c, +} diff --git a/test/etc/workspace_1/declarations/not-indexed.js b/test/etc/workspace_1/declarations/not-indexed.js new file mode 100644 index 0000000..e69de29 diff --git a/test/etc/workspace_1/declarations/not-indexed.txt b/test/etc/workspace_1/declarations/not-indexed.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/_old/_workspace/extension/import-grouping/imports.ts b/test/etc/workspace_1/imports/import-grouping/imports.ts similarity index 100% rename from test/_old/_workspace/extension/import-grouping/imports.ts rename to test/etc/workspace_1/imports/import-grouping/imports.ts diff --git a/test/etc/workspace_1/imports/import-manager-file.ts b/test/etc/workspace_1/imports/import-manager-file.ts new file mode 100644 index 0000000..f293c7b --- /dev/null +++ b/test/etc/workspace_1/imports/import-manager-file.ts @@ -0,0 +1,5 @@ +import { Class1 } from '../server/indices'; + +export class MyCoding { + constructor(private class1: Class1) { } +} diff --git a/test/_old/_workspace/extension/managers/ImportManagerFile.tsx b/test/etc/workspace_1/imports/import-manager-file.tsx similarity index 64% rename from test/_old/_workspace/extension/managers/ImportManagerFile.tsx rename to test/etc/workspace_1/imports/import-manager-file.tsx index a491196..6c2a84f 100644 --- a/test/_old/_workspace/extension/managers/ImportManagerFile.tsx +++ b/test/etc/workspace_1/imports/import-manager-file.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; export function doSomething(): any { - return ( -
- ); + return ( +
+ ); } diff --git a/test/_old/_workspace/extension/utilities/importsForSpecifierSort.ts b/test/etc/workspace_1/utilities/imports-for-specifier-sort.ts similarity index 100% rename from test/_old/_workspace/extension/utilities/importsForSpecifierSort.ts rename to test/etc/workspace_1/utilities/imports-for-specifier-sort.ts diff --git a/test/etc/workspace_2/declarations/declarations.ts b/test/etc/workspace_2/declarations/declarations.ts new file mode 100644 index 0000000..9093ae4 --- /dev/null +++ b/test/etc/workspace_2/declarations/declarations.ts @@ -0,0 +1 @@ +export class ClassDeclarationWorkspace2 { } diff --git a/test/etc/workspace_2/main.ts b/test/etc/workspace_2/main.ts deleted file mode 100644 index b6800e5..0000000 --- a/test/etc/workspace_2/main.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Foo } from './server/indices/foobar'; -import { Loggee } from './utilities/Logger'; -import winstonLogger, { Logger } from './utilities/Logger'; - -import iocSymbols from './ioc-symbols'; - -function foo() { - console.log(winstonLogger, Logger, Loggee, iocSymbols); -} - -Foo diff --git a/test/etc/workspace_3/declarations/declarations.ts b/test/etc/workspace_3/declarations/declarations.ts new file mode 100644 index 0000000..6d8fb3f --- /dev/null +++ b/test/etc/workspace_3/declarations/declarations.ts @@ -0,0 +1 @@ +export class ClassDeclarationWorkspace3 { } diff --git a/test/etc/workspace_3/main.ts b/test/etc/workspace_3/main.ts deleted file mode 100644 index b6800e5..0000000 --- a/test/etc/workspace_3/main.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Foo } from './server/indices/foobar'; -import { Loggee } from './utilities/Logger'; -import winstonLogger, { Logger } from './utilities/Logger'; - -import iocSymbols from './ioc-symbols'; - -function foo() { - console.log(winstonLogger, Logger, Loggee, iocSymbols); -} - -Foo diff --git a/test/etc/workspace_3/node_modules/@types/my-module/index.d.ts b/test/etc/workspace_3/node_modules/@types/my-module/index.d.ts new file mode 100644 index 0000000..886a932 --- /dev/null +++ b/test/etc/workspace_3/node_modules/@types/my-module/index.d.ts @@ -0,0 +1,3 @@ +declare namespace MyModuleFromTypes { + export interface InterfaceFromTypes { } +} diff --git a/test/etc/workspace_3/node_modules/node-module/index.d.ts b/test/etc/workspace_3/node_modules/node-module/index.d.ts new file mode 100644 index 0000000..bd309ed --- /dev/null +++ b/test/etc/workspace_3/node_modules/node-module/index.d.ts @@ -0,0 +1 @@ +export interface InterfaceFromNodeModules { } diff --git a/test/etc/workspace_3/package.json b/test/etc/workspace_3/package.json new file mode 100644 index 0000000..918fa4c --- /dev/null +++ b/test/etc/workspace_3/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "node-module": "*" + }, + "devDependencies": { + "@types/my-module": "*" + } +} diff --git a/test/tests/declarations/__snapshots__/workspace-declarations.multi.test.ts.snap b/test/tests/declarations/__snapshots__/workspace-declarations.multi.test.ts.snap new file mode 100644 index 0000000..0fee2c7 --- /dev/null +++ b/test/tests/declarations/__snapshots__/workspace-declarations.multi.test.ts.snap @@ -0,0 +1,77 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`WorkspaceDeclarations (multi root) should create declarations for different workspaces 1`] = ` +Array [ + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 43, + "isExported": true, + "methods": Array [], + "name": "ClassDeclarationWorkspace2", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/declarations", + }, +] +`; + +exports[`WorkspaceDeclarations (multi root) should create declarations for different workspaces 2`] = ` +Array [ + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 43, + "isExported": true, + "methods": Array [], + "name": "ClassDeclarationWorkspace3", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/declarations", + }, +] +`; + +exports[`WorkspaceDeclarations (multi root) should index correct types from @types 1`] = ` +Array [ + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 79, + "isExported": true, + "methods": Array [], + "name": "InterfaceFromTypes", + "properties": Array [], + "start": 40, + }, + "from": "MyModuleFromTypes", + }, + DeclarationInfo { + "declaration": ModuleDeclaration { + "end": 81, + "name": "mymodulefromtypes", + "start": 0, + }, + "from": "MyModuleFromTypes", + }, +] +`; + +exports[`WorkspaceDeclarations (multi root) should index correct types from node_modules 1`] = ` +Array [ + "node-module", +] +`; + +exports[`WorkspaceDeclarations (multi root) should return the correct files for different workspaces 1`] = ` +Array [ + "declarations.ts", +] +`; + +exports[`WorkspaceDeclarations (multi root) should return the correct files for different workspaces 2`] = ` +Array [ + "declarations.ts", +] +`; diff --git a/test/tests/declarations/__snapshots__/workspace-declarations.test.ts.snap b/test/tests/declarations/__snapshots__/workspace-declarations.test.ts.snap new file mode 100644 index 0000000..0722558 --- /dev/null +++ b/test/tests/declarations/__snapshots__/workspace-declarations.test.ts.snap @@ -0,0 +1,792 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`WorkspaceDeclarations should call reindex when a file has changed 1`] = ` +Array [ + Object { + "created": Array [], + "deleted": Array [], + "updated": Array [ + "./file-to-index.ts", + ], + }, +] +`; + +exports[`WorkspaceDeclarations should correctly move declarations for a barrel file 1`] = `Array []`; + +exports[`WorkspaceDeclarations should correctly move declarations for a barrel file 2`] = `Array []`; + +exports[`WorkspaceDeclarations should correctly move declarations for a barrel file 3`] = ` +Array [ + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 32, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel1", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 65, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel2", + "properties": Array [], + "start": 33, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 98, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel3", + "properties": Array [], + "start": 66, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 131, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel4", + "properties": Array [], + "start": 99, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 164, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel5", + "properties": Array [], + "start": 132, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": EnumDeclaration { + "end": 204, + "isExported": true, + "members": Array [], + "name": "EnumForBarrel", + "start": 175, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 205, + "isExported": true, + "methods": Array [], + "name": "InterfaceForBarrel1", + "properties": Array [], + "start": 165, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 246, + "isExported": true, + "methods": Array [], + "name": "InterfaceForBarrel2", + "properties": Array [], + "start": 206, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 287, + "isExported": true, + "methods": Array [], + "name": "InterfaceForBarrel3", + "properties": Array [], + "start": 247, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 34, + "isConst": true, + "isExported": true, + "name": "constForBarrel1", + "start": 0, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 69, + "isConst": true, + "isExported": true, + "name": "constForBarrel2", + "start": 35, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 104, + "isConst": true, + "isExported": true, + "name": "constForBarrel3", + "start": 70, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 139, + "isConst": true, + "isExported": true, + "name": "constForBarrel4", + "start": 105, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 174, + "isConst": true, + "isExported": true, + "name": "constForBarrel5", + "start": 140, + "type": undefined, + }, + "from": "/declarations/barrel", + }, +] +`; + +exports[`WorkspaceDeclarations should return the correct declarations for a file 1`] = ` +Array [ + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 224, + "isExported": true, + "methods": Array [ + MethodDeclaration { + "end": 191, + "isAbstract": false, + "name": "aMethod", + "parameters": Array [ + ParameterDeclaration { + "end": 159, + "name": "str", + "start": 148, + "type": "string", + }, + ], + "start": 130, + "type": "T", + "variables": Array [], + "visibility": 2, + }, + MethodDeclaration { + "end": 222, + "isAbstract": false, + "name": "bMethod", + "parameters": Array [], + "start": 195, + "type": "void", + "variables": Array [], + "visibility": 0, + }, + ], + "name": "Class", + "properties": Array [ + PropertyDeclaration { + "end": 126, + "name": "prop", + "start": 106, + "type": "string", + "visibility": 2, + }, + ], + "start": 83, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": EnumDeclaration { + "end": 333, + "isExported": true, + "members": Array [ + "a", + "b", + "c", + ], + "name": "Enum", + "start": 298, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 81, + "isExported": true, + "methods": Array [ + MethodDeclaration { + "end": 47, + "isAbstract": true, + "name": "method1", + "parameters": Array [], + "start": 31, + "type": "void", + "variables": Array [], + "visibility": 2, + }, + MethodDeclaration { + "end": 79, + "isAbstract": true, + "name": "method2", + "parameters": Array [ + ParameterDeclaration { + "end": 69, + "name": "str", + "start": 58, + "type": "string", + }, + ], + "start": 50, + "type": "number", + "variables": Array [], + "visibility": 2, + }, + ], + "name": "Interface", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 296, + "isConst": true, + "isExported": true, + "name": "exportedConstant", + "start": 261, + "type": undefined, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 259, + "isConst": false, + "isExported": true, + "name": "exportedVariable", + "start": 226, + "type": undefined, + }, + "from": "/declarations/multi-declarations", + }, +] +`; + +exports[`WorkspaceDeclarations should return the correct declarations for a workspace 1`] = ` +Array [ + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 224, + "isExported": true, + "methods": Array [ + MethodDeclaration { + "end": 191, + "isAbstract": false, + "name": "aMethod", + "parameters": Array [ + ParameterDeclaration { + "end": 159, + "name": "str", + "start": 148, + "type": "string", + }, + ], + "start": 130, + "type": "T", + "variables": Array [], + "visibility": 2, + }, + MethodDeclaration { + "end": 222, + "isAbstract": false, + "name": "bMethod", + "parameters": Array [], + "start": 195, + "type": "void", + "variables": Array [], + "visibility": 0, + }, + ], + "name": "Class", + "properties": Array [ + PropertyDeclaration { + "end": 126, + "name": "prop", + "start": 106, + "type": "string", + "visibility": 2, + }, + ], + "start": 83, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 32, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel1", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 65, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel2", + "properties": Array [], + "start": 33, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 98, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel3", + "properties": Array [], + "start": 66, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 131, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel4", + "properties": Array [], + "start": 99, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 164, + "isExported": true, + "methods": Array [], + "name": "ClassForBarrel5", + "properties": Array [], + "start": 132, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 31, + "isExported": true, + "methods": Array [], + "name": "ClassForIndex1", + "properties": Array [], + "start": 0, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 63, + "isExported": true, + "methods": Array [], + "name": "ClassForIndex2", + "properties": Array [], + "start": 32, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 95, + "isExported": true, + "methods": Array [], + "name": "ClassForIndex3", + "properties": Array [], + "start": 64, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 127, + "isExported": true, + "methods": Array [], + "name": "ClassForIndex4", + "properties": Array [], + "start": 96, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 159, + "isExported": true, + "methods": Array [], + "name": "ClassForIndex5", + "properties": Array [], + "start": 128, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": 72, + "isExported": true, + "methods": Array [], + "name": "ClassInIndex", + "properties": Array [], + "start": 43, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": DefaultDeclaration { + "end": undefined, + "isExported": true, + "name": "DefaultExportedClass", + "resource": File { + "declarations": Array [ + [Circular], + ], + "end": 46, + "exports": Array [], + "imports": Array [], + "resources": Array [], + "start": 0, + "usages": Array [], + }, + "start": undefined, + }, + "from": "/declarations/default-export", + }, + DeclarationInfo { + "declaration": DefaultDeclaration { + "end": undefined, + "isExported": true, + "name": "DefaultMultiExport", + "resource": File { + "declarations": Array [ + InterfaceDeclaration { + "end": 50, + "isExported": true, + "methods": Array [], + "name": "InterfaceInDefaultMultiExport", + "properties": Array [], + "start": 0, + }, + [Circular], + ], + "end": 95, + "exports": Array [], + "imports": Array [], + "resources": Array [], + "start": 0, + "usages": Array [], + }, + "start": undefined, + }, + "from": "/declarations/default-multi-export", + }, + DeclarationInfo { + "declaration": EnumDeclaration { + "end": 333, + "isExported": true, + "members": Array [ + "a", + "b", + "c", + ], + "name": "Enum", + "start": 298, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": EnumDeclaration { + "end": 204, + "isExported": true, + "members": Array [], + "name": "EnumForBarrel", + "start": 175, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 81, + "isExported": true, + "methods": Array [ + MethodDeclaration { + "end": 47, + "isAbstract": true, + "name": "method1", + "parameters": Array [], + "start": 31, + "type": "void", + "variables": Array [], + "visibility": 2, + }, + MethodDeclaration { + "end": 79, + "isAbstract": true, + "name": "method2", + "parameters": Array [ + ParameterDeclaration { + "end": 69, + "name": "str", + "start": 58, + "type": "string", + }, + ], + "start": 50, + "type": "number", + "variables": Array [], + "visibility": 2, + }, + ], + "name": "Interface", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 205, + "isExported": true, + "methods": Array [], + "name": "InterfaceForBarrel1", + "properties": Array [], + "start": 165, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 246, + "isExported": true, + "methods": Array [], + "name": "InterfaceForBarrel2", + "properties": Array [], + "start": 206, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 287, + "isExported": true, + "methods": Array [], + "name": "InterfaceForBarrel3", + "properties": Array [], + "start": 247, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 199, + "isExported": true, + "methods": Array [], + "name": "InterfaceForIndex1", + "properties": Array [], + "start": 160, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 239, + "isExported": true, + "methods": Array [], + "name": "InterfaceForIndex2", + "properties": Array [], + "start": 200, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 279, + "isExported": true, + "methods": Array [], + "name": "InterfaceForIndex3", + "properties": Array [], + "start": 240, + }, + "from": "/declarations", + }, + DeclarationInfo { + "declaration": InterfaceDeclaration { + "end": 50, + "isExported": true, + "methods": Array [], + "name": "InterfaceInDefaultMultiExport", + "properties": Array [], + "start": 0, + }, + "from": "/declarations/default-multi-export", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 34, + "isConst": true, + "isExported": true, + "name": "constForBarrel1", + "start": 0, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 69, + "isConst": true, + "isExported": true, + "name": "constForBarrel2", + "start": 35, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 104, + "isConst": true, + "isExported": true, + "name": "constForBarrel3", + "start": 70, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 139, + "isConst": true, + "isExported": true, + "name": "constForBarrel4", + "start": 105, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 174, + "isConst": true, + "isExported": true, + "name": "constForBarrel5", + "start": 140, + "type": undefined, + }, + "from": "/declarations/barrel", + }, + DeclarationInfo { + "declaration": DefaultDeclaration { + "end": undefined, + "isExported": true, + "name": "default-unnamed-export", + "resource": File { + "declarations": Array [ + [Circular], + ], + "end": 25, + "exports": Array [], + "imports": Array [], + "resources": Array [], + "start": 0, + "usages": Array [], + }, + "start": undefined, + }, + "from": "/declarations/default-unnamed-export", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 296, + "isConst": true, + "isExported": true, + "name": "exportedConstant", + "start": 261, + "type": undefined, + }, + "from": "/declarations/multi-declarations", + }, + DeclarationInfo { + "declaration": VariableDeclaration { + "end": 259, + "isConst": false, + "isExported": true, + "name": "exportedVariable", + "start": 226, + "type": undefined, + }, + "from": "/declarations/multi-declarations", + }, +] +`; + +exports[`WorkspaceDeclarations should return the correct files 1`] = ` +Array [ + "barrel.ts", + "declarations-for-barrel-1.ts", + "declarations-for-barrel-2.ts", + "declarations-for-index.ts", + "default-export.ts", + "default-multi-export.ts", + "default-unnamed-export.ts", + "index.ts", + "multi-declarations.ts", +] +`; diff --git a/test/tests/declarations/declaration-manager.multi.test.ts b/test/tests/declarations/declaration-manager.multi.test.ts new file mode 100644 index 0000000..1c8d6ae --- /dev/null +++ b/test/tests/declarations/declaration-manager.multi.test.ts @@ -0,0 +1,71 @@ +import { join } from 'path'; +import sinon = require('sinon'); +import { ExtensionContext, Uri, workspace } from 'vscode'; + +import DeclarationManager from '../../../src/declarations/declaration-manager'; +import WorkspaceDeclarations from '../../../src/declarations/workspace-declarations'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { Logger } from '../../../src/utilities/logger'; +import { expect } from '../setup'; + +describe('DeclarationManager (multi root)', () => { + + const folders = { + 1: workspace.workspaceFolders![0], + 2: workspace.workspaceFolders![1], + 3: workspace.workspaceFolders![2], + }; + let context: ExtensionContext; + let manager: DeclarationManager; + + beforeEach(() => { + const logger = ioc.get(iocSymbols.logger); + context = { + subscriptions: [], + } as any as ExtensionContext; + manager = new DeclarationManager(context, logger); + }); + + afterEach(() => { + manager.dispose(); + for (const disposable of context.subscriptions) { + disposable.dispose(); + } + }); + + it('should create a status bar item', () => { + expect((manager as any).statusBarItem).not.to.exist; + manager.setup(); + expect((manager as any).statusBarItem).to.exist; + }); + + it('should create a workspace for each workspace folder', () => { + const spy = sinon.spy(manager as any, 'createWorkspace'); + manager.setup(); + + expect(spy.callCount).to.equal(3); + }); + + it('should return the index for a file', async () => { + const d1 = new WorkspaceDeclarations(folders['1']); + const d2 = new WorkspaceDeclarations(folders['2']); + await d1.initialize(); + await d2.initialize(); + + (manager as any).workspaces[folders['1'].uri.fsPath] = d1; + (manager as any).workspaces[folders['2'].uri.fsPath] = d2; + const f1 = Uri.file(join(folders['1'].uri.fsPath, 'declarations', 'index.ts')); + const f2 = Uri.file(join(folders['2'].uri.fsPath, 'declarations', 'declarations.ts')); + + expect(manager.getIndexForFile(f1)).to.equal(d1.index); + expect(manager.getIndexForFile(f2)).to.equal(d2.index); + }); + + it('should return undefined for a non found file', async () => { + const file = Uri.file(join(folders['1'].uri.fsPath, 'declarations', 'notfoundfile.ts')); + + expect(manager.getIndexForFile(file)).not.to.exist; + }); + +}); diff --git a/test/tests/declarations/declaration-manager.single.test.ts b/test/tests/declarations/declaration-manager.single.test.ts new file mode 100644 index 0000000..56d4fd5 --- /dev/null +++ b/test/tests/declarations/declaration-manager.single.test.ts @@ -0,0 +1,153 @@ +import { join } from 'path'; +import sinon = require('sinon'); +import { ExtensionContext, Uri, workspace, WorkspaceFoldersChangeEvent } from 'vscode'; + +import DeclarationManager from '../../../src/declarations/declaration-manager'; +import WorkspaceDeclarations, { WorkspaceDeclarationsState } from '../../../src/declarations/workspace-declarations'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { Logger } from '../../../src/utilities/logger'; +import { expect } from '../setup'; + +describe('DeclarationManager (single root)', () => { + + const folder = workspace.workspaceFolders![0]; + let context: ExtensionContext; + let manager: DeclarationManager; + + beforeEach(() => { + const logger = ioc.get(iocSymbols.logger); + context = { + subscriptions: [], + } as any as ExtensionContext; + manager = new DeclarationManager(context, logger); + }); + + afterEach(() => { + manager.dispose(); + for (const disposable of context.subscriptions) { + disposable.dispose(); + } + }); + + it('should create a status bar item', () => { + expect((manager as any).statusBarItem).not.to.exist; + manager.setup(); + expect((manager as any).statusBarItem).to.exist; + }); + + it('should create a workspace for each workspace folder', () => { + const spy = sinon.spy(manager as any, 'createWorkspace'); + manager.setup(); + + expect(spy.callCount).to.equal(1); + }); + + it('should return the index for a file', async () => { + const declarations = new WorkspaceDeclarations(folder); + await declarations.initialize(); + + (manager as any).workspaces[folder.uri.fsPath] = declarations; + const file = Uri.file(join(folder.uri.fsPath, 'declarations', 'index.ts')); + + expect(manager.getIndexForFile(file)).to.equal(declarations.index); + }); + + it('should return undefined for a non found file', async () => { + const file = Uri.file(join(folder.uri.fsPath, 'declarations', 'notfoundfile.ts')); + + expect(manager.getIndexForFile(file)).not.to.exist; + }); + + it('should add a new workspace on a changed event', () => { + const stub = sinon.stub(manager as any, 'createWorkspace'); + stub.returns(Promise.resolve()); + + const event = { + added: [ + { + index: 1, + name: 'newWorkspace', + uri: Uri.file(''), + }, + ], + removed: [], + } as WorkspaceFoldersChangeEvent; + (manager as any).workspaceFoldersChanged(event); + expect(stub.callCount).to.equal(1); + }); + + it('should remove a workspace on a changed event', async () => { + const declarations = new WorkspaceDeclarations(folder); + await declarations.initialize(); + (manager as any).workspaces[folder.uri.fsPath] = declarations; + + const stub = sinon.stub(manager as any, 'createWorkspace'); + stub.returns(Promise.resolve()); + const spy = sinon.spy(declarations, 'dispose'); + + const event = { + added: [], + removed: [folder], + } as WorkspaceFoldersChangeEvent; + (manager as any).workspaceFoldersChanged(event); + expect(stub.callCount).to.equal(0); + expect(spy.callCount).to.equal(1); + }); + + it('should set the state to syncing when a workspace starts syncing', () => { + sinon.stub(manager as any, 'createWorkspace').returns(Promise.resolve()); + manager.setup(); + expect((manager as any).activeWorkspaces).to.equal(0); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + expect((manager as any).activeWorkspaces).to.equal(1); + expect((manager as any).statusBarItem.text).to.equal('TSH Resolver $(sync)'); + }); + + it('should set the state to ok when all workspaces are finished', () => { + sinon.stub(manager as any, 'createWorkspace').returns(Promise.resolve()); + manager.setup(); + expect((manager as any).activeWorkspaces).to.equal(0); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + expect((manager as any).activeWorkspaces).to.equal(2); + expect((manager as any).statusBarItem.text).to.equal('TSH Resolver $(sync)'); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Idle); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Idle); + expect((manager as any).activeWorkspaces).to.equal(0); + expect((manager as any).statusBarItem.text).to.equal('TSH Resolver $(check)'); + }); + + it('should set the state to error when one workspace errors', () => { + sinon.stub(manager as any, 'createWorkspace').returns(Promise.resolve()); + const stub = sinon.stub((manager as any).logger, 'error').returns(() => { }); + try { + manager.setup(); + expect((manager as any).activeWorkspaces).to.equal(0); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + expect((manager as any).activeWorkspaces).to.equal(1); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Error); + expect((manager as any).statusBarItem.text).to.equal('TSH Resolver $(flame)'); + } finally { + stub.restore(); + } + }); + + it('should not change the state away from error on other events', () => { + sinon.stub(manager as any, 'createWorkspace').returns(Promise.resolve()); + const stub = sinon.stub((manager as any).logger, 'error').returns(() => { }); + try { + manager.setup(); + expect((manager as any).activeWorkspaces).to.equal(0); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + expect((manager as any).activeWorkspaces).to.equal(1); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Error); + expect((manager as any).statusBarItem.text).to.equal('TSH Resolver $(flame)'); + (manager as any).workspaceStateChanged(WorkspaceDeclarationsState.Syncing); + expect((manager as any).statusBarItem.text).to.equal('TSH Resolver $(flame)'); + } finally { + stub.restore(); + } + }); + +}); diff --git a/test/tests/declarations/workspace-declarations.multi.test.ts b/test/tests/declarations/workspace-declarations.multi.test.ts new file mode 100644 index 0000000..8c367cf --- /dev/null +++ b/test/tests/declarations/workspace-declarations.multi.test.ts @@ -0,0 +1,67 @@ +import { parse, sep } from 'path'; +import { workspace } from 'vscode'; + +import WorkspaceDeclarations from '../../../src/declarations/workspace-declarations'; +import { expect } from '../setup'; + +describe('WorkspaceDeclarations (multi root)', () => { + + const folder2 = workspace.workspaceFolders![1]; + const folder3 = workspace.workspaceFolders![2]; + + it('should create declarations for different workspaces', async () => { + const w1 = new WorkspaceDeclarations(folder2); + const w2 = new WorkspaceDeclarations(folder3); + + await w1.initialize(); + await w2.initialize(); + + const d1 = w1.index.declarationInfos.filter(d => d.from.startsWith('/declarations')); + const d2 = w2.index.declarationInfos.filter(d => d.from.startsWith('/declarations')); + + expect(d1).to.matchSnapshot(); + expect(d2).to.matchSnapshot(); + }); + + it('should return the correct files for different workspaces', async () => { + const w1 = new WorkspaceDeclarations(folder2); + const w2 = new WorkspaceDeclarations(folder3); + + const f1 = await (w1 as any).findFiles() as string[]; + const f2 = await (w2 as any).findFiles() as string[]; + + const d1 = f1 + .filter(file => file.indexOf(`workspace_2${sep}declarations`) >= 0) + .map(file => parse(file).base) + .sort(); + const d2 = f2 + .filter(file => file.indexOf(`workspace_3${sep}declarations`) >= 0) + .map(file => parse(file).base) + .sort(); + + expect(d1).to.matchSnapshot(); + expect(d2).to.matchSnapshot(); + }); + + it('should index correct types from node_modules', async () => { + const workspaceDeclarations = new WorkspaceDeclarations(folder3); + await workspaceDeclarations.initialize(); + + const declarations = workspaceDeclarations.index.declarationInfos + .filter(d => d.from === 'node-module') + .map(d => d.from); + + expect(declarations).to.matchSnapshot(); + }); + + it('should index correct types from @types', async () => { + const workspaceDeclarations = new WorkspaceDeclarations(folder3); + await workspaceDeclarations.initialize(); + + const declarations = workspaceDeclarations.index.declarationInfos + .filter(d => d.from === 'MyModuleFromTypes'); + + expect(declarations).to.matchSnapshot(); + }); + +}); diff --git a/test/tests/declarations/workspace-declarations.test.ts b/test/tests/declarations/workspace-declarations.test.ts new file mode 100644 index 0000000..26055aa --- /dev/null +++ b/test/tests/declarations/workspace-declarations.test.ts @@ -0,0 +1,184 @@ +import { parse, sep } from 'path'; +import * as sinon from 'sinon'; +import { DefaultDeclaration, File } from 'typescript-parser'; +import { workspace } from 'vscode'; + +import Configuration from '../../../src/configuration'; +import WorkspaceDeclarations, { WorkspaceDeclarationsState } from '../../../src/declarations/workspace-declarations'; +import { expect, wait } from '../setup'; + +describe('WorkspaceDeclarations', () => { + + const folder = workspace.workspaceFolders![0]; + let workspaceDeclarations: WorkspaceDeclarations; + + beforeEach(() => { + workspaceDeclarations = new WorkspaceDeclarations(folder); + }); + + afterEach(() => { + if (workspaceDeclarations) { + workspaceDeclarations.dispose(); + } + }); + + it('should create an object', () => { + expect(new WorkspaceDeclarations(folder)).to.exist; + }); + + it('should return the correct files', async () => { + const files = await (workspaceDeclarations as any).findFiles() as string[]; + const declarationFiles = files + .filter(file => file.indexOf(`workspace_1${sep}declarations`) >= 0) + .map(file => parse(file).base) + .sort(); + + expect(declarationFiles).to.matchSnapshot(); + }); + + it('should not add non ts files', async () => { + const files = await (workspaceDeclarations as any).findFiles() as string[]; + const declarationFiles = files + .filter(file => file.indexOf(`workspace_1${sep}declarations`) >= 0) + .map(file => parse(file).ext); + + for (const ext of declarationFiles) { + expect(ext).to.equal('.ts'); + } + }); + + it('should initialize an index', async () => { + expect(workspaceDeclarations.index).not.to.exist; + await workspaceDeclarations.initialize(); + expect(workspaceDeclarations.index).to.exist; + expect(workspaceDeclarations.index.indexReady).to.equal(true); + }); + + it('should call syncing event', async () => { + const spy = sinon.spy(); + workspaceDeclarations.workspaceStateChanged(spy); + await workspaceDeclarations.initialize(); + expect(spy.getCall(0).args[0]).to.equal(WorkspaceDeclarationsState.Syncing); + }); + + it('should call idle event on finished sync', async () => { + const spy = sinon.spy(); + workspaceDeclarations.workspaceStateChanged(spy); + await workspaceDeclarations.initialize(); + expect(spy.getCall(1).args[0]).to.equal(WorkspaceDeclarationsState.Idle); + }); + + it('should call reindex when a file has changed', async () => { + await workspaceDeclarations.initialize(); + const eventSpy = sinon.spy(); + const reindexSpy = sinon.stub(workspaceDeclarations.index, 'reindexForChanges'); + reindexSpy.returns(Promise.resolve()); + workspaceDeclarations.workspaceStateChanged(eventSpy); + + expect(eventSpy.callCount).to.equal(0); + (workspaceDeclarations as any).fileWatcherEvent( + 'updated', + { fsPath: './file-to-index.ts' }, + ); + await wait(550); + expect(eventSpy.callCount).to.equal(2); + expect(reindexSpy.getCall(0).args).to.matchSnapshot(); + }); + + it('should return the correct declarations for a workspace', async () => { + await workspaceDeclarations.initialize(); + + const declarations = workspaceDeclarations.index.declarationInfos.filter(d => d.from.startsWith('/declarations')); + for (const d of declarations) { + if (d.declaration instanceof DefaultDeclaration) { + delete ((d.declaration as any).resource as File).filePath; + delete (d.declaration as any).resource.rootPath; + } + } + expect(declarations).to.matchSnapshot(); + }); + + it('should return the correct declarations for a file', async () => { + await workspaceDeclarations.initialize(); + + const declarations = workspaceDeclarations + .index + .declarationInfos + .filter(d => d.from.startsWith('/declarations/multi-declarations')); + + expect(declarations).to.matchSnapshot(); + }); + + it('should correctly move declarations for a barrel file', async () => { + await workspaceDeclarations.initialize(); + + const declarations1 = workspaceDeclarations + .index + .declarationInfos + .filter(d => d.from.startsWith('/declarations/declarations-for-barrel-1')); + const declarations2 = workspaceDeclarations + .index + .declarationInfos + .filter(d => d.from.startsWith('/declarations/declarations-for-barrel-2')); + const barrel = workspaceDeclarations + .index + .declarationInfos + .filter(d => d.from.startsWith('/declarations/barrel')); + + expect(declarations1).to.matchSnapshot(); + expect(declarations2).to.matchSnapshot(); + expect(barrel).to.matchSnapshot(); + }); + + it('should correctly remove trailing /index from location', async () => { + await workspaceDeclarations.initialize(); + + expect( + workspaceDeclarations.index.declarationInfos + .filter(d => d.from.startsWith('/declarations')) + .map(d => d.from) + .every(from => from.indexOf('/index') === -1), + ).to.equal(true); + }); + + it('should correctly ignore workspace files that are ignored by config', async () => { + await workspaceDeclarations.initialize(); + + const declarations = workspaceDeclarations.index.declarationInfos + .filter(d => d.from.startsWith('/declarations')) + .map(d => d.from); + expect( + declarations.every(from => from.indexOf('build') === -1), + ).to.equal(true); + }); + + it('should correctly add workspace files that are not ignored by config anymore', async () => { + Object.defineProperty( + workspaceDeclarations, + 'config', + { + get(): Configuration { + return { + index: { + moduleIgnorePatterns(): string[] { + return []; + }, + workspaceIgnorePatterns(): string[] { + return []; + }, + }, + } as any as Configuration; + }, + }, + ); + await workspaceDeclarations.initialize(); + + const declarations = workspaceDeclarations.index.declarationInfos + .filter(d => d.from.startsWith('/declarations')) + .map(d => d.from); + expect( + declarations.some(from => from.indexOf('build-file') >= 0), + ).to.equal(true); + }); + +}); diff --git a/test/tests/imports/__snapshots__/import-manager.test.ts.snap b/test/tests/imports/__snapshots__/import-manager.test.ts.snap new file mode 100644 index 0000000..c4f620d --- /dev/null +++ b/test/tests/imports/__snapshots__/import-manager.test.ts.snap @@ -0,0 +1,480 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportManager Typescript Constructor (via provider) should add an import proxy for a default import 1`] = ` +Array [ + NamedImport { + "defaultAlias": "myDefaultExportedFunction", + "end": 84, + "libraryName": "../defaultExport/lateDefaultExportedElement", + "specifiers": Array [], + "start": 0, + }, +] +`; + +exports[`ImportManager Typescript Constructor (via provider) should add an import proxy for a named import 1`] = ` +Array [ + NamedImport { + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, +] +`; + +exports[`ImportManager Typescript Constructor (via provider) should add multiple import proxies 1`] = ` +Array [ + NamedImport { + "defaultAlias": "myDefaultExportedFunction", + "end": 84, + "libraryName": "../defaultExport/lateDefaultExportedElement", + "specifiers": Array [], + "start": 0, + }, + NamedImport { + "end": 128, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 85, + }, +] +`; + +exports[`ImportManager Typescript Constructor (via provider) should not add a proxy for a namespace import 1`] = ` +Array [ + NamespaceImport { + "alias": "bodyParser", + "end": 42, + "libraryName": "body-parser", + "start": 0, + }, +] +`; + +exports[`ImportManager Typescript Constructor (via provider) should not add a proxy for a string import 1`] = ` +Array [ + StringImport { + "end": 21, + "libraryName": "body-parser", + "start": 0, + }, +] +`; + +exports[`ImportManager Typescript Constructor (via provider) should not add a proxy for an external import 1`] = ` +Array [ + ExternalModuleImport { + "alias": "bodyParser", + "end": 43, + "libraryName": "body-parser", + "start": 0, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should add a default import to the import index. 1`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "defaultAlias": "defaultdeclaration", + "end": undefined, + "libraryName": "../lib", + "specifiers": Array [], + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should add a module import to the import index 1`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamespaceImport { + "alias": "module", + "end": undefined, + "libraryName": "my-module", + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should add a normal import to a group 1`] = ` +KeywordImportGroup { + "imports": Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + ], + "keyword": 2, + "order": "asc", +} +`; + +exports[`ImportManager Typescript addDeclarationImport() should add a normal import to a group 2`] = ` +KeywordImportGroup { + "imports": Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class", + }, + ], + "start": undefined, + }, + ], + "keyword": 2, + "order": "asc", +} +`; + +exports[`ImportManager Typescript addDeclarationImport() should add a normal import to the document 1`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "classdeclaration", + }, + ], + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should add an import to an existing import group 1`] = ` +KeywordImportGroup { + "imports": Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + ], + "keyword": 2, + "order": "asc", +} +`; + +exports[`ImportManager Typescript addDeclarationImport() should add an import to an existing import group 2`] = ` +KeywordImportGroup { + "imports": Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib1", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class", + }, + ], + "start": undefined, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib1", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class2", + }, + ], + "start": undefined, + }, + ], + "keyword": 2, + "order": "asc", +} +`; + +exports[`ImportManager Typescript addDeclarationImport() should add an import to an existing import index item 1`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib1", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class1", + }, + ], + "start": undefined, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib1", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class2", + }, + ], + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should add multiple imports to the import index 1`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib1", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class1", + }, + ], + "start": undefined, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib2", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class2", + }, + ], + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should not add the same specifier twice 1`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class", + }, + ], + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript addDeclarationImport() should not add the same specifier twice 2`] = ` +Array [ + NamedImport { + "defaultAlias": undefined, + "end": 43, + "libraryName": "../server/indices", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "Class1", + }, + ], + "start": 0, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class", + }, + ], + "start": undefined, + }, + NamedImport { + "end": undefined, + "libraryName": "../lib", + "specifiers": Array [ + SymbolSpecifier { + "alias": undefined, + "specifier": "class", + }, + ], + "start": undefined, + }, +] +`; + +exports[`ImportManager Typescript commit() should add a single default import to the document top 1`] = `"import defaultDeclaration from '../lib';"`; + +exports[`ImportManager Typescript commit() should add a single new import to the document top 1`] = `"import { importedclass } from '../imp';"`; + +exports[`ImportManager Typescript commit() should add a single new module import to the document top 1`] = `"import * as newModule from 'new-module';"`; + +exports[`ImportManager Typescript commit() should add a specifier to an existing import 1`] = `"import { Class1, class2 } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should add a specifier to an import and a new import 1`] = ` +"import { class3 } from '../server/not-indices'; +import { Class1, class2 } from '../server/indices'; +" +`; + +exports[`ImportManager Typescript commit() should add a specifier with a default (first) and a normal (second) import to the doc 1`] = `"import defaultExport, { defaultClass } from '../lib';"`; + +exports[`ImportManager Typescript commit() should add multiple specifier to an existing import 1`] = `"import { Class1, class2, class3 } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should add three new imports to the document top 1`] = ` +"import { newClass } from '../lib'; +import { secondnewClass } from '../not-same-lib'; +import { thirdnewClass } from '../not-same-lib-again'; +" +`; + +exports[`ImportManager Typescript commit() should add two new imports to the document top 1`] = ` +"import { newClass } from '../lib'; +import { secondnewClass } from '../not-same-lib'; +" +`; + +exports[`ImportManager Typescript commit() should convert a default import when a normal specifier is added 1`] = `"import defaultExport, { Class1 } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should convert a default import when a normal specifier is added 2`] = `"import defaultExport, { Class1, defaultClass } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should convert a normal import when a default specifier is added 1`] = `"import { Class1, defaultClass } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should convert a normal import when a default specifier is added 2`] = `"import defaultExport, { Class1, defaultClass } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should render sorted imports when optimizing 1`] = ` +"import { Class1 } from '../server/indices'; +import { MultiExportClass } from '../server/indices/defaultExport/multiExport'; +" +`; + +exports[`ImportManager Typescript commit() should render sorted specifiers when optimizing 1`] = `"import { Class1, Class2 } from '../server/indices';"`; + +exports[`ImportManager Typescript commit() should render the optimized import 1`] = ` +"import { SomeOtherClass } from '../server/not-indices'; +import { Class1, Class2 } from '../server/indices'; +" +`; + +exports[`ImportManager Typescript commit() should render the optimized import 2`] = ` +"import { Class1, Class2 } from '../server/indices'; + +" +`; diff --git a/test/tests/imports/__snapshots__/import-quick-pick-item.test.ts.snap b/test/tests/imports/__snapshots__/import-quick-pick-item.test.ts.snap new file mode 100644 index 0000000..7714633 --- /dev/null +++ b/test/tests/imports/__snapshots__/import-quick-pick-item.test.ts.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportQuickPickItem should contain the declaration info 1`] = ` +Object { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": undefined, + "isExported": true, + "methods": Array [], + "name": "class", + "properties": Array [], + "start": undefined, + }, + "from": "/server/indices", +} +`; + +exports[`ImportQuickPickItem should set the correct fields 1`] = ` +ImportQuickPickItem { + "declarationInfo": Object { + "declaration": ClassDeclaration { + "accessors": Array [], + "end": undefined, + "isExported": true, + "methods": Array [], + "name": "class", + "properties": Array [], + "start": undefined, + }, + "from": "/server/indices", + }, + "description": "/server/indices", + "label": "class", +} +`; diff --git a/test/tests/imports/import-appender.test.ts b/test/tests/imports/import-appender.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/tests/imports/import-grouping/__snapshots__/import-group-setting-parser.test.ts.snap b/test/tests/imports/import-grouping/__snapshots__/import-group-setting-parser.test.ts.snap new file mode 100644 index 0000000..8db1ac3 --- /dev/null +++ b/test/tests/imports/import-grouping/__snapshots__/import-group-setting-parser.test.ts.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportGroupSettingParser should parse a complex keyword pattern 1`] = ` +KeywordImportGroup { + "imports": Array [], + "keyword": 2, + "order": "desc", +} +`; + +exports[`ImportGroupSettingParser should parse a complex regex 1`] = ` +RegexImportGroup { + "imports": Array [], + "order": "asc", + "regex": "/(@angular|react)/core/(.*)/", +} +`; + +exports[`ImportGroupSettingParser should parse a complex regex pattern 1`] = ` +RegexImportGroup { + "imports": Array [], + "order": "desc", + "regex": "/foobar/", +} +`; + +exports[`ImportGroupSettingParser should parse a regex with "@" 1`] = ` +RegexImportGroup { + "imports": Array [], + "order": "asc", + "regex": "/@angular/", +} +`; + +exports[`ImportGroupSettingParser should parse a regex with "or" 1`] = ` +RegexImportGroup { + "imports": Array [], + "order": "asc", + "regex": "/angular|react/", +} +`; + +exports[`ImportGroupSettingParser should parse a simple keyword 1`] = ` +KeywordImportGroup { + "imports": Array [], + "keyword": 2, + "order": "asc", +} +`; + +exports[`ImportGroupSettingParser should parse a simple regex 1`] = ` +RegexImportGroup { + "imports": Array [], + "order": "asc", + "regex": "/foobar/", +} +`; diff --git a/test/tests/imports/import-grouping/__snapshots__/keyword-import-group.test.ts.snap b/test/tests/imports/import-grouping/__snapshots__/keyword-import-group.test.ts.snap new file mode 100644 index 0000000..e4c09b7 --- /dev/null +++ b/test/tests/imports/import-grouping/__snapshots__/keyword-import-group.test.ts.snap @@ -0,0 +1,70 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`KeywordImportGroup keyword "Modules" should correctly process a list of imports 1`] = ` +Array [ + false, + false, + false, + false, + true, + true, +] +`; + +exports[`KeywordImportGroup keyword "Modules" should generate the correct typescript (asc) 1`] = ` +"import { AnotherModuleFoo } from 'anotherLib'; +import { ModuleFoobar } from 'myLib'; +" +`; + +exports[`KeywordImportGroup keyword "Modules" should generate the correct typescript (desc) 1`] = ` +"import { ModuleFoobar } from 'myLib'; +import { AnotherModuleFoo } from 'anotherLib'; +" +`; + +exports[`KeywordImportGroup keyword "Plains" should correctly process a list of imports 1`] = ` +Array [ + true, + true, + false, + false, + false, + false, +] +`; + +exports[`KeywordImportGroup keyword "Plains" should generate the correct typescript (asc) 1`] = ` +"import './workspaceSideEffectLib'; +import 'sideEffectLib'; +" +`; + +exports[`KeywordImportGroup keyword "Plains" should generate the correct typescript (desc) 1`] = ` +"import 'sideEffectLib'; +import './workspaceSideEffectLib'; +" +`; + +exports[`KeywordImportGroup keyword "Workspace" should correctly process a list of imports 1`] = ` +Array [ + false, + false, + true, + true, + false, + false, +] +`; + +exports[`KeywordImportGroup keyword "Workspace" should generate the correct typescript (asc) 1`] = ` +"import { AnotherFoobar } from './anotherFile'; +import { Foobar } from './myFile'; +" +`; + +exports[`KeywordImportGroup keyword "Workspace" should generate the correct typescript (desc) 1`] = ` +"import { Foobar } from './myFile'; +import { AnotherFoobar } from './anotherFile'; +" +`; diff --git a/test/tests/imports/import-grouping/__snapshots__/regex-import-group.test.ts.snap b/test/tests/imports/import-grouping/__snapshots__/regex-import-group.test.ts.snap new file mode 100644 index 0000000..f0c80ec --- /dev/null +++ b/test/tests/imports/import-grouping/__snapshots__/regex-import-group.test.ts.snap @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RegexImportGroup should correctly process a list of imports 1`] = ` +Array [ + true, + true, + false, + false, + true, + true, +] +`; + +exports[`RegexImportGroup should generate the correct typescript (asc) 1`] = ` +"import './workspaceSideEffectLib'; +import 'sideEffectLib'; +import { AnotherModuleFoo } from 'anotherLib'; +import { ModuleFoobar } from 'myLib'; +" +`; + +exports[`RegexImportGroup should generate the correct typescript (desc) 1`] = ` +"import 'sideEffectLib'; +import './workspaceSideEffectLib'; +import { ModuleFoobar } from 'myLib'; +import { AnotherModuleFoo } from 'anotherLib'; +" +`; diff --git a/test/tests/imports/import-grouping/__snapshots__/remain-import-group.test.ts.snap b/test/tests/imports/import-grouping/__snapshots__/remain-import-group.test.ts.snap new file mode 100644 index 0000000..e4eb1a9 --- /dev/null +++ b/test/tests/imports/import-grouping/__snapshots__/remain-import-group.test.ts.snap @@ -0,0 +1,32 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RemainImportGroup should generate the correct typescript (asc) 1`] = ` +"import './workspaceSideEffectLib'; +import 'sideEffectLib'; +import { AnotherFoobar } from './anotherFile'; +import { Foobar } from './myFile'; +import { AnotherModuleFoo } from 'anotherLib'; +import { ModuleFoobar } from 'myLib'; +" +`; + +exports[`RemainImportGroup should generate the correct typescript (desc) 1`] = ` +"import 'sideEffectLib'; +import './workspaceSideEffectLib'; +import { ModuleFoobar } from 'myLib'; +import { AnotherModuleFoo } from 'anotherLib'; +import { Foobar } from './myFile'; +import { AnotherFoobar } from './anotherFile'; +" +`; + +exports[`RemainImportGroup should process all imports 1`] = ` +Array [ + true, + true, + true, + true, + true, + true, +] +`; diff --git a/test/tests/imports/import-grouping/import-group-setting-parser.test.ts b/test/tests/imports/import-grouping/import-group-setting-parser.test.ts new file mode 100644 index 0000000..d08f737 --- /dev/null +++ b/test/tests/imports/import-grouping/import-group-setting-parser.test.ts @@ -0,0 +1,65 @@ +import { + ImportGroupIdentifierInvalidError, + ImportGroupSettingParser, + KeywordImportGroup, + RegexImportGroup, +} from '../../../../src/imports/import-grouping'; +import { expect } from '../../setup'; + +describe('ImportGroupSettingParser', () => { + + it('should parse a simple keyword', () => { + const result = ImportGroupSettingParser.parseSetting('Workspace') as KeywordImportGroup; + + expect(result).to.matchSnapshot(); + }); + + it('should parse a simple regex', () => { + const result = ImportGroupSettingParser.parseSetting('/foobar/') as RegexImportGroup; + + expect(result).to.matchSnapshot(); + }); + + it('should parse a complex keyword pattern', () => { + const result = ImportGroupSettingParser.parseSetting({ + identifier: 'Workspace', + order: 'desc', + }) as KeywordImportGroup; + + expect(result).to.matchSnapshot(); + }); + + it('should parse a complex regex pattern', () => { + const result = ImportGroupSettingParser.parseSetting({ + identifier: '/foobar/', + order: 'desc', + }) as RegexImportGroup; + + expect(result).to.matchSnapshot(); + }); + + it('should throw on non found keyword and regex', () => { + const fn = () => ImportGroupSettingParser.parseSetting('whatever'); + + expect(fn).to.throw(ImportGroupIdentifierInvalidError); + }); + + it('should parse a regex with "or"', () => { + const result = ImportGroupSettingParser.parseSetting('/angular|react/'); + + expect(result).to.matchSnapshot(); + }); + + it('should parse a regex with "@"', () => { + const result = ImportGroupSettingParser.parseSetting('/@angular/'); + + expect(result).to.matchSnapshot(); + }); + + it('should parse a complex regex', () => { + const result = ImportGroupSettingParser.parseSetting('/(@angular|react)/core/(.*)/'); + + expect(result).to.matchSnapshot(); + }); + +}); diff --git a/test/tests/imports/import-grouping/keyword-import-group.test.ts b/test/tests/imports/import-grouping/keyword-import-group.test.ts new file mode 100644 index 0000000..6596c53 --- /dev/null +++ b/test/tests/imports/import-grouping/keyword-import-group.test.ts @@ -0,0 +1,177 @@ +import { join } from 'path'; +import { + File, + Generatable, + GENERATORS, + TypescriptCodeGenerator, + TypescriptGenerationOptions, + TypescriptParser, +} from 'typescript-parser'; +import { Uri, workspace } from 'vscode'; + +import { ImportGroupKeyword, KeywordImportGroup } from '../../../../src/imports/import-grouping'; +import ioc from '../../../../src/ioc'; +import iocSymbols, { TypescriptCodeGeneratorFactory } from '../../../../src/ioc-symbols'; +import { expect } from '../../setup'; + +describe('KeywordImportGroup', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const fsFile = Uri.file( + join(rootPath, 'imports', 'import-grouping', 'imports.ts'), + ); + let file: File; + let importGroup: KeywordImportGroup; + let generator: TypescriptCodeGenerator; + + before(() => { + if (!GENERATORS[KeywordImportGroup.name]) { + GENERATORS[KeywordImportGroup.name] = (generatable: Generatable, options: TypescriptGenerationOptions): string => { + const gen = new TypescriptCodeGenerator(options); + const group = generatable as KeywordImportGroup; + if (!group.imports.length) { + return ''; + } + return group.sortedImports + .map(imp => gen.generate(imp)) + .join('\n') + '\n'; + }; + } + }); + + before(async () => { + const parser = ioc.get(iocSymbols.parser); + generator = ioc.get(iocSymbols.generatorFactory)(fsFile); + file = await parser.parseFile(fsFile.fsPath, rootPath); + }); + + describe(`keyword "Modules"`, () => { + + beforeEach(() => { + importGroup = new KeywordImportGroup(ImportGroupKeyword.Modules); + }); + + it('should process a module import', () => { + expect(importGroup.processImport(file.imports[4])).to.be.true; + }); + + it('should not process a plain import', () => { + expect(importGroup.processImport(file.imports[0])).to.be.false; + }); + + it('should not process a workspace import', () => { + expect(importGroup.processImport(file.imports[2])).to.be.false; + }); + + it('should correctly process a list of imports', () => { + expect(file.imports.map(i => importGroup.processImport(i))).to.matchSnapshot(); + }); + + it('should generate the correct typescript (asc)', () => { + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + it('should generate the correct typescript (desc)', () => { + (importGroup as any).order = 'desc'; + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + }); + + describe(`keyword "Plains"`, () => { + + beforeEach(() => { + importGroup = new KeywordImportGroup(ImportGroupKeyword.Plains); + }); + + it('should not process a module import', () => { + expect(importGroup.processImport(file.imports[4])).to.be.false; + }); + + it('should process a plain import', () => { + expect(importGroup.processImport(file.imports[0])).to.be.true; + }); + + it('should not process a workspace import', () => { + expect(importGroup.processImport(file.imports[2])).to.be.false; + }); + + it('should correctly process a list of imports', () => { + expect(file.imports.map(i => importGroup.processImport(i))).to.matchSnapshot(); + }); + + it('should generate the correct typescript (asc)', () => { + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + it('should generate the correct typescript (desc)', () => { + (importGroup as any).order = 'desc'; + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + }); + + describe(`keyword "Workspace"`, () => { + + beforeEach(() => { + importGroup = new KeywordImportGroup(ImportGroupKeyword.Workspace); + }); + + it('should not process a module import', () => { + expect(importGroup.processImport(file.imports[4])).to.be.false; + }); + + it('should not process a plain import', () => { + expect(importGroup.processImport(file.imports[0])).to.be.false; + }); + + it('should process a workspace import', () => { + expect(importGroup.processImport(file.imports[2])).to.be.true; + }); + + it('should correctly process a list of imports', () => { + expect(file.imports.map(i => importGroup.processImport(i))).to.matchSnapshot(); + }); + + it('should generate the correct typescript (asc)', () => { + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + it('should generate the correct typescript (desc)', () => { + (importGroup as any).order = 'desc'; + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + }); + +}); diff --git a/test/tests/imports/import-grouping/regex-import-group.test.ts b/test/tests/imports/import-grouping/regex-import-group.test.ts new file mode 100644 index 0000000..6e690ce --- /dev/null +++ b/test/tests/imports/import-grouping/regex-import-group.test.ts @@ -0,0 +1,109 @@ +import { join } from 'path'; +import { + File, + Generatable, + GENERATORS, + NamedImport, + TypescriptCodeGenerator, + TypescriptGenerationOptions, + TypescriptParser, +} from 'typescript-parser'; +import { Uri, workspace } from 'vscode'; + +import { RegexImportGroup } from '../../../../src/imports/import-grouping'; +import ioc from '../../../../src/ioc'; +import iocSymbols, { TypescriptCodeGeneratorFactory } from '../../../../src/ioc-symbols'; +import { expect } from '../../setup'; + +describe('RegexImportGroup', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const fsFile = Uri.file( + join(rootPath, 'imports', 'import-grouping', 'imports.ts'), + ); + let file: File; + let importGroup: RegexImportGroup; + let generator: TypescriptCodeGenerator; + + before(() => { + if (!GENERATORS[RegexImportGroup.name]) { + GENERATORS[RegexImportGroup.name] = (generatable: Generatable, options: TypescriptGenerationOptions): string => { + const gen = new TypescriptCodeGenerator(options); + const group = generatable as RegexImportGroup; + if (!group.imports.length) { + return ''; + } + return group.sortedImports + .map(imp => gen.generate(imp)) + .join('\n') + '\n'; + }; + } + }); + + before(async () => { + const parser = ioc.get(iocSymbols.parser); + generator = ioc.get(iocSymbols.generatorFactory)(fsFile); + file = await parser.parseFile(fsFile.fsPath, rootPath); + }); + + beforeEach(() => { + importGroup = new RegexImportGroup(`/Lib/`); + }); + + it('should process a matching import', () => { + expect(importGroup.processImport(file.imports[0])).to.be.true; + }); + + it('should not process a not matching import', () => { + expect(importGroup.processImport(file.imports[2])).to.be.false; + }); + + it('should correctly process a list of imports', () => { + expect(file.imports.map(i => importGroup.processImport(i))).to.matchSnapshot(); + }); + + it('should generate the correct typescript (asc)', () => { + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + it('should generate the correct typescript (desc)', () => { + (importGroup as any).order = 'desc'; + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + it('should work with regex "or" conditions', () => { + const group = new RegexImportGroup('/angular|react/'); + const imp = new NamedImport('@angular'); + const imp2 = new NamedImport('@react/core'); + + expect(group.processImport(imp)).to.be.true; + expect(group.processImport(imp2)).to.be.true; + }); + + it('should work with regex containing an "@"', () => { + const group = new RegexImportGroup('/@angular/'); + const imp = new NamedImport('@angular'); + + expect(group.processImport(imp)).to.be.true; + }); + + it('should work with slash separated regex', () => { + const group = new RegexImportGroup('/@angular/http/'); + const imp = new NamedImport('@angular/http'); + const imp2 = new NamedImport('@angular/core/component'); + + expect(group.processImport(imp)).to.be.true; + expect(group.processImport(imp2)).to.be.false; + }); + +}); diff --git a/test/tests/imports/import-grouping/remain-import-group.test.ts b/test/tests/imports/import-grouping/remain-import-group.test.ts new file mode 100644 index 0000000..02ba376 --- /dev/null +++ b/test/tests/imports/import-grouping/remain-import-group.test.ts @@ -0,0 +1,75 @@ +import { join } from 'path'; +import { + File, + Generatable, + GENERATORS, + TypescriptCodeGenerator, + TypescriptGenerationOptions, + TypescriptParser, +} from 'typescript-parser'; +import { Uri, workspace } from 'vscode'; + +import { RemainImportGroup } from '../../../../src/imports/import-grouping'; +import ioc from '../../../../src/ioc'; +import iocSymbols, { TypescriptCodeGeneratorFactory } from '../../../../src/ioc-symbols'; +import { expect } from '../../setup'; + +describe('RemainImportGroup', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const fsFile = Uri.file( + join(rootPath, 'imports', 'import-grouping', 'imports.ts'), + ); + let file: File; + let importGroup: RemainImportGroup; + let generator: TypescriptCodeGenerator; + + before(() => { + if (!GENERATORS[RemainImportGroup.name]) { + GENERATORS[RemainImportGroup.name] = (generatable: Generatable, options: TypescriptGenerationOptions): string => { + const gen = new TypescriptCodeGenerator(options); + const group = generatable as RemainImportGroup; + if (!group.imports.length) { + return ''; + } + return group.sortedImports + .map(imp => gen.generate(imp)) + .join('\n') + '\n'; + }; + } + }); + + before(async () => { + const parser = ioc.get(iocSymbols.parser); + generator = ioc.get(iocSymbols.generatorFactory)(fsFile); + file = await parser.parseFile(fsFile.fsPath, rootPath); + }); + + beforeEach(() => { + importGroup = new RemainImportGroup(); + }); + + it('should process all imports', () => { + expect(file.imports.map(i => importGroup.processImport(i))).to.matchSnapshot(); + }); + + it('should generate the correct typescript (asc)', () => { + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + + it('should generate the correct typescript (desc)', () => { + (importGroup as any).order = 'desc'; + for (const imp of file.imports) { + if (importGroup.processImport(imp)) { + continue; + } + } + expect(generator.generate(importGroup as any)).to.matchSnapshot(); + }); + +}); diff --git a/test/tests/imports/import-manager.test.ts b/test/tests/imports/import-manager.test.ts new file mode 100644 index 0000000..5b8a85c --- /dev/null +++ b/test/tests/imports/import-manager.test.ts @@ -0,0 +1,448 @@ +import { join } from 'path'; +import { ClassDeclaration, DefaultDeclaration, File, ModuleDeclaration } from 'typescript-parser'; +import { Position, Range, TextDocument, Uri, window, workspace } from 'vscode'; + +import ImportManager from '../../../src/imports/import-manager'; +import ioc from '../../../src/ioc'; +import iocSymbols, { ImportManagerProvider } from '../../../src/ioc-symbols'; +import { expect, getDocumentText } from '../setup'; + +describe('ImportManager', () => { + + describe('Typescript', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const file = Uri.file(join(rootPath, 'imports', 'import-manager-file.ts')); + const provider: ImportManagerProvider = ioc.get(iocSymbols.importManager); + let document: TextDocument; + let documentText: string; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + + documentText = document.getText(); + }); + + afterEach(async () => { + await window.activeTextEditor!.edit((builder) => { + builder.delete(new Range( + new Position(0, 0), + document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, + )); + builder.insert(new Position(0, 0), documentText); + }); + + }); + + describe('Constructor (via provider)', () => { + + it('should create a document controller', async () => { + const ctrl = await provider(document); + + expect(ctrl).to.be.an.instanceof(ImportManager); + }); + + it('should parse the document', async () => { + const ctrl = await provider(document); + + expect((ctrl as any).parsedDocument).to.be.an.instanceof(File); + }); + + it('should add an import proxy for a named import', async () => { + const ctrl = await provider(document); + const imps = (ctrl as any).parsedDocument.imports; + + expect(imps).to.matchSnapshot(); + }); + + it('should add an import proxy for a default import', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.replace( + new Range( + new Position(0, 0), + new Position(1, 0), + ), + `import myDefaultExportedFunction from '../defaultExport/lateDefaultExportedElement';\n`, + ); + }); + + const ctrl = await provider(document); + const imps = (ctrl as any).parsedDocument.imports; + + expect(imps).to.matchSnapshot(); + }); + + it('should add multiple import proxies', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `import myDefaultExportedFunction from '../defaultExport/lateDefaultExportedElement';\n`, + ); + }); + + const ctrl = await provider(document); + const imps = (ctrl as any).parsedDocument.imports; + + expect(imps).to.matchSnapshot(); + }); + + it('should not add a proxy for a namespace import', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.replace( + new Range( + new Position(0, 0), + new Position(1, 0), + ), + `import * as bodyParser from 'body-parser';\n`, + ); + }); + + const ctrl = await provider(document); + const imps = (ctrl as any).parsedDocument.imports; + + expect(imps).to.matchSnapshot(); + }); + + it('should not add a proxy for an external import', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.replace( + new Range( + new Position(0, 0), + new Position(1, 0), + ), + `import bodyParser = require('body-parser');\n`, + ); + }); + + const ctrl = await provider(document); + const imps = (ctrl as any).parsedDocument.imports; + + expect(imps).to.matchSnapshot(); + }); + + it('should not add a proxy for a string import', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.replace( + new Range( + new Position(0, 0), + new Position(1, 0), + ), + `import 'body-parser';\n`, + ); + }); + + const ctrl = await provider(document); + const imps = (ctrl as any).parsedDocument.imports; + + expect(imps).to.matchSnapshot(); + }); + + }); + + describe('addDeclarationImport()', () => { + + it('should add a normal import to the document', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('classdeclaration', true); + ctrl.addDeclarationImport({ declaration, from: '../lib' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + }); + + it('should add a module import to the import index', async () => { + const ctrl = await provider(document); + const declaration = new ModuleDeclaration('module'); + ctrl.addDeclarationImport({ declaration, from: 'my-module' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + }); + + it('should add a default import to the import index.', async () => { + const ctrl = await provider(document); + + const declaration = new DefaultDeclaration('defaultdeclaration', new File('path', rootPath, 0, 1)); + ctrl.addDeclarationImport({ declaration, from: '../lib' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + }); + + it('should add multiple imports to the import index', async () => { + const ctrl = await provider(document); + const declarations = [ + new ClassDeclaration('class1', true), + new ClassDeclaration('class2', true), + ]; + ctrl + .addDeclarationImport({ declaration: declarations[0], from: '../lib1' }) + .addDeclarationImport({ declaration: declarations[1], from: '../lib2' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + }); + + it('should add an import to an existing import index item', async () => { + const ctrl = await provider(document); + const declarations = [ + new ClassDeclaration('class1', true), + new ClassDeclaration('class2', true), + ]; + + ctrl + .addDeclarationImport({ declaration: declarations[0], from: '../lib1' }) + .addDeclarationImport({ declaration: declarations[1], from: '../lib1' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + }); + + it('should not add the same specifier twice', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('class', true); + + ctrl.addDeclarationImport({ declaration, from: '../lib' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + + ctrl.addDeclarationImport({ declaration, from: '../lib' }); + + expect((ctrl as any).imports).to.matchSnapshot(); + }); + + it('should add a normal import to a group', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('class', true); + + expect((ctrl as any).importGroups[2]).to.matchSnapshot(); + + ctrl.addDeclarationImport({ declaration, from: '../lib' }); + + expect((ctrl as any).importGroups[2]).to.matchSnapshot(); + }); + + it('should add an import to an existing import group', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('class', true); + const declaration2 = new ClassDeclaration('class2', true); + + expect((ctrl as any).importGroups[2]).to.matchSnapshot(); + + ctrl + .addDeclarationImport({ declaration, from: '../lib1' }) + .addDeclarationImport({ declaration: declaration2, from: '../lib1' }); + + expect((ctrl as any).importGroups[2]).to.matchSnapshot(); + }); + + }); + + describe('organizeImports()', () => { + + it('should remove an unused import'); + + it('should remove an unused specifier'); + + it('should not remove an excluded library'); + + it('should merge two same libraries into one import'); + + }); + + describe('commit()', () => { + + it('should not touch anything if nothing changed', async () => { + const ctrl = await provider(document); + + await window.activeTextEditor!.edit((builder) => { + builder.replace( + document.lineAt(0).rangeIncludingLineBreak, + `import {Class1} from '../resourceIndex';`, + ); + }); + + expect(await ctrl.commit()).to.be.true; + expect(document.lineAt(0).text).to.equal(`import {Class1} from '../resourceIndex';`); + }); + + it('should add a single new import to the document top', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('importedclass', true); + ctrl.addDeclarationImport({ declaration, from: '../imp' }); + await ctrl.commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should add two new imports to the document top', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('newClass', true); + const declaration2 = new ClassDeclaration('secondnewClass', true); + + ctrl + .addDeclarationImport({ declaration, from: '../lib' }) + .addDeclarationImport({ declaration: declaration2, from: '../not-same-lib' }); + await ctrl.commit(); + + expect(getDocumentText(document, 0, 1)).to.matchSnapshot(); + }); + + it('should add three new imports to the document top', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('newClass', true); + const declaration2 = new ClassDeclaration('secondnewClass', true); + const declaration3 = new ClassDeclaration('thirdnewClass', true); + + ctrl + .addDeclarationImport({ declaration, from: '../lib' }) + .addDeclarationImport({ declaration: declaration2, from: '../not-same-lib' }) + .addDeclarationImport({ declaration: declaration3, from: '../not-same-lib-again' }); + await ctrl.commit(); + + expect(getDocumentText(document, 0, 2)).to.matchSnapshot(); + }); + + it('should add a single new module import to the document top', async () => { + const ctrl = await provider(document); + const declaration = new ModuleDeclaration('newModule'); + ctrl.addDeclarationImport({ declaration, from: 'new-module' }); + await ctrl.commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should add a single default import to the document top', async () => { + const ctrl = await provider(document); + const declaration = new DefaultDeclaration('defaultDeclaration', new File('file', rootPath, 1, 2)); + ctrl.addDeclarationImport({ declaration, from: '../lib' }); + await ctrl.commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should add a specifier to an existing import', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('class2', true); + ctrl.addDeclarationImport({ declaration, from: '/server/indices' }); + await ctrl.commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should add multiple specifier to an existing import', async () => { + const ctrl = await provider(document); + const declaration = new ClassDeclaration('class2', true); + const declaration2 = new ClassDeclaration('class3', true); + + await ctrl + .addDeclarationImport({ declaration, from: '/server/indices' }) + .addDeclarationImport({ declaration: declaration2, from: '/server/indices' }) + .commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should add a specifier with a default (first) and a normal (second) import to the doc', async () => { + const ctrl = await provider(document); + const def = new DefaultDeclaration('defaultExport', new File(file.fsPath, rootPath, 1, 2)); + const dec = new ClassDeclaration('defaultClass', true); + + await ctrl + .addDeclarationImport({ declaration: def, from: '/lib' }) + .addDeclarationImport({ declaration: dec, from: '/lib' }) + .commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should add a specifier to an import and a new import', async () => { + const ctrl = await provider(document); + const declaration1 = new ClassDeclaration('class2', true); + const declaration2 = new ClassDeclaration('class3', true); + + await ctrl + .addDeclarationImport({ declaration: declaration1, from: '/server/indices' }) + .addDeclarationImport({ declaration: declaration2, from: '/server/not-indices' }) + .commit(); + + expect(getDocumentText(document, 0, 1)).to.matchSnapshot(); + }); + + it('should convert a default import when a normal specifier is added', async () => { + const ctrl = await provider(document); + const def = new DefaultDeclaration('defaultExport', new File(file.fsPath, rootPath, 1, 2)); + const dec = new ClassDeclaration('defaultClass', true); + + await ctrl.addDeclarationImport({ declaration: def, from: '/server/indices' }).commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + + await ctrl.addDeclarationImport({ declaration: dec, from: '/server/indices' }).commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should convert a normal import when a default specifier is added', async () => { + const ctrl = await provider(document); + const def = new DefaultDeclaration('defaultExport', new File(file.fsPath, rootPath, 1, 2)); + const dec = new ClassDeclaration('defaultClass', true); + + await ctrl.addDeclarationImport({ declaration: dec, from: '/server/indices' }).commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + + await ctrl.addDeclarationImport({ declaration: def, from: '/server/indices' }).commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + it('should render the optimized import', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert(new Position(5, 0), 'const foobar = new Class2();\n'); + }); + + const ctrl = await provider(document); + const declaration1 = new ClassDeclaration('Class2', true); + const declaration2 = new ClassDeclaration('SomeOtherClass', true); + + await ctrl + .addDeclarationImport({ declaration: declaration1, from: '/server/indices' }) + .addDeclarationImport({ declaration: declaration2, from: '/server/not-indices' }) + .commit(); + + expect(getDocumentText(document, 0, 1)).to.matchSnapshot(); + + await ctrl.organizeImports().commit(); + + expect(getDocumentText(document, 0, 1)).to.matchSnapshot(); + }); + + it('should render sorted imports when optimizing', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `import { MultiExportClass } from '../server/indices/defaultExport/multiExport';\n`, + ); + builder.insert(new Position(5, 0), 'const foobar = new MultiExportClass();\n'); + }); + const ctrl = await provider(document); + + await ctrl.organizeImports().commit(); + + expect(getDocumentText(document, 0, 1)).to.matchSnapshot(); + }); + + it('should render sorted specifiers when optimizing', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert(new Position(0, 9), 'Class2, '); + builder.insert(new Position(5, 0), 'const foobar = new Class2();\n'); + }); + const ctrl = await provider(document); + + await ctrl.organizeImports().commit(); + + expect(document.lineAt(0).text).to.matchSnapshot(); + }); + + }); + + }); + +}); diff --git a/test/tests/imports/import-organizer.test.ts b/test/tests/imports/import-organizer.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/tests/imports/import-quick-pick-item.test.ts b/test/tests/imports/import-quick-pick-item.test.ts new file mode 100644 index 0000000..691f828 --- /dev/null +++ b/test/tests/imports/import-quick-pick-item.test.ts @@ -0,0 +1,26 @@ +import { ClassDeclaration } from 'typescript-parser'; + +import ImportQuickPickItem from '../../../src/imports/import-quick-pick-item'; +import { expect } from '../setup'; + +describe('ImportQuickPickItem', () => { + + it('should set the correct fields', () => { + const item = new ImportQuickPickItem({ + declaration: new ClassDeclaration('class', true), + from: '/server/indices', + }); + + expect(item).to.matchSnapshot(); + }); + + it('should contain the declaration info', () => { + const item = new ImportQuickPickItem({ + declaration: new ClassDeclaration('class', true), + from: '/server/indices', + }); + + expect(item.declarationInfo).to.matchSnapshot(); + }); + +}); diff --git a/test/tests/setup.ts b/test/tests/setup.ts index f6a78be..7e1c3b3 100644 --- a/test/tests/setup.ts +++ b/test/tests/setup.ts @@ -1,5 +1,8 @@ import { expect as chaiExpect, use } from 'chai'; +import { EOL } from 'os'; import { join, parse } from 'path'; +import sinonChai = require('sinon-chai'); +import { TextDocument } from 'vscode'; const chaiJestSnapshot = require('chai-jest-snapshot'); @@ -12,6 +15,7 @@ declare global { } use(chaiJestSnapshot); +use(sinonChai); before(() => { chaiJestSnapshot.resetSnapshotRegistry(); @@ -26,3 +30,15 @@ beforeEach(function (): void { }); export const expect = chaiExpect; + +export function wait(ms: number): Promise { + return new Promise(resolve => setTimeout(() => resolve(), ms)); +} + +export function getDocumentText(document: TextDocument, lineFrom: number, lineTo: number): string { + const lines: string[] = []; + for (let line = lineFrom; line <= lineTo; line++) { + lines.push(document.lineAt(line).text); + } + return lines.join(EOL) + EOL; +} diff --git a/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap b/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap new file mode 100644 index 0000000..addaef1 --- /dev/null +++ b/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`utility functions getImportInsertPosition() should return correct position for commented file 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + +exports[`utility functions getImportInsertPosition() should return correct position for jsdoc comment close 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + +exports[`utility functions getImportInsertPosition() should return correct position for jsdoc comment line 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + +exports[`utility functions getImportInsertPosition() should return correct position for jsdoc comment open 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + +exports[`utility functions getImportInsertPosition() should return correct position for use strict 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + +exports[`utility functions getImportInsertPosition() should return the top position if empty file 1`] = ` +Object { + "character": 0, + "line": 0, +} +`; + +exports[`utility functions getImportInsertPosition() should return top position if no editor is specified 1`] = ` +Object { + "character": 0, + "line": 0, +} +`; + +exports[`utility functions importSortByFirstSpecifier should sort according to first specifier/alias, falling back to module path 1`] = ` +Array [ + "./anotherFile", + "coolEffectLib", + "./myFile", + "myLib", + "anotherLib", + "./workspaceSideEffectLib", +] +`; diff --git a/test/tests/utilities/utility-functions.test.ts b/test/tests/utilities/utility-functions.test.ts new file mode 100644 index 0000000..cb13ace --- /dev/null +++ b/test/tests/utilities/utility-functions.test.ts @@ -0,0 +1,118 @@ +import { join } from 'path'; +import { TypescriptParser } from 'typescript-parser'; +import { workspace } from 'vscode'; + +import { ImportGroupKeyword, KeywordImportGroup, RegexImportGroup } from '../../../src/imports/import-grouping'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { + getImportInsertPosition, + importGroupSortForPrecedence, + importSortByFirstSpecifier, +} from '../../../src/utilities/utility-functions'; +import { expect } from '../setup'; + +describe('utility functions', () => { + + describe('getImportInsertPosition()', () => { + + class MockDocument { + constructor(private documentText: string) { } + + public getText(): string { + return this.documentText; + } + } + + it('should return top position if no editor is specified', () => { + const pos = getImportInsertPosition(undefined); + expect(pos).to.matchSnapshot(); + }); + + it('should return the top position if empty file', () => { + const pos = getImportInsertPosition({ + document: new MockDocument(''), + } as any); + expect(pos).to.matchSnapshot(); + }); + + it('should return correct position for commented file', () => { + const pos = getImportInsertPosition({ + document: new MockDocument(' // This is a file header\nStart of file\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + + it('should return correct position for use strict', () => { + const pos = getImportInsertPosition({ + document: new MockDocument(`'use strict'\nStart of file\n`), + } as any); + expect(pos).to.matchSnapshot(); + }); + + it('should return correct position for jsdoc comment open', () => { + const pos = getImportInsertPosition({ + document: new MockDocument('/** start of a jsdoc\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + + it('should return correct position for jsdoc comment line', () => { + const pos = getImportInsertPosition({ + document: new MockDocument(' * jsdoc line\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + + it('should return correct position for jsdoc comment close', () => { + const pos = getImportInsertPosition({ + document: new MockDocument('*/\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + + }); + + describe('importGroupSortForPrecedence', () => { + + it('should prioritize regexes, leaving original order untouched besides that', () => { + const initialList = [ + new KeywordImportGroup(ImportGroupKeyword.Modules), + new KeywordImportGroup(ImportGroupKeyword.Plains), + new RegexImportGroup('/cool-library/'), + new RegexImportGroup('/cooler-library/'), + new KeywordImportGroup(ImportGroupKeyword.Workspace), + ]; + const expectedList = initialList + .slice(2, 4) + .concat(initialList.slice(0, 2)) + .concat(initialList.slice(4)); + + expect(importGroupSortForPrecedence(initialList)).to.deep.equal( + expectedList, + 'Regex Import Groups should appear first (and that should be the only change)', + ); + }); + + }); + + describe('importSortByFirstSpecifier', () => { + const parser = ioc.get(iocSymbols.parser); + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + + it('should sort according to first specifier/alias, falling back to module path', async () => { + const file = await parser.parseFile( + join( + rootPath, + 'utilities', + 'imports-for-specifier-sort.ts', + ), + rootPath, + ); + + const result = [...file.imports].sort(importSortByFirstSpecifier); + expect(result.map(i => i.libraryName)).to.matchSnapshot(); + }); + }); + +}); From 44fb21ce99a43348cd13512a650222e9ff538d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Mon, 5 Mar 2018 09:51:19 +0100 Subject: [PATCH 3/8] test: fix globalpath hack --- test/tests/index.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/tests/index.ts b/test/tests/index.ts index e3a2723..d1618c0 100644 --- a/test/tests/index.ts +++ b/test/tests/index.ts @@ -11,7 +11,6 @@ import { ensureFileSync, readFileSync, writeFileSync } from 'fs-extra'; import * as glob from 'glob'; import { hook, Instrumenter, Reporter } from 'istanbul'; -import { platform } from 'os'; import { join, relative } from 'path'; import { ExtensionContext, Memento } from 'vscode'; @@ -33,11 +32,7 @@ class ContextMock implements ExtensionContext { // Prepare for snapshot (sigh) tests. // HACK -if (platform() === 'win32') { - global['rootPath'] = join(process.cwd(), '..'); -} else { - global['rootPath'] = process.cwd(); -} +global['rootPath'] = join(__dirname, '..', '..', '..'); // END HACK const testRunner = require('vscode/lib/testrunner'); From 9348b40eeb0cadc363eefea80a65252287948dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Mon, 5 Mar 2018 15:59:49 +0100 Subject: [PATCH 4/8] fix(organize-imports): Don't remove exported elements and react called functions (#413) Closes #380. Closes #364. --- .vscode/launch.json | 4 +- package.json | 16 +- src/configuration/index.ts | 4 +- src/imports/import-manager.ts | 5 +- src/imports/import-organizer.ts | 2 +- .../imports/import-organizer-file.ts | 0 .../imports/import-organizer-file.tsx | 0 .../import-organizer.test.ts.snap | 74 +++ test/tests/imports/import-organizer.test.ts | 143 +++++ yarn.lock | 583 +++++++++--------- 10 files changed, 530 insertions(+), 301 deletions(-) create mode 100644 test/etc/workspace_1/imports/import-organizer-file.ts create mode 100644 test/etc/workspace_1/imports/import-organizer-file.tsx create mode 100644 test/tests/imports/__snapshots__/import-organizer.test.ts.snap diff --git a/.vscode/launch.json b/.vscode/launch.json index 4ff367d..e05a550 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -51,7 +51,7 @@ "EXT_DEBUG": "true", "LOCAL_TEST": "true", "COVERAGE": "true", - "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "true" + "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "" }, "stopOnEntry": false, "sourceMaps": true, @@ -75,7 +75,7 @@ "EXT_DEBUG": "true", "LOCAL_TEST": "true", "COVERAGE": "true", - "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "true" + "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "" }, "stopOnEntry": false, "sourceMaps": true, diff --git a/package.json b/package.json index 36d9fc8..e426d01 100644 --- a/package.json +++ b/package.json @@ -87,13 +87,13 @@ ] }, "devDependencies": { - "@smartive/tslint-config": "^2.0.0", + "@smartive/tslint-config": "^2.1.0", "@types/chai": "^4.1.2", "@types/istanbul": "^0.4.29", "@types/mocha": "^2.2.48", - "@types/node": "^9.4.0", + "@types/node": "^9.4.6", "@types/reflect-metadata": "0.1.0", - "@types/sinon": "^4.1.3", + "@types/sinon": "^4.3.0", "@types/sinon-chai": "^2.7.29", "chai": "^4.1.2", "chai-jest-snapshot": "^2.0.0", @@ -103,19 +103,19 @@ "remap-istanbul": "^0.10.1", "semantic-release": "^12.4.1", "semantic-release-vsce": "^2.0.0", - "sinon": "^4.2.2", + "sinon": "^4.4.2", "sinon-chai": "^2.14.0", "tslint": "^5.9.1", - "tsutils": "^2.21.0", + "tsutils": "^2.22.2", "vscode": "^1.1.10" }, "dependencies": { "fs-extra": "^5.0.0", - "inversify": "^4.10.0", + "inversify": "^4.11.1", "reflect-metadata": "^0.1.12", "tslib": "^1.9.0", - "typescript": "~2.7.1", - "typescript-parser": "^2.2.2", + "typescript": "~2.7.2", + "typescript-parser": "^2.3.0", "winston": "^3.0.0-rc1" }, "activationEvents": [ diff --git a/src/configuration/index.ts b/src/configuration/index.ts index dd6fe4e..2e1802f 100644 --- a/src/configuration/index.ts +++ b/src/configuration/index.ts @@ -1,5 +1,5 @@ import { inject, injectable } from 'inversify'; -import { TypescriptGenerationOptions } from 'typescript-parser'; +import { MultiLineImportRule, TypescriptGenerationOptions } from 'typescript-parser'; import { Event, EventEmitter, ExtensionContext, Uri, window, workspace } from 'vscode'; import iocSymbols from '../ioc-symbols'; @@ -50,6 +50,7 @@ export default class Configuration { public typescriptGeneratorOptions(resource: Uri): TypescriptGenerationOptions { return { eol: this.imports.insertSemicolons(resource) ? ';' : '', + insertSpaces: true, multiLineTrailingComma: this.imports.multiLineTrailingComma(resource), multiLineWrapThreshold: this.imports.multiLineWrapThreshold(resource), spaceBraces: this.imports.insertSpaceBeforeAndAfterImportBraces(resource), @@ -57,6 +58,7 @@ export default class Configuration { tabSize: window.activeTextEditor && window.activeTextEditor.options.tabSize ? (window.activeTextEditor.options.tabSize as any) * 1 : workspace.getConfiguration('editor', resource).get('tabSize', 4), + wrapMethod: MultiLineImportRule.oneImportPerLineOnlyAfterThreshold, }; } } diff --git a/src/imports/import-manager.ts b/src/imports/import-manager.ts index 50c7a1c..a4d2001 100644 --- a/src/imports/import-manager.ts +++ b/src/imports/import-manager.ts @@ -155,7 +155,10 @@ export default class ImportManager { const defaultSpec = actImport.defaultAlias; const libraryAlreadyImported = keep.find(d => d.libraryName === actImport.libraryName); if (actImport.specifiers.length || - (!!defaultSpec && this._parsedDocument.nonLocalUsages.indexOf(defaultSpec) >= 0)) { + (!!defaultSpec && [ + ...this._parsedDocument.nonLocalUsages, + ...this._parsedDocument.usages, + ].indexOf(defaultSpec) >= 0)) { if (libraryAlreadyImported) { if (actImport.defaultAlias) { (libraryAlreadyImported).defaultAlias = actImport.defaultAlias; diff --git a/src/imports/import-organizer.ts b/src/imports/import-organizer.ts index 8067d22..661ab9e 100644 --- a/src/imports/import-organizer.ts +++ b/src/imports/import-organizer.ts @@ -65,7 +65,7 @@ export class ImportOrganizer implements Activatable { * @private * @returns {Promise} * - * @memberof ImportResolveExtension + * @memberof ImportOrganizer */ private async organizeImports(): Promise { if (!window.activeTextEditor) { diff --git a/test/etc/workspace_1/imports/import-organizer-file.ts b/test/etc/workspace_1/imports/import-organizer-file.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/etc/workspace_1/imports/import-organizer-file.tsx b/test/etc/workspace_1/imports/import-organizer-file.tsx new file mode 100644 index 0000000..e69de29 diff --git a/test/tests/imports/__snapshots__/import-organizer.test.ts.snap b/test/tests/imports/__snapshots__/import-organizer.test.ts.snap new file mode 100644 index 0000000..5910b9a --- /dev/null +++ b/test/tests/imports/__snapshots__/import-organizer.test.ts.snap @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportOrganizer import-organizer-file.ts should not remove default exported default imports 1`] = ` +"import Barbaz from './foo'; + +export default Barbaz; +" +`; + +exports[`ImportOrganizer import-organizer-file.ts should not remove default exported default imports 2`] = ` +"import Barbaz from './foo'; + +export default Barbaz; +" +`; + +exports[`ImportOrganizer import-organizer-file.ts should not remove directly exported default imports 1`] = ` +"import Barbaz from './foo'; + +export { Barbaz } +" +`; + +exports[`ImportOrganizer import-organizer-file.ts should not remove directly exported default imports 2`] = ` +"import Barbaz from './foo'; + +export { Barbaz } +" +`; + +exports[`ImportOrganizer import-organizer-file.ts should not remove directly exported imports 1`] = ` +"import * as Foobar from './lol'; +import * as Barbaz from './foo'; + +export { Foobar, Barbaz } +" +`; + +exports[`ImportOrganizer import-organizer-file.ts should not remove directly exported imports 2`] = ` +"import * as Barbaz from './foo'; +import * as Foobar from './lol'; + +export { Foobar, Barbaz } +" +`; + +exports[`ImportOrganizer import-organizer-file.tsx should not remove function that is used in tsx 1`] = ` +"import { f } from './somewhere'; +import * as React from 'react'; + +export class Comp extends React.Component { + render() { + return ( +
{f()}
+ ); + } +} +" +`; + +exports[`ImportOrganizer import-organizer-file.tsx should not remove function that is used in tsx 2`] = ` +"import * as React from 'react'; + +import { f } from './somewhere'; + +export class Comp extends React.Component { + render() { + return ( +
{f()}
+ ); + } +} +" +`; diff --git a/test/tests/imports/import-organizer.test.ts b/test/tests/imports/import-organizer.test.ts index e69de29..4b7dd31 100644 --- a/test/tests/imports/import-organizer.test.ts +++ b/test/tests/imports/import-organizer.test.ts @@ -0,0 +1,143 @@ +import { join } from 'path'; +import { Position, Range, TextDocument, Uri, window, workspace } from 'vscode'; + +import { ImportOrganizer } from '../../../src/imports'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { expect } from '../setup'; + +describe('ImportOrganizer', () => { + + describe('import-organizer-file.ts', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const file = Uri.file(join(rootPath, 'imports', 'import-organizer-file.ts')); + let document: TextDocument; + let extension: any; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + + extension = new ImportOrganizer( + ioc.get(iocSymbols.extensionContext), + ioc.get(iocSymbols.logger), + ioc.get(iocSymbols.configuration), + ioc.get(iocSymbols.importManager), + ); + }); + + afterEach(async () => { + await window.activeTextEditor!.edit((builder) => { + builder.delete(new Range( + new Position(0, 0), + document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, + )); + }); + }); + + it('should not remove directly exported imports', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `import * as Foobar from './lol'; +import * as Barbaz from './foo'; + +export { Foobar, Barbaz } +`, + ); + }); + + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + await extension.organizeImports(); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should not remove directly exported default imports', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `import Barbaz from './foo'; + +export { Barbaz } +`, + ); + }); + + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + await extension.organizeImports(); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should not remove default exported default imports', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `import Barbaz from './foo'; + +export default Barbaz; +`, + ); + }); + + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + await extension.organizeImports(); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + }); + + describe('import-organizer-file.tsx', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const file = Uri.file(join(rootPath, 'imports', 'import-organizer-file.tsx')); + let document: TextDocument; + let extension: any; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + + extension = new ImportOrganizer( + ioc.get(iocSymbols.extensionContext), + ioc.get(iocSymbols.logger), + ioc.get(iocSymbols.configuration), + ioc.get(iocSymbols.importManager), + ); + }); + + afterEach(async () => { + await window.activeTextEditor!.edit((builder) => { + builder.delete(new Range( + new Position(0, 0), + document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, + )); + }); + }); + + it('should not remove function that is used in tsx', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `import { f } from './somewhere'; +import * as React from 'react'; + +export class Comp extends React.Component { + render() { + return ( +
{f()}
+ ); + } +} +`, + ); + }); + + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + await extension.organizeImports(); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + }); + +}); diff --git a/yarn.lock b/yarn.lock index ed8c6ea..dc38c13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,22 +3,19 @@ "@octokit/rest@^14.0.3": - version "14.0.8" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-14.0.8.tgz#594292f9c30eb86a832f99f7d464ee7c9c8114c5" + version "14.0.9" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-14.0.9.tgz#d5e0a00dcb78901dd7b2ef852acfc0aea7c479ef" dependencies: before-after-hook "^1.1.0" debug "^3.1.0" - dotenv "^4.0.0" - https-proxy-agent "^2.1.0" is-array-buffer "^1.0.0" is-stream "^1.1.0" lodash "^4.17.4" - proxy-from-env "^1.0.0" url-template "^2.0.8" "@semantic-release/commit-analyzer@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-5.0.1.tgz#1af758537b2a366e18d71fd398764170cbfdb567" + version "5.0.2" + resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-5.0.2.tgz#4db92f1aaed02397393ac78309892627c88eb64a" dependencies: conventional-changelog-angular "^1.4.0" conventional-commits-parser "^2.0.0" @@ -27,8 +24,8 @@ lodash "^4.17.4" "@semantic-release/error@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-2.1.0.tgz#44771f676f5b148da309111285a97901aa95a6e0" + version "2.2.0" + resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-2.2.0.tgz#ee9d5a09c9969eade1ec864776aeda5c5cddbbf0" "@semantic-release/github@^3.0.1": version "3.0.3" @@ -62,8 +59,8 @@ registry-auth-token "^3.3.1" "@semantic-release/release-notes-generator@^6.0.0": - version "6.0.5" - resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-6.0.5.tgz#cd98a374a525d524a82ee767287b65d533f467d3" + version "6.0.6" + resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-6.0.6.tgz#c24c3cf6ad3d44e2453d55e5aaf63e0f091251d8" dependencies: conventional-changelog-angular "^1.4.0" conventional-changelog-writer "^3.0.0" @@ -75,11 +72,17 @@ into-stream "^3.1.0" lodash "^4.17.4" -"@smartive/tslint-config@^2.0.0": +"@sinonjs/formatio@^2.0.0": version "2.0.0" - resolved "https://registry.yarnpkg.com/@smartive/tslint-config/-/tslint-config-2.0.0.tgz#51ff4d91c87ced8c03729502e63f3d3a0acec378" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + +"@smartive/tslint-config@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@smartive/tslint-config/-/tslint-config-2.1.0.tgz#21b84699b24bff1aa7bacdbea12e68a16833097b" dependencies: - tslint-config-airbnb "~5.4.2" + tslint-config-airbnb "~5.7.0" tslint-react "^3.2.0" "@types/chai@*", "@types/chai@^4.1.2": @@ -94,9 +97,9 @@ version "2.2.48" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.48.tgz#3523b126a0b049482e1c3c11877460f76622ffab" -"@types/node@*", "@types/node@^9.4.0": - version "9.4.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.0.tgz#b85a0bcf1e1cc84eb4901b7e96966aedc6f078d1" +"@types/node@*", "@types/node@^9.4.6": + version "9.4.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e" "@types/reflect-metadata@0.1.0": version "0.1.0" @@ -111,9 +114,9 @@ "@types/chai" "*" "@types/sinon" "*" -"@types/sinon@*", "@types/sinon@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.1.3.tgz#2ee25e0e302f31e78a945650a60029e08878eaf8" +"@types/sinon@*", "@types/sinon@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.0.tgz#7f53915994a00ccea24f4e0c24709822ed11a3b1" JSONStream@^1.0.4: version "1.3.2" @@ -140,15 +143,9 @@ acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.4.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" - -agent-base@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" - dependencies: - es6-promisify "^5.0.0" +acorn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.0.tgz#1abb587fbf051f94e3de20e6b26ef910b1828298" aggregate-error@^1.0.0: version "1.0.0" @@ -222,9 +219,9 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.1.0, ansi-styles@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" @@ -248,8 +245,8 @@ are-we-there-yet@~1.1.2: readable-stream "^2.0.6" argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" @@ -415,8 +412,8 @@ boxen@^1.2.1: widest-line "^2.0.0" brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -466,6 +463,14 @@ camelcase-keys@^2.0.0: camelcase "^2.0.0" map-obj "^1.0.0" +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -474,7 +479,7 @@ camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" -camelcase@^4.0.0: +camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -533,12 +538,12 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: supports-color "^2.0.0" chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" dependencies: - ansi-styles "^3.1.0" + ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + supports-color "^5.3.0" chardet@^0.4.0: version "0.4.2" @@ -685,9 +690,9 @@ colorspace@1.0.x: color "0.8.x" text-hex "0.0.x" -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" @@ -696,8 +701,8 @@ commander@2.11.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" commander@^2.11.0, commander@^2.12.1, commander@^2.8.1, commander@^2.9.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.0.tgz#7b25325963e6aace20d3a9285b09379b0c2208b5" + version "2.14.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" compare-func@^1.3.1: version "1.3.2" @@ -711,8 +716,8 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" concat-stream@^1.5.2, concat-stream@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + version "1.6.1" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" dependencies: inherits "^2.0.3" readable-stream "^2.2.2" @@ -745,42 +750,42 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" conventional-changelog-angular@^1.4.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.6.2.tgz#0a811313de46326e5e4e11dac281d61cfe1f00c4" + version "1.6.6" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz#b27f2b315c16d0a1f23eb181309d0e6a4698ea0f" dependencies: compare-func "^1.3.1" - q "^1.4.1" + q "^1.5.1" conventional-changelog-writer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-3.0.0.tgz#e106154ed94341e387d717b61be2181ff53254cc" + version "3.0.4" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-3.0.4.tgz#705b46a8b8277bd7fd79cad8032095b5d803864c" dependencies: compare-func "^1.3.1" - conventional-commits-filter "^1.1.1" - dateformat "^1.0.11" + conventional-commits-filter "^1.1.5" + dateformat "^3.0.0" handlebars "^4.0.2" json-stringify-safe "^5.0.1" - lodash "^4.0.0" - meow "^3.3.0" - semver "^5.0.1" + lodash "^4.2.1" + meow "^4.0.0" + semver "^5.5.0" split "^1.0.0" through2 "^2.0.0" -conventional-commits-filter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-1.1.1.tgz#72172319c0c88328a015b30686b55527b3a5e54a" +conventional-commits-filter@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-1.1.5.tgz#77aac065e3de9c1a74b801e8e25c9affb3184f65" dependencies: is-subset "^0.1.1" modify-values "^1.0.0" conventional-commits-parser@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-2.1.1.tgz#1525a01bdad3349297b4210396e283d8a8ffd044" + version "2.1.5" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-2.1.5.tgz#9ac3a4ab221c0c3c9e9dd2c09ae01e6d1e1dabe0" dependencies: JSONStream "^1.0.4" is-text-path "^1.0.0" lodash "^4.2.1" - meow "^3.3.0" + meow "^4.0.0" split2 "^2.0.0" through2 "^2.0.0" trim-off-newlines "^1.0.0" @@ -802,16 +807,6 @@ cosmiconfig@^4.0.0: parse-json "^4.0.0" require-from-string "^2.0.1" -coveralls@^2.13.3: - version "2.13.3" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.3.tgz#9ad7c2ae527417f361e8b626483f48ee92dd2bc7" - dependencies: - js-yaml "3.6.1" - lcov-parse "0.0.10" - log-driver "1.2.5" - minimist "1.2.0" - request "2.79.0" - create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" @@ -867,17 +862,14 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -dateformat@^1.0.11: - version "1.0.12" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" - dependencies: - get-stdin "^4.0.1" - meow "^3.3.0" - dateformat@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" +dateformat@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" + debug@3.1.0, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -896,7 +888,14 @@ decache@^4.4.0: dependencies: callsite "^1.0.0" -decamelize@^1.0.0, decamelize@^1.1.2: +decamelize-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -980,8 +979,8 @@ diff@3.3.1: resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" diff@^3.1.0, diff@^3.2.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" dir-glob@^2.0.0: version "2.0.0" @@ -1039,8 +1038,8 @@ domutils@1.5.1: domelementtype "1" domutils@^1.5.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff" + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" dependencies: dom-serializer "0" domelementtype "1" @@ -1057,10 +1056,6 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" -dotenv@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" - duplexer2@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" @@ -1082,8 +1077,8 @@ duplexer@~0.1.1: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" duplexify@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e" + version "3.5.4" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" @@ -1119,15 +1114,15 @@ entities@^1.1.1, entities@~1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" env-ci@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-1.4.0.tgz#d5a81534fb25c9dd8627c61e8db0d45bcbb7ef2c" + version "1.4.1" + resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-1.4.1.tgz#e4c68257270155db202f6ca9c61f6520ac6bfeaa" dependencies: execa "^0.9.0" java-properties "^0.2.9" env-variable@0.0.x: - version "0.0.3" - resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.3.tgz#b86c1641be5610267d506f18071ea76d707097cb" + version "0.0.4" + resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.4.tgz#0d6280cf507d84242befe35a512b5ae4be77c54e" error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.1" @@ -1135,16 +1130,6 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es6-promise@^4.0.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - dependencies: - es6-promise "^4.0.3" - escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1179,8 +1164,8 @@ eslint-module-utils@^2.1.1: pkg-dir "^1.0.0" eslint-plugin-import@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894" + version "2.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz#26002efbfca5989b7288ac047508bd24f217b169" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" @@ -1189,7 +1174,7 @@ eslint-plugin-import@^2.7.0: eslint-import-resolver-node "^0.3.1" eslint-module-utils "^2.1.1" has "^1.0.1" - lodash.cond "^4.3.0" + lodash "^4.17.4" minimatch "^3.0.3" read-pkg-up "^2.0.0" @@ -1222,8 +1207,8 @@ eslint-visitor-keys@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" eslint@^4.11.0: - version "4.17.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.17.0.tgz#dc24bb51ede48df629be7031c71d9dc0ee4f3ddf" + version "4.18.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.2.tgz#0f81267ad1012e7d2051e186a9004cc2267b8d45" dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -1260,17 +1245,17 @@ eslint@^4.11.0: semver "^5.3.0" strip-ansi "^4.0.0" strip-json-comments "~2.0.1" - table "^4.0.1" + table "4.0.2" text-table "~0.2.0" espree@^3.5.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.3.tgz#931e0af64e7fbbed26b050a29daad1fc64799fa6" + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: - acorn "^5.4.0" + acorn "^5.5.0" acorn-jsx "^3.0.0" -esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: +esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -1289,11 +1274,10 @@ esquery@^1.0.0: estraverse "^4.0.0" esrecurse@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" dependencies: estraverse "^4.1.0" - object-assign "^4.0.1" estraverse@^1.9.1: version "1.9.3" @@ -1406,8 +1390,8 @@ fancy-log@^1.1.0: time-stamp "^1.0.0" fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" fast-json-stable-stringify@^2.0.0: version "2.0.0" @@ -1424,8 +1408,8 @@ fd-slicer@~1.0.1: pend "~1.2.0" fecha@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.2.tgz#360f035dd6edd954bc9581f95f2a4a7f2a3505c1" + version "2.3.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" figures@^2.0.0: version "2.0.0" @@ -1503,19 +1487,13 @@ form-data@~2.1.1: mime-types "^2.1.12" form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "1.0.6" mime-types "^2.1.12" -formatio@1.2.0, formatio@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" - dependencies: - samsam "1.x" - from2@^2.1.1: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -1616,8 +1594,8 @@ git-up@^2.0.0: parse-url "^1.3.0" git-url-parse@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-8.0.1.tgz#eb3fa427e294d214d9abbeb59637cc8646279c00" + version "8.1.0" + resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-8.1.0.tgz#d1ee09213efce5d8dc7a21bb03f17cfe0c111122" dependencies: git-up "^2.0.0" @@ -1894,6 +1872,10 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" @@ -1937,8 +1919,8 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" hook-std@^0.4.0: version "0.4.0" @@ -1975,13 +1957,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9" - dependencies: - agent-base "^4.1.0" - debug "^3.1.0" - iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -2055,9 +2030,9 @@ into-stream@^3.1.0: from2 "^2.1.1" p-is-promise "^1.1.0" -inversify@^4.10.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.10.0.tgz#06b97792e69220dd150b986cde9a445b3bcb9482" +inversify@^4.11.1: + version "4.11.1" + resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.11.1.tgz#9a10635d1fd347da11da96475b3608babd5945a6" is-array-buffer@^1.0.0: version "1.0.0" @@ -2138,12 +2113,17 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + is-my-json-valid@^2.12.4: - version "2.17.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" + version "2.17.2" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" jsonpointer "^4.0.0" xtend "^4.0.0" @@ -2183,7 +2163,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -2332,13 +2312,6 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - js-yaml@3.x, js-yaml@^3.7.0, js-yaml@^3.9.0, js-yaml@^3.9.1: version "3.10.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" @@ -2403,7 +2376,7 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -just-extend@^1.1.26: +just-extend@^1.1.27: version "1.1.27" resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" @@ -2445,10 +2418,6 @@ lazystream@^1.0.0: dependencies: readable-stream "^2.0.5" -lcov-parse@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -2497,6 +2466,10 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +lodash-es@^4.17.5: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.5.tgz#9fc6e737b1c4d151d8f9cae2247305d552ce748f" + lodash._basecopy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" @@ -2537,10 +2510,6 @@ lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" -lodash.cond@^4.3.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - lodash.escape@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" @@ -2604,14 +2573,10 @@ lodash.values@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" -lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.1, lodash@^4.3.0: +lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" -log-driver@1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" - logform@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/logform/-/logform-1.2.2.tgz#7be8847684de07185029ed09c65b11d06191ef93" @@ -2619,11 +2584,7 @@ logform@^1.2.1: colors "^1.1.2" fecha "^2.3.2" -lolex@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" - -lolex@^2.2.0: +lolex@^2.2.0, lolex@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.2.tgz#85f9450425103bf9e7a60668ea25dc43274ca807" @@ -2650,8 +2611,8 @@ lru-cache@^4.0.1: yallist "^2.1.2" make-dir@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" + version "1.2.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b" dependencies: pify "^3.0.0" @@ -2659,19 +2620,23 @@ map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" markdown-it@^8.3.1: - version "8.4.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.0.tgz#e2400881bf171f7018ed1bd9da441dac8af6306d" + version "8.4.1" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.1.tgz#206fe59b0e4e1b78a7c73250af9b34a4ad0aaf44" dependencies: argparse "^1.0.7" entities "~1.1.1" linkify-it "^2.0.0" mdurl "^1.0.1" - uc.micro "^1.0.3" + uc.micro "^1.0.5" marked-terminal@^2.0.0: version "2.0.0" @@ -2684,14 +2649,14 @@ marked-terminal@^2.0.0: node-emoji "^1.4.1" marked@^0.3.9: - version "0.3.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519" + version "0.3.17" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.17.tgz#607f06668b3c6b1246b28f13da76116ac1aa2d2b" mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" -meow@^3.3.0, meow@^3.6.0: +meow@^3.6.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" dependencies: @@ -2706,6 +2671,20 @@ meow@^3.3.0, meow@^3.6.0: redent "^1.0.0" trim-newlines "^1.0.0" +meow@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.0.tgz#fd5855dd008db5b92c552082db1c307cba20b29d" + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist "^1.1.3" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + merge-stream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" @@ -2730,15 +2709,15 @@ micromatch@^2.3.7: parse-glob "^3.0.4" regex-cache "^0.4.2" -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: - mime-db "~1.30.0" + mime-db "~1.33.0" mime@^1.3.4: version "1.6.0" @@ -2758,11 +2737,18 @@ mimic-fn@^1.0.0: dependencies: brace-expansion "^1.1.7" +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -2827,12 +2813,12 @@ nerf-dart@^1.0.0: resolved "https://registry.yarnpkg.com/nerf-dart/-/nerf-dart-1.0.0.tgz#e6dab7febf5ad816ea81cf5c629c5a0ebde72c1a" nise@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.2.tgz#9aa5edb500da38035884106e3c571341bc68b2c1" + version "1.3.0" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.3.0.tgz#7d6d506e64a0e37959495157f30a799c0436df72" dependencies: - formatio "^1.2.0" - just-extend "^1.1.26" - lolex "^1.6.0" + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" path-to-regexp "^1.7.0" text-encoding "^0.6.4" @@ -3011,8 +2997,8 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" osenv@^0.1.3, osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -3246,6 +3232,10 @@ process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" @@ -3258,10 +3248,6 @@ protocols@^1.1.0, protocols@^1.4.0: version "1.4.6" resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.6.tgz#f8bb263ea1b5fd7a7604d26b8be39bd77678bf8a" -proxy-from-env@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" - pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -3270,7 +3256,7 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -q@^1.0.1, q@^1.4.1: +q@^1.0.1, q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -3306,6 +3292,10 @@ queue@^4.2.1: dependencies: inherits "~2.0.0" +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -3383,13 +3373,13 @@ read@^1.0.7: string_decoder "~0.10.x" readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + version "2.3.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" isarray "~1.0.0" - process-nextick-args "~1.0.6" + process-nextick-args "~2.0.0" safe-buffer "~5.1.1" string_decoder "~1.0.3" util-deprecate "~1.0.1" @@ -3421,6 +3411,13 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + redeyed@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-1.0.1.tgz#e96c193b40c0816b00aec842698e61185e55498a" @@ -3487,31 +3484,6 @@ replace-ext@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" -request@2.79.0, request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - request@^2.74.0, request@^2.83.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" @@ -3539,6 +3511,31 @@ request@^2.74.0, request@^2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" +request@~2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + require-from-string@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" @@ -3619,7 +3616,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.x: +samsam@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" @@ -3676,7 +3673,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1: +"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -3706,12 +3703,12 @@ sinon-chai@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" -sinon@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.2.2.tgz#e039ab27bdb426fc61363c380726e996a2e2c620" +sinon@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.4.2.tgz#c4c41d4bd346e1d33594daec2d5df0548334fc65" dependencies: + "@sinonjs/formatio" "^2.0.0" diff "^3.1.0" - formatio "1.2.0" lodash.get "^4.4.2" lolex "^2.2.0" nise "^1.2.0" @@ -3784,19 +3781,27 @@ spawn-error-forwarder@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz#1afd94738e999b0346d7b9fc373be55e07577029" -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" dependencies: - spdx-license-ids "^1.0.2" + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" split2@^2.0.0: version "2.2.0" @@ -3953,6 +3958,10 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -3973,19 +3982,13 @@ supports-color@^3.1.0: dependencies: has-flag "^1.0.0" -supports-color@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - dependencies: - has-flag "^2.0.0" - -supports-color@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" +supports-color@^5.1.0, supports-color@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" dependencies: - has-flag "^2.0.0" + has-flag "^3.0.0" -table@^4.0.1: +table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: @@ -4085,8 +4088,8 @@ to-absolute-glob@^0.1.1: extend-shallow "^2.0.1" tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1" @@ -4098,6 +4101,10 @@ trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + trim-off-newlines@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" @@ -4110,9 +4117,9 @@ tslib@^1.0.0, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" -tslint-config-airbnb@~5.4.2: - version "5.4.2" - resolved "https://registry.yarnpkg.com/tslint-config-airbnb/-/tslint-config-airbnb-5.4.2.tgz#18eeff28f697b578731249d9a3ef8955b2f04f44" +tslint-config-airbnb@~5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/tslint-config-airbnb/-/tslint-config-airbnb-5.7.0.tgz#09ff04b0dd599765f44b4425004458d08fcb2c40" dependencies: tslint-consistent-codestyle "^1.10.0" tslint-eslint-rules "^4.1.1" @@ -4134,14 +4141,14 @@ tslint-eslint-rules@^4.1.1: tsutils "^1.4.0" tslint-microsoft-contrib@~5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.2.tgz#ecc2a797f777a12f0066944cec0c81a9e7c59ee9" + version "5.0.3" + resolved "https://registry.yarnpkg.com/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.3.tgz#6fc3e238179cd72045c2b422e4d655f4183a8d5c" dependencies: tsutils "^2.12.1" tslint-react@^3.2.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.4.0.tgz#12ed3fc7063f3df988370206736b50acbce07e59" + version "3.5.1" + resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.5.1.tgz#a5ca48034bf583fb63b42763bb89fa23062d5390" dependencies: tsutils "^2.13.1" @@ -4166,9 +4173,9 @@ tsutils@^1.4.0: version "1.9.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0" -tsutils@^2.12.1, tsutils@^2.13.1, tsutils@^2.21.0: - version "2.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.21.0.tgz#43466a2283a0abce64e2209bc732ad72f8a04fab" +tsutils@^2.12.1, tsutils@^2.13.1, tsutils@^2.21.0, tsutils@^2.22.2: + version "2.22.2" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.22.2.tgz#0b9f3d87aa3eb95bd32d26ce2b88aa329a657951" dependencies: tslib "^1.8.1" @@ -4211,20 +4218,20 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript-parser@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/typescript-parser/-/typescript-parser-2.2.2.tgz#c8f0adeca61c2a8718c32bd00e628f8cc06b6bb4" +typescript-parser@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/typescript-parser/-/typescript-parser-2.3.0.tgz#76cc93b24f89fbaa3e82216748fd0adc6fc4e5e4" dependencies: - coveralls "^2.13.3" - lodash "^4.17.4" - tslib "^1.7.1" - typescript "^2.5.3" + lodash "^4.17.5" + lodash-es "^4.17.5" + tslib "^1.9.0" + typescript "^2.7.2" -typescript@^2.5.3, typescript@~2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359" +typescript@^2.7.2, typescript@~2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" -uc.micro@^1.0.1, uc.micro@^1.0.3: +uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" @@ -4318,11 +4325,11 @@ vali-date@^1.0.0: resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" validate-npm-package-name@^3.0.0: version "3.0.0" @@ -4414,8 +4421,8 @@ vinyl@~2.0.1: replace-ext "^1.0.0" vsce@^1.33.2: - version "1.36.2" - resolved "https://registry.yarnpkg.com/vsce/-/vsce-1.36.2.tgz#dfcfca722bc6aa6bfcbffb1efd23176ba99b2944" + version "1.37.5" + resolved "https://registry.yarnpkg.com/vsce/-/vsce-1.37.5.tgz#0b153bc8aede2cbf35971f10f795e2f88ca1f8fe" dependencies: cheerio "^1.0.0-rc.1" commander "^2.8.1" @@ -4431,7 +4438,7 @@ vsce@^1.33.2: semver "^5.1.0" tmp "0.0.29" url-join "^1.1.0" - vso-node-api "^6.1.2-preview" + vso-node-api "6.1.2-preview" yauzl "^2.3.1" yazl "^2.2.2" @@ -4454,7 +4461,7 @@ vscode@^1.1.10: url-parse "^1.1.9" vinyl-source-stream "^1.1.0" -vso-node-api@^6.1.2-preview: +vso-node-api@6.1.2-preview: version "6.1.2-preview" resolved "https://registry.yarnpkg.com/vso-node-api/-/vso-node-api-6.1.2-preview.tgz#aab3546df2451ecd894e071bb99b5df19c5fa78f" dependencies: From 77d4d01ca878aefc581c10bc7082885a016ea8aa Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 6 Mar 2018 07:15:34 +0000 Subject: [PATCH 5/8] chore(package): update sinon-chai to version 3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e426d01..a34d36a 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "semantic-release": "^12.4.1", "semantic-release-vsce": "^2.0.0", "sinon": "^4.4.2", - "sinon-chai": "^2.14.0", + "sinon-chai": "^3.0.0", "tslint": "^5.9.1", "tsutils": "^2.22.2", "vscode": "^1.1.10" From efcfb3d206f2acdcbc8823dfdc5c1e132b21eca3 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Tue, 6 Mar 2018 07:21:11 +0000 Subject: [PATCH 6/8] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index dc38c13..118d2db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3699,9 +3699,9 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -sinon-chai@^2.14.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" +sinon-chai@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.0.0.tgz#d5cbd70fa71031edd96b528e0eed4038fcc99f29" sinon@^4.4.2: version "4.4.2" From a83c410d94737d9d4f4ee87df690ea884c53880f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 6 Mar 2018 09:29:57 +0100 Subject: [PATCH 7/8] fix(organize-imports): Don't reorder shebang and block comment (#415) Fixes #409. Fixes #412. Add shebang and js block comment to the excluded heading lines. --- .vscode/launch.json | 4 +- src/utilities/utility-functions.ts | 2 +- .../imports/import-appender-file.ts | 0 .../import-appender.test.ts.snap | 50 +++++++ test/tests/imports/import-appender.test.ts | 141 ++++++++++++++++++ .../utility-functions.test.ts.snap | 14 ++ .../tests/utilities/utility-functions.test.ts | 14 ++ 7 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 test/etc/workspace_1/imports/import-appender-file.ts create mode 100644 test/tests/imports/__snapshots__/import-appender.test.ts.snap diff --git a/.vscode/launch.json b/.vscode/launch.json index e05a550..e8bacfb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -50,7 +50,7 @@ "env": { "EXT_DEBUG": "true", "LOCAL_TEST": "true", - "COVERAGE": "true", + "COVERAGE": "", "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "" }, "stopOnEntry": false, @@ -74,7 +74,7 @@ "env": { "EXT_DEBUG": "true", "LOCAL_TEST": "true", - "COVERAGE": "true", + "COVERAGE": "", "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "" }, "stopOnEntry": false, diff --git a/src/utilities/utility-functions.ts b/src/utilities/utility-functions.ts index 5e7fb5a..4116aca 100644 --- a/src/utilities/utility-functions.ts +++ b/src/utilities/utility-functions.ts @@ -320,7 +320,7 @@ export function getRelativeLibraryName(library: string, actualFilePath: string, return toPosix(relativePath); } -const REGEX_IGNORED_LINE = /^\s*(?:\/\/|\/\*\*|\*\/|\*|(['"])use strict\1)/; +const REGEX_IGNORED_LINE = /^\s*(?:\/\/|\/\*|\*\/|\*|#!|(['"])use strict\1)/; /** * Calculate the position, where a new import should be inserted. diff --git a/test/etc/workspace_1/imports/import-appender-file.ts b/test/etc/workspace_1/imports/import-appender-file.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/tests/imports/__snapshots__/import-appender.test.ts.snap b/test/tests/imports/__snapshots__/import-appender.test.ts.snap new file mode 100644 index 0000000..dec87b6 --- /dev/null +++ b/test/tests/imports/__snapshots__/import-appender.test.ts.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportAppender import-appender-file.ts should add a double normal named import 1`] = ` +"import { MyClass, MyClass2 } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add a normal default import 1`] = ` +"import defaultDec from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add a normal named import 1`] = ` +"import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a block comment 1`] = ` +"/* + * copy right by me! + */ +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a comment 1`] = ` +"// my fancy comment +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a jsdoc comment 1`] = ` +"/** + * js documentation! + */ +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a shebang 1`] = ` +"#! /usr/bin/env node +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a use strict 1`] = ` +"\\"use strict\\" +import { MyClass } from '../lib'; +" +`; diff --git a/test/tests/imports/import-appender.test.ts b/test/tests/imports/import-appender.test.ts index e69de29..42e12b0 100644 --- a/test/tests/imports/import-appender.test.ts +++ b/test/tests/imports/import-appender.test.ts @@ -0,0 +1,141 @@ +import { join } from 'path'; +import { ClassDeclaration, DeclarationInfo, DefaultDeclaration, File } from 'typescript-parser'; +import { Position, Range, TextDocument, Uri, window, workspace } from 'vscode'; + +import { ImportAppender } from '../../../src/imports'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { expect } from '../setup'; + +describe('ImportAppender', () => { + + describe('import-appender-file.ts', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const file = Uri.file(join(rootPath, 'imports', 'import-appender-file.ts')); + let document: TextDocument; + let extension: { addImportToDocument(declaration: DeclarationInfo): Promise }; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + + extension = new ImportAppender( + ioc.get(iocSymbols.extensionContext), + ioc.get(iocSymbols.logger), + ioc.get(iocSymbols.importManager), + ioc.get(iocSymbols.declarationManager), + ioc.get(iocSymbols.parser), + ) as any; + }); + + afterEach(async () => { + await window.activeTextEditor!.edit((builder) => { + builder.delete(new Range( + new Position(0, 0), + document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, + )); + }); + }); + + it('should add a normal named import', async () => { + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add a double normal named import', async () => { + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass2', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add a normal default import', async () => { + await extension.addImportToDocument({ + from: '/lib', + declaration: new DefaultDeclaration('defaultDec', new File(file.fsPath, rootPath, 0, 0), 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a comment', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `// my fancy comment\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a block comment', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `/* \n * copy right by me!\n */\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a jsdoc comment', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `/** \n * js documentation!\n */\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a shebang', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `#! /usr/bin/env node\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a use strict', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `"use strict"\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + }); + +}); diff --git a/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap b/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap index addaef1..26a89b3 100644 --- a/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap +++ b/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap @@ -7,6 +7,13 @@ Object { } `; +exports[`utility functions getImportInsertPosition() should return correct position for js block comment open 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + exports[`utility functions getImportInsertPosition() should return correct position for jsdoc comment close 1`] = ` Object { "character": 0, @@ -28,6 +35,13 @@ Object { } `; +exports[`utility functions getImportInsertPosition() should return correct position for shebang (#!) 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + exports[`utility functions getImportInsertPosition() should return correct position for use strict 1`] = ` Object { "character": 0, diff --git a/test/tests/utilities/utility-functions.test.ts b/test/tests/utilities/utility-functions.test.ts index cb13ace..4341742 100644 --- a/test/tests/utilities/utility-functions.test.ts +++ b/test/tests/utilities/utility-functions.test.ts @@ -57,6 +57,13 @@ describe('utility functions', () => { expect(pos).to.matchSnapshot(); }); + it('should return correct position for js block comment open', () => { + const pos = getImportInsertPosition({ + document: new MockDocument('/* yay\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + it('should return correct position for jsdoc comment line', () => { const pos = getImportInsertPosition({ document: new MockDocument(' * jsdoc line\n'), @@ -71,6 +78,13 @@ describe('utility functions', () => { expect(pos).to.matchSnapshot(); }); + it('should return correct position for shebang (#!)', () => { + const pos = getImportInsertPosition({ + document: new MockDocument('#!\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + }); describe('importGroupSortForPrecedence', () => { From 3651cbc41c36942a44c9a08f6acf47bfc76ec3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 6 Mar 2018 14:00:57 +0100 Subject: [PATCH 8/8] feat(code-completion): Add the code completion back with testing (#416) Add the code completion back. Remove old code. Fixes #388. --- .vscode/launch.json | 6 +- config/tsconfig.base.json | 3 - config/tsconfig.test-multi-workspace.json | 2 - config/tsconfig.test-single-workspace.json | 2 - package.json | 13 +- .../common/config/CodeCompletionConfig.ts | 28 - src/_old/common/config/CodeOutlineConfig.ts | 27 - src/_old/common/config/ExtensionConfig.ts | 68 - src/_old/common/config/ResolverConfig.ts | 207 - src/_old/common/config/index.ts | 4 - src/_old/common/enums.ts | 11 - src/_old/common/errors/ClassNotFoundError.ts | 13 - .../common/errors/MethodDuplicatedError.ts | 13 - src/_old/common/errors/MethodNotFoundError.ts | 13 - .../common/errors/NotImplementedYetError.ts | 13 - .../common/errors/PropertyDuplicatedError.ts | 13 - .../common/errors/PropertyNotFoundError.ts | 13 - src/_old/common/errors/index.ts | 6 - src/_old/common/factories/index.ts | 11 - .../common/helpers/DeclarationIndexHelpers.ts | 1 - src/_old/common/helpers/ImportHelpers.ts | 1 - src/_old/common/helpers/index.ts | 2 - src/_old/common/quick-pick-items/index.ts | 1 - src/_old/extension/IoC.ts | 74 - src/_old/extension/IoCSymbols.ts | 13 - src/_old/extension/TypeScriptHero.ts | 39 - src/_old/extension/code-actions/CodeAction.ts | 193 - .../code-actions/CodeActionCreator.ts | 58 - .../MissingImplementationInClassCreator.ts | 134 - .../code-actions/MissingImportCreator.ts | 104 - src/_old/extension/code-actions/index.ts | 4 - .../config/VscodeCodeCompletionConfig.ts | 30 - .../config/VscodeCodeOutlineConfig.ts | 30 - .../extension/config/VscodeExtensionConfig.ts | 90 - .../extension/config/VscodeResolverConfig.ts | 318 -- src/_old/extension/extension.ts | 51 - .../extension/extensions/BaseExtension.ts | 41 - .../extensions/CodeActionExtension.ts | 130 - .../extensions/CodeCompletionExtension.ts | 188 - .../DocumentSymbolStructureExtension.ts | 169 - .../extensions/ImportResolveExtension.ts | 260 -- .../OrganizeImportsOnSaveExtension.ts | 81 - src/_old/extension/helpers/index.ts | 1 - .../extension/helpers/nodeRangeHelpers.ts | 17 - src/_old/extension/managers/ClassManager.ts | 416 -- src/_old/extension/managers/ObjectManager.ts | 23 - src/_old/extension/managers/index.ts | 2 - .../extension/proxy-objects/Changeable.ts | 16 - .../utilities/DeclarationIndexMapper.ts | 257 -- src/_old/old-config.json | 51 - src/code-completion/index.ts | 167 + src/configuration/code-completion-config.ts | 9 + src/configuration/index.ts | 2 + src/ioc.ts | 2 + test/_old/_workspace/.gitignore | 4 - test/_old/_workspace/.vscode/settings.json | 20 - test/_old/_workspace/build/app.d.ts | 1 - test/_old/_workspace/build/app.js | 0 .../common/helpers/importHelperFile.ts | 0 .../_workspace/common/ts-parsing/class.ts | 32 - .../_old/_workspace/common/ts-parsing/enum.ts | 10 - .../common/ts-parsing/exportsOnly.ts | 7 - .../_workspace/common/ts-parsing/function.ts | 16 - .../common/ts-parsing/importsOnly.ts | 10 - .../_workspace/common/ts-parsing/interface.ts | 16 - .../_workspace/common/ts-parsing/module.ts | 12 - .../_workspace/common/ts-parsing/typeAlias.ts | 3 - .../common/ts-parsing/usagesOnly.ts | 41 - .../_workspace/common/ts-parsing/variable.ts | 12 - .../extensions/codeActionExtension/empty.ts | 0 .../codeActionExtension/exportedObjects.ts | 13 - .../implementInterfaceOrAbstract.ts | 39 - .../codeCompletionFile.ts | 16 - .../codeCompletionImports.ts | 3 - .../documentSymbolFile.ts | 13 - .../notParsable.txt | 3 - .../addImportToDocument.js | 0 .../addImportToDocument.ts | 0 .../importResolveExtension/jsfile.js | 9 - .../importResolveExtension/jsxfile.jsx | 15 - .../importResolveExtension/organizeImports.ts | 8 - .../organizeImportsWithExports.ts | 10 - .../importResolveExtension/sameDirectory.ts | 3 - .../sub1/sub2/sub3/subFile.ts | 3 - .../organizeFile.ts | 0 .../extension/managers/ClassManagerFile.ts | 47 - test/_old/_workspace/foobar.ts | 0 .../node_modules/@types/node/README.md | 18 - .../node_modules/@types/node/index.d.ts | 3640 ----------------- .../node_modules/@types/node/package.json | 79 - .../@types/node/types-metadata.json | 72 - .../fancy-library/FancierLibraryClass.d.ts | 3 - .../fancy-library/FancyLibraryClass.d.ts | 7 - .../controllers/MyController.d.ts | 9 - .../node_modules/fancy-library/index.d.ts | 2 - .../some-lib/dist/SomeDeclaration.d.ts | 4 - test/_old/_workspace/out/out.d.ts | 1 - test/_old/_workspace/out/out.js | 0 test/_old/_workspace/package.json | 18 - .../server/indices/HelperFunctions.ts | 7 - .../_old/_workspace/server/indices/MyClass.ts | 17 - .../server/indices/MyReactTemplate.tsx | 5 - .../server/indices/NotBarelExported.ts | 3 - .../server/indices/SpecialExports.ts | 1 - .../indices/circularExport/circularExport1.ts | 5 - .../indices/circularExport/circularExport2.ts | 5 - .../server/indices/defaultExport/codefile.ts | 1 - .../lateDefaultExportedElement.ts | 3 - .../indices/defaultExport/multiExport.ts | 7 - .../indices/defaultExport/namelessClass.ts | 3 - .../indices/defaultExport/namelessFunction.ts | 3 - .../indices/defaultExport/namelessVariable.ts | 1 - test/_old/_workspace/server/indices/index.ts | 2 - test/_old/_workspace/server/indices/proto.ts | 7 - .../typings/globals/body-parser/index.d.ts | 133 - test/_old/_workspace_2/file1.ts | 0 test/_old/_workspace_2/file2.ts | 3 - .../extensions/CodeActionExtension.test.ts | 509 --- .../CodeCompletionExtension.test.ts | 139 - .../OrganizeImportsOnSaveExtension.test.ts | 138 - .../extension/managers/ClassManager.test.ts | 502 --- .../workspace_1/code-completion/classes.ts | 4 + .../code-completion/completions.ts | 10 + test/etc/workspace_1/main.ts | 11 - .../code-completion.test.ts.snap | 83 + .../code-completion/code-completion.test.ts | 124 + test/tests/setup.ts | 19 + tsconfig.json | 2 - 128 files changed, 431 insertions(+), 8976 deletions(-) delete mode 100644 src/_old/common/config/CodeCompletionConfig.ts delete mode 100644 src/_old/common/config/CodeOutlineConfig.ts delete mode 100644 src/_old/common/config/ExtensionConfig.ts delete mode 100644 src/_old/common/config/ResolverConfig.ts delete mode 100644 src/_old/common/config/index.ts delete mode 100644 src/_old/common/enums.ts delete mode 100644 src/_old/common/errors/ClassNotFoundError.ts delete mode 100644 src/_old/common/errors/MethodDuplicatedError.ts delete mode 100644 src/_old/common/errors/MethodNotFoundError.ts delete mode 100644 src/_old/common/errors/NotImplementedYetError.ts delete mode 100644 src/_old/common/errors/PropertyDuplicatedError.ts delete mode 100644 src/_old/common/errors/PropertyNotFoundError.ts delete mode 100644 src/_old/common/errors/index.ts delete mode 100644 src/_old/common/factories/index.ts delete mode 100644 src/_old/common/helpers/DeclarationIndexHelpers.ts delete mode 100644 src/_old/common/helpers/ImportHelpers.ts delete mode 100644 src/_old/common/helpers/index.ts delete mode 100644 src/_old/common/quick-pick-items/index.ts delete mode 100644 src/_old/extension/IoC.ts delete mode 100644 src/_old/extension/IoCSymbols.ts delete mode 100644 src/_old/extension/TypeScriptHero.ts delete mode 100644 src/_old/extension/code-actions/CodeAction.ts delete mode 100644 src/_old/extension/code-actions/CodeActionCreator.ts delete mode 100644 src/_old/extension/code-actions/MissingImplementationInClassCreator.ts delete mode 100644 src/_old/extension/code-actions/MissingImportCreator.ts delete mode 100644 src/_old/extension/code-actions/index.ts delete mode 100644 src/_old/extension/config/VscodeCodeCompletionConfig.ts delete mode 100644 src/_old/extension/config/VscodeCodeOutlineConfig.ts delete mode 100644 src/_old/extension/config/VscodeExtensionConfig.ts delete mode 100644 src/_old/extension/config/VscodeResolverConfig.ts delete mode 100644 src/_old/extension/extension.ts delete mode 100644 src/_old/extension/extensions/BaseExtension.ts delete mode 100644 src/_old/extension/extensions/CodeActionExtension.ts delete mode 100644 src/_old/extension/extensions/CodeCompletionExtension.ts delete mode 100644 src/_old/extension/extensions/DocumentSymbolStructureExtension.ts delete mode 100644 src/_old/extension/extensions/ImportResolveExtension.ts delete mode 100644 src/_old/extension/extensions/OrganizeImportsOnSaveExtension.ts delete mode 100644 src/_old/extension/helpers/index.ts delete mode 100644 src/_old/extension/helpers/nodeRangeHelpers.ts delete mode 100644 src/_old/extension/managers/ClassManager.ts delete mode 100644 src/_old/extension/managers/ObjectManager.ts delete mode 100644 src/_old/extension/managers/index.ts delete mode 100644 src/_old/extension/proxy-objects/Changeable.ts delete mode 100644 src/_old/extension/utilities/DeclarationIndexMapper.ts delete mode 100644 src/_old/old-config.json create mode 100644 src/code-completion/index.ts create mode 100644 src/configuration/code-completion-config.ts delete mode 100644 test/_old/_workspace/.gitignore delete mode 100644 test/_old/_workspace/.vscode/settings.json delete mode 100644 test/_old/_workspace/build/app.d.ts delete mode 100644 test/_old/_workspace/build/app.js delete mode 100644 test/_old/_workspace/common/helpers/importHelperFile.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/class.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/enum.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/exportsOnly.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/function.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/importsOnly.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/interface.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/module.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/typeAlias.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/usagesOnly.ts delete mode 100644 test/_old/_workspace/common/ts-parsing/variable.ts delete mode 100644 test/_old/_workspace/extension/extensions/codeActionExtension/empty.ts delete mode 100644 test/_old/_workspace/extension/extensions/codeActionExtension/exportedObjects.ts delete mode 100644 test/_old/_workspace/extension/extensions/codeActionExtension/implementInterfaceOrAbstract.ts delete mode 100644 test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionFile.ts delete mode 100644 test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionImports.ts delete mode 100644 test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts delete mode 100644 test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/notParsable.txt delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/addImportToDocument.js delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/addImportToDocument.ts delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/jsfile.js delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/jsxfile.jsx delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/organizeImports.ts delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/organizeImportsWithExports.ts delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/sameDirectory.ts delete mode 100644 test/_old/_workspace/extension/extensions/importResolveExtension/sub1/sub2/sub3/subFile.ts delete mode 100644 test/_old/_workspace/extension/extensions/organizeImportsOnSaveExtension/organizeFile.ts delete mode 100644 test/_old/_workspace/extension/managers/ClassManagerFile.ts delete mode 100644 test/_old/_workspace/foobar.ts delete mode 100644 test/_old/_workspace/node_modules/@types/node/README.md delete mode 100644 test/_old/_workspace/node_modules/@types/node/index.d.ts delete mode 100644 test/_old/_workspace/node_modules/@types/node/package.json delete mode 100644 test/_old/_workspace/node_modules/@types/node/types-metadata.json delete mode 100644 test/_old/_workspace/node_modules/fancy-library/FancierLibraryClass.d.ts delete mode 100644 test/_old/_workspace/node_modules/fancy-library/FancyLibraryClass.d.ts delete mode 100644 test/_old/_workspace/node_modules/fancy-library/controllers/MyController.d.ts delete mode 100644 test/_old/_workspace/node_modules/fancy-library/index.d.ts delete mode 100644 test/_old/_workspace/node_modules/some-lib/dist/SomeDeclaration.d.ts delete mode 100644 test/_old/_workspace/out/out.d.ts delete mode 100644 test/_old/_workspace/out/out.js delete mode 100644 test/_old/_workspace/package.json delete mode 100644 test/_old/_workspace/server/indices/HelperFunctions.ts delete mode 100644 test/_old/_workspace/server/indices/MyClass.ts delete mode 100644 test/_old/_workspace/server/indices/MyReactTemplate.tsx delete mode 100644 test/_old/_workspace/server/indices/NotBarelExported.ts delete mode 100644 test/_old/_workspace/server/indices/SpecialExports.ts delete mode 100644 test/_old/_workspace/server/indices/circularExport/circularExport1.ts delete mode 100644 test/_old/_workspace/server/indices/circularExport/circularExport2.ts delete mode 100644 test/_old/_workspace/server/indices/defaultExport/codefile.ts delete mode 100644 test/_old/_workspace/server/indices/defaultExport/lateDefaultExportedElement.ts delete mode 100644 test/_old/_workspace/server/indices/defaultExport/multiExport.ts delete mode 100644 test/_old/_workspace/server/indices/defaultExport/namelessClass.ts delete mode 100644 test/_old/_workspace/server/indices/defaultExport/namelessFunction.ts delete mode 100644 test/_old/_workspace/server/indices/defaultExport/namelessVariable.ts delete mode 100644 test/_old/_workspace/server/indices/index.ts delete mode 100644 test/_old/_workspace/server/indices/proto.ts delete mode 100644 test/_old/_workspace/typings/globals/body-parser/index.d.ts delete mode 100644 test/_old/_workspace_2/file1.ts delete mode 100644 test/_old/_workspace_2/file2.ts delete mode 100644 test/_old/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts delete mode 100644 test/_old/single-workspace-tests/extension/managers/ClassManager.test.ts create mode 100644 test/etc/workspace_1/code-completion/classes.ts create mode 100644 test/etc/workspace_1/code-completion/completions.ts create mode 100644 test/tests/code-completion/__snapshots__/code-completion.test.ts.snap create mode 100644 test/tests/code-completion/code-completion.test.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index e8bacfb..fe87ed3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -57,8 +57,7 @@ "sourceMaps": true, "smartStep": true, "outFiles": [ - "${workspaceRoot}/out/src/**/*.js", - "${workspaceRoot}/out/test/tests/**/*.js" + "${workspaceRoot}/out/**/*.js" ] }, { @@ -81,8 +80,7 @@ "sourceMaps": true, "smartStep": true, "outFiles": [ - "${workspaceRoot}/out/src/**/*.js", - "${workspaceRoot}/out/test/tests/**/*.js" + "${workspaceRoot}/out/**/*.js" ] } ], diff --git a/config/tsconfig.base.json b/config/tsconfig.base.json index d5461f4..59b9807 100644 --- a/config/tsconfig.base.json +++ b/config/tsconfig.base.json @@ -19,8 +19,5 @@ }, "include": [ "../src/**/*" - ], - "exclude": [ - "../src/_old" ] } diff --git a/config/tsconfig.test-multi-workspace.json b/config/tsconfig.test-multi-workspace.json index 5b8571d..043417d 100644 --- a/config/tsconfig.test-multi-workspace.json +++ b/config/tsconfig.test-multi-workspace.json @@ -8,8 +8,6 @@ "../test/**/*" ], "exclude": [ - "../src/_old", - "../test/_old", "../test/etc", "../test/**/*.single.test.ts" ] diff --git a/config/tsconfig.test-single-workspace.json b/config/tsconfig.test-single-workspace.json index 1bf40ca..07fae4c 100644 --- a/config/tsconfig.test-single-workspace.json +++ b/config/tsconfig.test-single-workspace.json @@ -8,8 +8,6 @@ "../test/**/*" ], "exclude": [ - "../src/_old", - "../test/_old", "../test/etc", "../test/**/*.multi.test.ts" ] diff --git a/package.json b/package.json index a34d36a..640bf3f 100644 --- a/package.json +++ b/package.json @@ -137,10 +137,6 @@ { "command": "typescriptHero.imports.organize", "title": "TS Hero: Organize imports (sort and remove unused)" - }, - { - "command": "typescriptHero.codeOutline.gotoNode", - "title": "TS Hero (internal): Jump to the given nodes location" } ], "keybindings": [ @@ -183,6 +179,15 @@ "description": "Defines the log output level in the output window. In the log file, it's always info or debug.", "scope": "window" }, + "typescriptHero.codeCompletion.completionSortMode": { + "enum": [ + "default", + "bottom" + ], + "default": "default", + "description": "Defines the sortmode of the code completion in intellisense (bottom means sorted to bottom).", + "scope": "resource" + }, "typescriptHero.codeOutline.enabled": { "type": "boolean", "default": true, diff --git a/src/_old/common/config/CodeCompletionConfig.ts b/src/_old/common/config/CodeCompletionConfig.ts deleted file mode 100644 index 617bea6..0000000 --- a/src/_old/common/config/CodeCompletionConfig.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Uri } from 'vscode'; - -/** - * Configuration interface for the code outline feature. - * - * @export - * @interface CodeCompletionConfig - */ -export interface CodeCompletionConfig { - /** - * The given resource URI (if any) for the actual configuration. - * Is needed to determine the actual config values for multi root environments. - * - * @readonly - * @type {Uri} - * @memberof CodeCompletionConfig - */ - resource?: Uri; - - /** - * Defines the used completion sort mode (i.e. if the completions should be sorted to the bottom of the list). - * - * @readonly - * @type {('default' | 'bottom')} - * @memberof CodeCompletionConfig - */ - completionSortMode: 'default' | 'bottom'; -} diff --git a/src/_old/common/config/CodeOutlineConfig.ts b/src/_old/common/config/CodeOutlineConfig.ts deleted file mode 100644 index e6c5aee..0000000 --- a/src/_old/common/config/CodeOutlineConfig.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Uri } from 'vscode'; - -/** - * Configuration interface for the code outline feature. - * - * @export - * @interface CodeOutlineConfig - */ -export interface CodeOutlineConfig { - /** - * The given resource URI (if any) for the actual configuration. - * Is needed to determine the actual config values for multi root environments. - * - * @readonly - * @type {Uri} - * @memberof CodeOutlineConfig - */ - resource?: Uri; - - /** - * Defined if the code outline feature is enabled or not. - * - * @type {boolean} - * @memberof CodeOutlineConfig - */ - outlineEnabled: boolean; -} diff --git a/src/_old/common/config/ExtensionConfig.ts b/src/_old/common/config/ExtensionConfig.ts deleted file mode 100644 index 22e0e6c..0000000 --- a/src/_old/common/config/ExtensionConfig.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Uri } from 'vscode'; - -import { CodeCompletionConfig } from './CodeCompletionConfig'; -import { CodeOutlineConfig } from './CodeOutlineConfig'; -import { ResolverConfig } from './ResolverConfig'; - -/** - * Configuration interface for TypeScript Hero - * Contains all exposed config endpoints. - * - * @export - * @interface ExtensionConfig - */ -export interface ExtensionConfig { - /** - * The given resource URI (if any) for the actual configuration. - * Is needed to determine the actual config values for multi root environments. - * - * @readonly - * @type {Uri} - * @memberof ExtensionConfig - */ - resource?: Uri; - - /** - * The actual log level. - * - * @readonly - * @type {'error' | 'warn' | 'info' | 'debug'} - * @memberof ExtensionConfig - */ - verbosity: 'error' | 'warn' | 'info' | 'debug'; - - /** - * Returns a list of possible language IDs that are registered within this extension. - * - * @type {string[]} - * @memberof ExtensionConfig - */ - possibleLanguages: string[]; - - /** - * Configuration object for the resolver extension. - * - * @readonly - * @type {ResolverConfig} - * @memberof ExtensionConfig - */ - resolver: ResolverConfig; - - /** - * Configuration object for the code outline extension. - * - * @readonly - * @type {CodeOutlineConfig} - * @memberof ExtensionConfig - */ - codeOutline: CodeOutlineConfig; - - /** - * Configuration object for the code completion extension. - * - * @readonly - * @type {CodeCompletionConfig} - * @memberof ExtensionConfig - */ - codeCompletion: CodeCompletionConfig; -} diff --git a/src/_old/common/config/ResolverConfig.ts b/src/_old/common/config/ResolverConfig.ts deleted file mode 100644 index 9edae74..0000000 --- a/src/_old/common/config/ResolverConfig.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { TypescriptGenerationOptions } from 'typescript-parser'; -import { Uri } from 'vscode'; - -import { ImportGroup } from '../../extension/import-grouping'; -import { ResolverMode } from '../enums'; - -/** - * Configuration interface for the resolver extension. - * - * @interface ResolverConfig - */ -export interface ResolverConfig { - /** - * The given resource URI (if any) for the actual configuration. - * Is needed to determine the actual config values for multi root environments. - * - * @readonly - * @type {Uri} - * @memberof ResolverConfig - */ - resource?: Uri; - - /** - * Defines, if there should be a space between the brace and the import specifiers. - * {Symbol} vs { Symbol } - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - */ - insertSpaceBeforeAndAfterImportBraces: boolean; - - /** - * Defines, if there should be a semicolon at the end of a statement. - * import Symbol from 'symbol' vs import Symbol from 'symbol'; - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - */ - insertSemicolons: boolean; - - /** - * Defines the quote style (' or "). - * - * @readonly - * @type {string} - * @memberof ResolverConfig - */ - stringQuoteStyle: string; - - /** - * Array of string that are excluded from indexing of the workspace (e.g. build, out, dist). - * This patterns are ignored during indexing of the files found in the workspace. - * To exclude other files that are found in the node_modules, use moduleIgnorePatterns. - * - * @readonly - * @type {string[]} - * @memberof ResolverConfig - */ - workspaceIgnorePatterns: string[]; - - /** - * Array of string that are excluded from indexing of the modules (e.g. further node_modules). - * This patterns are ignored during indexing of the files found in the workspace. - * To exclude other files that are found in the node_modules, use moduleIgnorePatterns. - * - * @readonly - * @type {string[]} - * @memberof ResolverConfig - */ - moduleIgnorePatterns: string[]; - - /** - * A length number after which the import is transformed into a multiline import. - * - * @readonly - * @type {number} - * @memberof ResolverConfig - */ - multiLineWrapThreshold: number; - - /** - * If a multiline named import should contain the last trailing comma. - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - * - * @example - * import { - * Foo, - * Bar, << - * } from 'whatever'; - */ - multiLineTrailingComma: boolean; - - /** - * Returns the tab size that is configured in vscode. - * - * @readonly - * @type {number} - * @memberof ResolverConfig - */ - tabSize: number; - - /** - * Disables sorting of the imports on organize. - * - * @type {boolean} - * @memberof ResolverConfig - */ - disableImportSorting: boolean; - - /** - * Disables removal of the unsed imports on organize. - * - * @type {boolean} - * @memberof ResolverConfig - */ - disableImportRemovalOnOrganize: boolean; - - /** - * List of import libraries ("from" part) which are ignored during the organize import function. - * - * @type {string[]} - * @memberof ResolverConfig - */ - ignoreImportsForOrganize: string[]; - - /** - * Returns the configured import groups. On a parsing error, a default should be provided. - * - * @type {ImportGroup[]} - * @memberof ResolverConfig - */ - importGroups: ImportGroup[]; - - /** - * All information that are needed to print an import. - * - * @readonly - * @type {TypescriptGenerationOptions} - * @memberof ResolverConfig - */ - generationOptions: TypescriptGenerationOptions; - - /** - * Current mode of the resolver. - * - * @type {ResolverMode} - * @memberof ResolverConfig - */ - resolverMode: ResolverMode; - - /** - * Returns a list of file globs for the actual set resolver mode. - * - * @example `TypeScript` - * Will return: ['\*\*\/\*.ts', '\*\*\/\*.tsx'] - * - * @example `ES6` - * Will return: ['\*\*\/\*.js', '\*\*\/\*.jsx'] - * - * @type {string[]} - * @memberof ResolverConfig - */ - resolverModeFileGlobs: string[]; - - /** - * Returns a list of usable languages for the set resolver mode. - * - * @example `TypeScript` - * Will return: ['typescript', 'typescriptreact'] - * - * @type {string[]} - * @memberof ResolverConfig - */ - resolverModeLanguages: string[]; - - /** - * Sorts imports by first specifier / alias / default alias (when available), - * instead of by library names (module paths). - * - * @type {boolean} - * @memberof ResolverConfig - */ - organizeSortsByFirstSpecifier: boolean; - - /** - * Defines if typescript hero tries to organize your imports of a - * file as soon as the file would be saved. - * - * @type {boolean} - * @memberof ResolverConfig - */ - organizeOnSave: boolean; - - /** - * Defines if typescript hero should ask the user for default specifiers or duplicate specifier aliases. - * If true, tsh does ask the user. - * - * @type {boolean} - * @memberof ResolverConfig - */ - promptForSpecifiers: boolean; -} diff --git a/src/_old/common/config/index.ts b/src/_old/common/config/index.ts deleted file mode 100644 index 04b8fa7..0000000 --- a/src/_old/common/config/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './ExtensionConfig'; -export * from './ResolverConfig'; -export * from './CodeOutlineConfig'; -export * from './CodeCompletionConfig'; diff --git a/src/_old/common/enums.ts b/src/_old/common/enums.ts deleted file mode 100644 index fbd393d..0000000 --- a/src/_old/common/enums.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Enum to describe the actual mode that the symbol resolver is set in. - * - * @export - * @enum {number} - */ -export enum ResolverMode { - TypeScript, - ES6, - Both, -} diff --git a/src/_old/common/errors/ClassNotFoundError.ts b/src/_old/common/errors/ClassNotFoundError.ts deleted file mode 100644 index 460c4c9..0000000 --- a/src/_old/common/errors/ClassNotFoundError.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This error is thrown, when a class manager does not find the searched class in the given document. - * - * @export - * @class ClassNotFoundError - * @extends {Error} - */ -export class ClassNotFoundError extends Error { - constructor(className: string) { - super(); - this.message = `The class "${className}" was not found in the given document.`; - } -} diff --git a/src/_old/common/errors/MethodDuplicatedError.ts b/src/_old/common/errors/MethodDuplicatedError.ts deleted file mode 100644 index 82bc179..0000000 --- a/src/_old/common/errors/MethodDuplicatedError.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Thrown when a method should be added to a virtual class that is already present. - * - * @export - * @class MethodDuplicated - * @extends {Error} - */ -export class MethodDuplicated extends Error { - constructor(methodName: string, parent: string) { - super(); - this.message = `The method "${methodName}" is duplicated in "${parent}".`; - } -} diff --git a/src/_old/common/errors/MethodNotFoundError.ts b/src/_old/common/errors/MethodNotFoundError.ts deleted file mode 100644 index 31932c4..0000000 --- a/src/_old/common/errors/MethodNotFoundError.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Thrown when a method should be removed that does not exist on the virtual class. - * - * @export - * @class MethodNotFound - * @extends {Error} - */ -export class MethodNotFound extends Error { - constructor(methodName: string, parent?: string) { - super(); - this.message = `The method "${methodName}" was not found${parent ? ` in "${parent}"` : ''}.`; - } -} diff --git a/src/_old/common/errors/NotImplementedYetError.ts b/src/_old/common/errors/NotImplementedYetError.ts deleted file mode 100644 index a6f2691..0000000 --- a/src/_old/common/errors/NotImplementedYetError.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Error that should be thrown, when a feature is not implemented yet. - * - * @export - * @class NotImplementedYetError - * @extends {Error} - */ -export class NotImplementedYetError extends Error { - constructor() { - super(); - this.message = 'This feature is not yet implemented.'; - } -} diff --git a/src/_old/common/errors/PropertyDuplicatedError.ts b/src/_old/common/errors/PropertyDuplicatedError.ts deleted file mode 100644 index 8b19de9..0000000 --- a/src/_old/common/errors/PropertyDuplicatedError.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This error is thrown, when a property should be added to a virtual class that is already present. - * - * @export - * @class PropertyDuplicated - * @extends {Error} - */ -export class PropertyDuplicated extends Error { - constructor(propName: string, parent: string) { - super(); - this.message = `The property "${propName}" is duplicated in "${parent}".`; - } -} diff --git a/src/_old/common/errors/PropertyNotFoundError.ts b/src/_old/common/errors/PropertyNotFoundError.ts deleted file mode 100644 index 3bda5e0..0000000 --- a/src/_old/common/errors/PropertyNotFoundError.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Thrown when a property does not exist on a virtual class. - * - * @export - * @class PropertyNotFound - * @extends {Error} - */ -export class PropertyNotFound extends Error { - constructor(propName: string, parent?: string) { - super(); - this.message = `The property "${propName}" was not found${parent ? ` in "${parent}"` : ''}.`; - } -} diff --git a/src/_old/common/errors/index.ts b/src/_old/common/errors/index.ts deleted file mode 100644 index a02f7af..0000000 --- a/src/_old/common/errors/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './ClassNotFoundError'; -export * from './MethodDuplicatedError'; -export * from './MethodNotFoundError'; -export * from './NotImplementedYetError'; -export * from './PropertyDuplicatedError'; -export * from './PropertyNotFoundError'; diff --git a/src/_old/common/factories/index.ts b/src/_old/common/factories/index.ts deleted file mode 100644 index 3b2f7ee..0000000 --- a/src/_old/common/factories/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TypescriptCodeGenerator } from 'typescript-parser'; -import { Uri } from 'vscode'; - -import { ExtensionConfig } from '../config'; - -/** - * IOC Factory for the {TypescriptCodeGenerator}. - */ -export type TypescriptCodeGeneratorFactory = () => TypescriptCodeGenerator; - -export type ConfigFactory = (resource?: Uri) => ExtensionConfig; diff --git a/src/_old/common/helpers/DeclarationIndexHelpers.ts b/src/_old/common/helpers/DeclarationIndexHelpers.ts deleted file mode 100644 index 8b13789..0000000 --- a/src/_old/common/helpers/DeclarationIndexHelpers.ts +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/_old/common/helpers/ImportHelpers.ts b/src/_old/common/helpers/ImportHelpers.ts deleted file mode 100644 index 8b13789..0000000 --- a/src/_old/common/helpers/ImportHelpers.ts +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/_old/common/helpers/index.ts b/src/_old/common/helpers/index.ts deleted file mode 100644 index 371a938..0000000 --- a/src/_old/common/helpers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './DeclarationIndexHelpers'; -export * from './ImportHelpers'; diff --git a/src/_old/common/quick-pick-items/index.ts b/src/_old/common/quick-pick-items/index.ts deleted file mode 100644 index c26492c..0000000 --- a/src/_old/common/quick-pick-items/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ResolveQuickPickItem'; diff --git a/src/_old/extension/IoC.ts b/src/_old/extension/IoC.ts deleted file mode 100644 index 9c540e5..0000000 --- a/src/_old/extension/IoC.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Container as IoCContainer, interfaces } from 'inversify'; -import inversifyInjectDecorators from 'inversify-inject-decorators'; -import { TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { ExtensionContext, Uri } from 'vscode'; - -import { ExtensionConfig } from '../common/config'; -import { ConfigFactory } from '../common/factories'; -import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; -import { VscodeExtensionConfig } from './config/VscodeExtensionConfig'; -import { BaseExtension } from './extensions/BaseExtension'; -import { CodeActionExtension } from './extensions/CodeActionExtension'; -import { CodeCompletionExtension } from './extensions/CodeCompletionExtension'; -import { DocumentSymbolStructureExtension } from './extensions/DocumentSymbolStructureExtension'; -import { ImportResolveExtension } from './extensions/ImportResolveExtension'; -import { OrganizeImportsOnSaveExtension } from './extensions/OrganizeImportsOnSaveExtension'; -import { iocSymbols } from './IoCSymbols'; -import { TypeScriptHero } from './TypeScriptHero'; -import { DeclarationIndexMapper } from './utilities/DeclarationIndexMapper'; -import winstonLogger, { Logger } from './utilities/winstonLogger'; - -const container = new IoCContainer(); - -container.bind(TypeScriptHero).to(TypeScriptHero).inSingletonScope(); - -container.bind(iocSymbols.declarationIndexMapper).to(DeclarationIndexMapper).inSingletonScope(); - -container - .bind(iocSymbols.typescriptParser) - .toConstantValue(new TypescriptParser()); - -container - .bind>(iocSymbols.generatorFactory) - .toFactory((context: interfaces.Context) => { - return (resource?: Uri) => { - const configFactory = context.container.get(iocSymbols.configuration); - return new TypescriptCodeGenerator(configFactory(resource).resolver.generationOptions); - }; - }); - -container - .bind>(iocSymbols.configuration) - .toFactory(() => (resource?: Uri) => new VscodeExtensionConfig(resource)); - -// Extensions -container.bind(iocSymbols.extensions).to(ImportResolveExtension).inSingletonScope(); -container.bind(iocSymbols.extensions).to(CodeCompletionExtension).inSingletonScope(); -container.bind(iocSymbols.extensions).to(DocumentSymbolStructureExtension).inSingletonScope(); -container.bind(iocSymbols.extensions).to(CodeActionExtension).inSingletonScope(); -container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExtension).inSingletonScope(); - -// Logging -container - .bind(iocSymbols.logger) - .toDynamicValue((context: interfaces.Context) => { - const extContext = context.container.get(iocSymbols.extensionContext); - const config = context.container.get(iocSymbols.configuration)(); - return winstonLogger(config.verbosity, extContext); - }) - .inSingletonScope(); - -// Code Action Extension (action creators) -container.bind(iocSymbols.codeActionCreators).to(MissingImportCreator); -container.bind(iocSymbols.codeActionCreators).to(MissingImplementationInClassCreator); - -/** - * Injection container. IoC baby. - */ -export const Container = container; - -/** - * IocDecorators to lazy inject stuff into properties or something. Useful when normal injection via the - * constructor is not possible. - */ -export const IocDecorators = inversifyInjectDecorators(container); diff --git a/src/_old/extension/IoCSymbols.ts b/src/_old/extension/IoCSymbols.ts deleted file mode 100644 index aac9c1f..0000000 --- a/src/_old/extension/IoCSymbols.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * List of usable symbols for IoC. - */ -export const iocSymbols = { - configuration: Symbol('config'), - extensionContext: Symbol('context'), - extensions: Symbol('extensions'), - logger: Symbol('logger'), - generatorFactory: Symbol('generatorFactory'), - codeActionCreators: Symbol('codeActionCreators'), - declarationIndexMapper: Symbol('declarationIndexMapper'), - typescriptParser: Symbol('typescriptParser'), -}; diff --git a/src/_old/extension/TypeScriptHero.ts b/src/_old/extension/TypeScriptHero.ts deleted file mode 100644 index 53b7e78..0000000 --- a/src/_old/extension/TypeScriptHero.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { inject, injectable, multiInject } from 'inversify'; -import { Disposable } from 'vscode'; - -import { BaseExtension } from './extensions/BaseExtension'; -import { iocSymbols } from './IoCSymbols'; -import { Logger } from './utilities/winstonLogger'; - -/** - * TypeScript Hero vscode extension. - * Central entrypoint. - * - * @export - * @class TypeScriptHero - * @implements {Disposable} - */ -@injectable() -export class TypeScriptHero implements Disposable { - constructor( - @inject(iocSymbols.logger) private logger: Logger, - @multiInject(iocSymbols.extensions) private extensions: BaseExtension[], - ) { - this.logger.debug('[%s] activation event, initializing', TypeScriptHero.name); - this.extensions.forEach(o => o.initialize()); - this.logger.info('[%s] initialized', TypeScriptHero.name); - } - - /** - * Disposes TypeScript Hero. - * - * @memberof TypeScriptHero - */ - public dispose(): void { - this.logger.debug('[%s] deactivation event, disposing', TypeScriptHero.name); - for (const ext of this.extensions) { - ext.dispose(); - } - this.logger.info('[%s] disposed', TypeScriptHero.name); - } -} diff --git a/src/_old/extension/code-actions/CodeAction.ts b/src/_old/extension/code-actions/CodeAction.ts deleted file mode 100644 index bf55f73..0000000 --- a/src/_old/extension/code-actions/CodeAction.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { - ClassLikeDeclaration, - DeclarationIndex, - DeclarationInfo, - DeclarationVisibility, - GenericDeclaration, -} from 'typescript-parser'; -import { TextDocument } from 'vscode'; - -import { Container } from '../IoC'; -import { iocSymbols } from '../IoCSymbols'; -import { ClassManager } from '../managers/ClassManager'; -import { ImportManager } from '../managers/ImportManager'; -import { Logger } from '../utilities/winstonLogger'; - -/** - * Interface for all codeactions that are generated by the typescript code action provider. - * - * @export - * @interface CodeAction - */ -export interface CodeAction { - - /** - * Executes the code action. Depending on the action, there are several actions performed. - * - * @returns {Promise} - * - * @memberof CodeAction - */ - execute(): Promise; -} - -/** - * Code action that adds a missing import the the actual document. - * - * @export - * @class AddImportCodeAction - * @implements {CodeAction} - */ -export class AddImportCodeAction implements CodeAction { - private static get logger(): Logger { - return Container.get(iocSymbols.logger); - } - - constructor(private document: TextDocument, private importToAdd: DeclarationInfo) { } - - /** - * Executes the code action. Depending on the action, there are several actions performed. - * - * @returns {Promise} - * - * @memberof AddImportCodeAction - */ - public async execute(): Promise { - AddImportCodeAction.logger.debug( - '[%s] add import for declaration "%s"', - AddImportCodeAction.name, - this.importToAdd.declaration.name, - ); - const controller = await ImportManager.create(this.document); - return controller.addDeclarationImport(this.importToAdd).commit(); - } -} - -/** - * Code action that adds all missing imports to the actual document, based on the non-local usages. - * - * @export - * @class AddMissingImportsCodeAction - * @implements {CodeAction} - */ -export class AddMissingImportsCodeAction implements CodeAction { - private static get logger(): Logger { - return Container.get(iocSymbols.logger); - } - - constructor(private document: TextDocument, private resolveIndex: DeclarationIndex) { } - - /** - * Executes the code action. Depending on the action, there are several actions performed. - * - * @returns {Promise} - * - * @memberof AddMissingImportsCodeAction - */ - public async execute(): Promise { - AddMissingImportsCodeAction.logger.debug( - '[%s] add all missing imports for document "%s"', - AddMissingImportsCodeAction.name, - this.document.fileName, - ); - const controller = await ImportManager.create(this.document); - return controller.addMissingImports(this.resolveIndex).commit(); - } -} - -/** - * Code action that does literally nothing. Is used to "communicate" with the user. E.g. if - * an import cannot be resolved, the lightbulb will show "cannot resolve ". - * - * @export - * @class NoopCodeAction - * @implements {CodeAction} - */ -export class NoopCodeAction implements CodeAction { - /** - * Executes the code action. Depending on the action, there are several actions performed. - * - * @returns {Promise} - * - * @memberof NoopCodeAction - */ - public execute(): Promise { - return Promise.resolve(true); - } -} - -/** - * Code action that does implement missing properties and methods from interfaces or abstract classes. - * - * @export - * @class ImplementPolymorphElements - * @implements {CodeAction} - */ -export class ImplementPolymorphElements implements CodeAction { - private static get logger(): Logger { - return Container.get(iocSymbols.logger); - } - - constructor( - private document: TextDocument, - private managedClass: string, - private polymorphObject: ClassLikeDeclaration & GenericDeclaration, - private typeParameterMappings?: { [type: string]: string }, - ) { } - - /** - * Executes the code action. Depending on the action, there are several actions performed. - * - * @returns {Promise} - * - * @memberof ImplementPolymorphElements - */ - public async execute(): Promise { - ImplementPolymorphElements.logger.debug( - '[%s] implement polymorph elements for class "%s"', - ImplementPolymorphElements.name, - this.managedClass, - { file: this.document.fileName }, - ); - const controller = await ClassManager.create(this.document, this.managedClass); - let typeKeys; - - if (this.typeParameterMappings) { - typeKeys = Object.keys(this.typeParameterMappings); - } - - for (const property of this.polymorphObject.properties.filter(o => !controller.hasProperty(o.name))) { - if (!property.visibility) { - property.visibility = DeclarationVisibility.Public; - } - if (this.typeParameterMappings) { - const type = property.type || ''; - if (typeKeys.indexOf(type) >= 0) { - property.type = this.typeParameterMappings[type]; - } - } - controller.addProperty(property); - } - - for (const method of this.polymorphObject.methods.filter(o => !controller.hasMethod(o.name) && o.isAbstract)) { - if (!method.visibility) { - method.visibility = DeclarationVisibility.Public; - } - if (this.typeParameterMappings) { - const type = method.type || ''; - if (typeKeys.indexOf(type) >= 0) { - method.type = this.typeParameterMappings[type]; - } - for (const param of method.parameters) { - const paramType = param.type || ''; - if (typeKeys.indexOf(paramType) >= 0) { - param.type = this.typeParameterMappings[paramType]; - } - } - } - controller.addMethod(method); - } - - return controller.commit(); - } -} diff --git a/src/_old/extension/code-actions/CodeActionCreator.ts b/src/_old/extension/code-actions/CodeActionCreator.ts deleted file mode 100644 index d026d49..0000000 --- a/src/_old/extension/code-actions/CodeActionCreator.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { CodeAction } from './CodeAction'; -import { injectable } from 'inversify'; -import { Command, Diagnostic, TextDocument } from 'vscode'; - -/** - * Interface for a action creator. A creator is registered in the code action extension and does create - * commands out of a diagnostic. - * - * @export - * @abstract - * @class CodeActionCreator - */ -@injectable() -export abstract class CodeActionCreator { - /** - * Determines if the given diagnostic can be handled by this creator. - * - * @param {Diagnostic} diagnostic - * @returns {boolean} - * - * @memberof CodeActionCreator - */ - public abstract canHandleDiagnostic(diagnostic: Diagnostic): boolean; - - /** - * Handles the given diagnostic. Must return an array of commands that are given to the light bulb. - * - * @param {TextDocument} document The commands that are created until now - * @param {Command[]} commands The commands that are created until now - * @param {Diagnostic} diagnostic The diagnostic to handle - * @returns {Promise} - * - * @memberof CodeActionCreator - */ - public abstract handleDiagnostic( - document: TextDocument, - commands: Command[], - diagnostic: Diagnostic, - ): Promise; - - /** - * Creates a customized command for the lightbulb with the correct strings. - * - * @private - * @param {string} title - * @param {CodeAction} codeAction - * @returns {Command} - * - * @memberof CodeActionCreator - */ - protected createCommand(title: string, codeAction: CodeAction): Command { - return { - title, - arguments: [codeAction], - command: 'typescriptHero.codeFix.executeCodeAction', - }; - } -} diff --git a/src/_old/extension/code-actions/MissingImplementationInClassCreator.ts b/src/_old/extension/code-actions/MissingImplementationInClassCreator.ts deleted file mode 100644 index 9e2692b..0000000 --- a/src/_old/extension/code-actions/MissingImplementationInClassCreator.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { ClassLikeDeclaration, GenericDeclaration, NamedImport, TypescriptParser } from 'typescript-parser'; -import { Command, Diagnostic, TextDocument, workspace } from 'vscode'; - -import { getAbsolutLibraryName } from '../../common/helpers'; -import { iocSymbols } from '../IoCSymbols'; -import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; -import { getScriptKind } from '../utilities/utilityFunctions'; -import { Logger } from '../utilities/winstonLogger'; -import { ImplementPolymorphElements, NoopCodeAction } from './CodeAction'; -import { CodeActionCreator } from './CodeActionCreator'; - -const REGEX_GENERICS = /^(.*)<(.*)>$/; -const REGEX_INCORRECT_IMPL = /class (['"])(.*)\1 incorrectly implements.*(['"])(.*)\3\./i; -const REGEX_NON_ABSTRACT_IMPL = /non-abstract class (['"])(.*)\1.*implement inherited.*from class (['"])(.*)\3\./i; - -/** - * Action creator that handles missing implementations in a class. - * - * @export - * @class MissingImplementationInClassCreator - * @extends {CodeActionCreator} - */ -@injectable() -export class MissingImplementationInClassCreator extends CodeActionCreator { - constructor( - @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - @inject(iocSymbols.logger) private logger: Logger, - ) { - super(); - } - - /** - * Determines if the given diagnostic can be handled by this creator. - * - * @param {Diagnostic} diagnostic - * @returns {boolean} - * - * @memberof MissingImplementationInClassCreator - */ - public canHandleDiagnostic(diagnostic: Diagnostic): boolean { - return REGEX_INCORRECT_IMPL.test(diagnostic.message) || - REGEX_NON_ABSTRACT_IMPL.test(diagnostic.message); - } - - /** - * Handles the given diagnostic. Must return an array of commands that are given to the light bulb. - * - * @param {TextDocument} document The commands that are created until now - * @param {Command[]} commands The commands that are created until now - * @param {Diagnostic} diagnostic The diagnostic to handle - * @returns {Promise} - * - * @memberof MissingImplementationInClassCreator - */ - public async handleDiagnostic(document: TextDocument, commands: Command[], diagnostic: Diagnostic): Promise { - const match = REGEX_INCORRECT_IMPL.exec(diagnostic.message) || - REGEX_NON_ABSTRACT_IMPL.exec(diagnostic.message); - - const index = this.indices.getIndexForFile(document.uri); - const rootFolder = workspace.getWorkspaceFolder(document.uri); - - if (!match || !index || !rootFolder) { - this.logger.debug( - '[%s] cannot handle the diagnostic', - MissingImplementationInClassCreator.name, - ); - return commands; - } - - let specifier = match[4]; - let types: string[] | undefined; - let typeParams: { [type: string]: string } | undefined; - const genericMatch = REGEX_GENERICS.exec(specifier); - - if (genericMatch) { - specifier = genericMatch[1]; - types = genericMatch[2].split(',').map(t => t.trim()); - } - - const parsedDocument = await this.parser.parseSource(document.getText(), getScriptKind(document.fileName)); - const alreadyImported = parsedDocument.imports.find( - o => o instanceof NamedImport && o.specifiers.some(s => s.specifier === specifier), - ); - const declaration = (parsedDocument.declarations.find(o => o.name === specifier) || - (index.declarationInfos.find( - o => o.declaration.name === specifier && - o.from === getAbsolutLibraryName(alreadyImported!.libraryName, document.fileName, rootFolder.uri.fsPath), - ) || { declaration: undefined }).declaration) as (ClassLikeDeclaration & GenericDeclaration) | undefined; - - if (commands.some((o: Command) => o.title.indexOf(specifier) >= 0)) { - // Do leave the method when a command with the found class is already added. - this.logger.debug( - '[%s] command with the found class is already added', - MissingImplementationInClassCreator.name, - ); - return commands; - } - - if (!declaration) { - this.logger.debug( - '[%s] class definition not found in the index', - MissingImplementationInClassCreator.name, - { specifier }, - ); - commands.push(this.createCommand( - `Cannot find "${specifier}" in the index or the actual file.`, - new NoopCodeAction(), - )); - return commands; - } - - if (genericMatch && declaration.typeParameters && types) { - typeParams = {}; - for (const typeParam of declaration.typeParameters) { - typeParams[typeParam] = types[declaration.typeParameters.indexOf(typeParam)]; - } - } - - commands.push(this.createCommand( - `Implement missing elements from "${genericMatch && types ? `${specifier}<${types.join(', ')}>` : specifier}".`, - new ImplementPolymorphElements(document, match[2], declaration, typeParams), - )); - - this.logger.debug( - '[%s] adding commands to handle missing implementation', - MissingImplementationInClassCreator.name, - { specifier, types }, - ); - - return commands; - } -} diff --git a/src/_old/extension/code-actions/MissingImportCreator.ts b/src/_old/extension/code-actions/MissingImportCreator.ts deleted file mode 100644 index 684b510..0000000 --- a/src/_old/extension/code-actions/MissingImportCreator.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Logger } from '../utilities/winstonLogger'; -import { inject, injectable } from 'inversify'; -import { Command, Diagnostic, TextDocument } from 'vscode'; - -import { iocSymbols } from '../IoCSymbols'; -import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; -import { AddImportCodeAction, AddMissingImportsCodeAction, NoopCodeAction } from './CodeAction'; -import { CodeActionCreator } from './CodeActionCreator'; - -const REGEX_CANNOT_FIND_IMPORT = /cannot find name (['"])(.*)\1/i; - -/** - * Action creator that handles missing imports in files. - * - * @export - * @class MissingImportCreator - * @extends {CodeActionCreator} - */ -@injectable() -export class MissingImportCreator extends CodeActionCreator { - constructor( - @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - @inject(iocSymbols.logger) private logger: Logger, - ) { - super(); - } - - /** - * Determines if the given diagnostic can be handled by this creator. - * - * @param {Diagnostic} diagnostic - * @returns {boolean} - * - * @memberof MissingImportCreator - */ - public canHandleDiagnostic(diagnostic: Diagnostic): boolean { - return REGEX_CANNOT_FIND_IMPORT.test(diagnostic.message); - } - - /** - * Handles the given diagnostic. Must return an array of commands that are given to the light bulb. - * - * @param {TextDocument} document The commands that are created until now - * @param {Command[]} commands The commands that are created until now - * @param {Diagnostic} diagnostic The diagnostic to handle - * @returns {Promise} - * - * @memberof MissingImportCreator - */ - public async handleDiagnostic(document: TextDocument, commands: Command[], diagnostic: Diagnostic): Promise { - const match = REGEX_CANNOT_FIND_IMPORT.exec(diagnostic.message); - const index = this.indices.getIndexForFile(document.uri); - - if (!match || !index) { - this.logger.debug( - '[%s] cannot handle the diagnostic', - MissingImportCreator.name, - ); - return commands; - } - - const infos = index.declarationInfos.filter(o => o.declaration.name === match[2]); - if (infos.length > 0) { - for (const info of infos) { - commands.push(this.createCommand( - `Import "${info.declaration.name}" from "${info.from}".`, - new AddImportCodeAction(document, info), - )); - this.logger.debug( - '[%s] add command to import missing specifier', - MissingImportCreator.name, - { symbol: info.declaration.name, library: info.from }, - ); - } - if ( - !commands.some(o => - o.arguments !== undefined && - o.arguments.some(a => a instanceof AddMissingImportsCodeAction), - ) - ) { - commands.push(this.createCommand( - 'Add all missing imports if possible.', - new AddMissingImportsCodeAction(document, index), - )); - this.logger.debug( - '[%s] add "import all missing imports" command', - MissingImportCreator.name, - ); - } - } else { - commands.push(this.createCommand( - `Cannot find "${match[2]}" in the index.`, - new NoopCodeAction(), - )); - this.logger.debug( - '[%s] class not found in index', - MissingImportCreator.name, - { specifier: match[2] }, - ); - } - - return commands; - } -} diff --git a/src/_old/extension/code-actions/index.ts b/src/_old/extension/code-actions/index.ts deleted file mode 100644 index 7884414..0000000 --- a/src/_old/extension/code-actions/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './CodeAction'; -export * from './CodeActionCreator'; -export * from './MissingImportCreator'; -export * from './MissingImplementationInClassCreator'; diff --git a/src/_old/extension/config/VscodeCodeCompletionConfig.ts b/src/_old/extension/config/VscodeCodeCompletionConfig.ts deleted file mode 100644 index 634532e..0000000 --- a/src/_old/extension/config/VscodeCodeCompletionConfig.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Uri, workspace, WorkspaceConfiguration } from 'vscode'; - -import { CodeCompletionConfig } from '../../common/config'; - -const sectionKey = 'typescriptHero.codeCompletion'; - -/** - * Configuration interface for the code outline feature. - * - * @class VscodeCodeCompletionConfig - * @implements {CodeCompletionConfig} - */ -export class VscodeCodeCompletionConfig implements CodeCompletionConfig { - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey, this.resource); - } - - /** - * Defines the used completion sort mode (i.e. if the completions should be sorted to the bottom of the list). - * - * @readonly - * @type {'default'|'bottom'} - * @memberof VscodeCodeCompletionConfig - */ - public get completionSortMode(): 'default' | 'bottom' { - return this.workspaceSection.get<'default' | 'bottom'>('completionSortMode', 'default'); - } - - constructor(public readonly resource?: Uri) { } -} diff --git a/src/_old/extension/config/VscodeCodeOutlineConfig.ts b/src/_old/extension/config/VscodeCodeOutlineConfig.ts deleted file mode 100644 index 4d1db04..0000000 --- a/src/_old/extension/config/VscodeCodeOutlineConfig.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Uri, workspace, WorkspaceConfiguration } from 'vscode'; - -import { CodeOutlineConfig } from '../../common/config'; - -const sectionKey = 'typescriptHero.codeOutline'; - -/** - * Configuration interface for the code outline feature. - * - * @class VscodeCodeOutlineConfig - * @implements {CodeOutlineConfig} - */ -export class VscodeCodeOutlineConfig implements CodeOutlineConfig { - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey, this.resource); - } - - /** - * Defined if the code outline feature is enabled or not. - * - * @readonly - * @type {boolean} - * @memberof VscodeCodeOutlineConfig - */ - public get outlineEnabled(): boolean { - return this.workspaceSection.get('enabled', true); - } - - constructor(public readonly resource?: Uri) { } -} diff --git a/src/_old/extension/config/VscodeExtensionConfig.ts b/src/_old/extension/config/VscodeExtensionConfig.ts deleted file mode 100644 index 94fc225..0000000 --- a/src/_old/extension/config/VscodeExtensionConfig.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { injectable } from 'inversify'; -import { Uri, workspace, WorkspaceConfiguration } from 'vscode'; - -import { CodeCompletionConfig, CodeOutlineConfig, ExtensionConfig, ResolverConfig } from '../../common/config'; -import { VscodeCodeCompletionConfig } from './VscodeCodeCompletionConfig'; -import { VscodeCodeOutlineConfig } from './VscodeCodeOutlineConfig'; -import { VscodeResolverConfig } from './VscodeResolverConfig'; - -const sectionKey = 'typescriptHero'; - -/** - * Configuration class for TypeScript Hero - * Contains all exposed config endpoints. - * - * @export - * @class VscodeExtensionConfig - */ -@injectable() -export class VscodeExtensionConfig implements ExtensionConfig { - public readonly possibleLanguages: string[] = [ - 'typescript', - 'typescriptreact', - 'javascript', - 'javascriptreact', - ]; - - private resolverConfig: ResolverConfig; - private codeOutlineConfig: CodeOutlineConfig; - private codeCompletionConfig: CodeCompletionConfig; - - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey, this.resource); - } - - /** - * The actual log level. - * - * @readonly - * @type {'error' | 'warn' | 'info' | 'debug'} - * @memberof VscodeExtensionConfig - */ - public get verbosity(): 'error' | 'warn' | 'info' | 'debug' { - const verbosity = this.workspaceSection.get<'error' | 'warn' | 'info' | 'debug'>('verbosity', 'warn'); - if (['error', 'warn', 'info', 'debug'].indexOf(verbosity) < 0) { - return 'warn'; - } - return verbosity; - } - - /** - * Configuration object for the resolver extension. - * - * @readonly - * @type {ResolverConfig} - * @memberof VscodeExtensionConfig - */ - public get resolver(): ResolverConfig { - return this.resolverConfig; - } - - /** - * Configuration object for the code outline extension. - * - * @readonly - * @type {CodeOutlineConfig} - * @memberof VscodeExtensionConfig - */ - public get codeOutline(): CodeOutlineConfig { - return this.codeOutlineConfig; - } - - /** - * Configuration object for the code completion extension. - * - * @readonly - * @type {CodeCompletionConfig} - * @memberof VscodeExtensionConfig - */ - public get codeCompletion(): CodeCompletionConfig { - return this.codeCompletionConfig; - } - - constructor(public readonly resource?: Uri) { - this.codeCompletionConfig = new VscodeCodeCompletionConfig(resource); - this.codeOutlineConfig = new VscodeCodeOutlineConfig(resource); - this.resolverConfig = new VscodeResolverConfig(resource); - } -} - - diff --git a/src/_old/extension/config/VscodeResolverConfig.ts b/src/_old/extension/config/VscodeResolverConfig.ts deleted file mode 100644 index dd4bc35..0000000 --- a/src/_old/extension/config/VscodeResolverConfig.ts +++ /dev/null @@ -1,318 +0,0 @@ -import { TypescriptGenerationOptions } from 'typescript-parser'; -import { Uri, workspace, WorkspaceConfiguration } from 'vscode'; - -import { ResolverConfig } from '../../common/config'; -import { ResolverMode } from '../../common/enums'; -import { ImportGroup, ImportGroupSetting, ImportGroupSettingParser, RemainImportGroup } from '../import-grouping'; - -const sectionKey = 'typescriptHero.resolver'; - -/** - * Configuration class for the resolver extension. - * - * @class VscodeResolverConfig - */ -export class VscodeResolverConfig implements ResolverConfig { - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey, this.resource); - } - - /** - * Defines, if there should be a space between the brace and the import specifiers. - * {Symbol} vs { Symbol } - * - * @readonly - * @type {boolean} - * @memberof VscodeResolverConfig - */ - public get insertSpaceBeforeAndAfterImportBraces(): boolean { - return this.workspaceSection.get('insertSpaceBeforeAndAfterImportBraces', true); - } - - /** - * Defines, if there should be a semicolon at the end of a statement. - * import Symbol from 'symbol' vs import Symbol from 'symbol'; - * - * @readonly - * @type {boolean} - * @memberof VscodeResolverConfig - */ - public get insertSemicolons(): boolean { - return this.workspaceSection.get('insertSemicolons', true); - } - - /** - * Defines the quote style (' or "). - * - * @readonly - * @type {string} - * @memberof VscodeResolverConfig - */ - public get stringQuoteStyle(): string { - return this.workspaceSection.get('stringQuoteStyle', `'`); - } - - /** - * Array of string that are excluded from indexing of the workspace (e.g. build, out, dist). - * This patterns are ignored during indexing of the files found in the workspace. - * To exclude other files that are found in the node_modules, use moduleIgnorePatterns. - * - * @readonly - * @type {string[]} - * @memberof VscodeResolverConfig - */ - public get workspaceIgnorePatterns(): string[] { - return this.workspaceSection.get( - 'workspaceIgnorePatterns', - [ - '**/build/**/*', - '**/out/**/*', - '**/dist/**/*', - ], - ); - } - - /** - * Array of string that are excluded from indexing of the modules (e.g. further node_modules). - * This patterns are ignored during indexing of the files found in the workspace. - * To exclude other files that are found in the node_modules, use moduleIgnorePatterns. - * - * @readonly - * @type {string[]} - * @memberof VscodeResolverConfig - */ - public get moduleIgnorePatterns(): string[] { - return this.workspaceSection.get( - 'moduleIgnorePatterns', - [ - '**/node_modules/**/*', - ], - ); - } - - /** - * A length number after which the import is transformed into a multiline import. - * - * @readonly - * @type {number} - * @memberof VscodeResolverConfig - */ - public get multiLineWrapThreshold(): number { - return this.workspaceSection.get('multiLineWrapThreshold', 125); - } - - /** - * If a multiline named import should contain the last trailing comma. - * - * @readonly - * @type {boolean} - * @memberof VscodeResolverConfig - * - * @example - * import { - * Foo, - * Bar, << - * } from 'whatever'; - */ - public get multiLineTrailingComma(): boolean { - return this.workspaceSection.get('multiLineTrailingComma', true); - } - - /** - * Defines, if sorting is obligatory during organize imports - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - */ - public get disableImportSorting(): boolean { - return this.workspaceSection.get('disableImportsSorting', false); - } - - /** - * Defines, if removal unsed is obligatory during organize imports - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - */ - public get disableImportRemovalOnOrganize(): boolean { - return this.workspaceSection.get('disableImportRemovalOnOrganize', false); - } - - /** - * Returns the tab size that is configured in vscode. - * - * @readonly - * @type {number} - * @memberof VscodeResolverConfig - */ - public get tabSize(): number { - return workspace.getConfiguration().get('editor.tabSize', 4); - } - - /** - * Returns the list of imports that should be ignored during organize import feature. - * - * @readonly - * @type {string[]} - * @memberof VscodeResolverConfig - */ - public get ignoreImportsForOrganize(): string[] { - return this.workspaceSection.get('ignoreImportsForOrganize', []); - } - - /** - * Returns the configured import groups. On a parsing error, the default is used. - * - * @type {ImportGroup[]} - * @memberof VscodeResolverConfig - */ - public get importGroups(): ImportGroup[] { - const groups = this.workspaceSection.get('importGroups'); - let importGroups: ImportGroup[] = []; - - try { - if (groups) { - importGroups = groups.map(g => ImportGroupSettingParser.parseSetting(g)); - } else { - importGroups = ImportGroupSettingParser.default; - } - } catch (e) { - importGroups = ImportGroupSettingParser.default; - } - if (!importGroups.some(i => i instanceof RemainImportGroup)) { - importGroups.push(new RemainImportGroup()); - } - - return importGroups; - } - - /** - * All information that are needed to print an import. - * - * @readonly - * @type {TypescriptGenerationOptions} - * @memberof VscodeResolverConfig - */ - public get generationOptions(): TypescriptGenerationOptions { - return { - eol: this.insertSemicolons ? ';' : '', - multiLineWrapThreshold: this.multiLineWrapThreshold, - multiLineTrailingComma: this.multiLineTrailingComma, - spaceBraces: this.insertSpaceBeforeAndAfterImportBraces, - stringQuoteStyle: this.stringQuoteStyle, - tabSize: this.tabSize, - }; - } - - /** - * Current mode of the - * - * @readonly - * @type {ResolverMode} - * @memberof VscodeResolverConfig - */ - public get resolverMode(): ResolverMode { - const mode = this.workspaceSection.get('resolverMode', 'TypeScript'); - return ResolverMode[mode] || ResolverMode.TypeScript; - } - - /** - * Returns a list of file globs for the actual set resolver mode. - * - * @example `TypeScript` - * Will return: ['\*\*\/\*.ts', '\*\*\/\*.tsx'] - * - * @example `ES6` - * Will return: ['\*\*\/\*.js', '\*\*\/\*.jsx'] - * - * @type {string[]} - * @memberof VscodeResolverConfig - */ - public get resolverModeFileGlobs(): string[] { - const mode = this.resolverMode; - const globs: string[] = []; - - if (mode === ResolverMode.TypeScript || mode === ResolverMode.Both) { - globs.push('**/*.ts'); - globs.push('**/*.tsx'); - } - - if (mode === ResolverMode.ES6 || mode === ResolverMode.Both) { - globs.push('**/*.js'); - globs.push('**/*.jsx'); - } - - return globs; - } - - /** - * Returns a list of usable languages for the set resolver mode. - * - * @example `TypeScript` - * Will return: ['typescript', 'typescriptreact'] - * - * @readonly - * @type {string[]} - * @memberof VscodeResolverConfig - */ - public get resolverModeLanguages(): string[] { - const mode = this.resolverMode; - const languages: string[] = []; - - if (mode === ResolverMode.TypeScript || mode === ResolverMode.Both) { - languages.push('typescript'); - languages.push('typescriptreact'); - } - - if (mode === ResolverMode.ES6 || mode === ResolverMode.Both) { - languages.push('javascript'); - languages.push('javascriptreact'); - } - - return languages; - } - - /** - * Defines if typescript hero tries to organize your imports of a - * file as soon as the file would be saved. - * Is a combination between the editor.formatOnSave and the resolver settings. - * - * @readonly - * @type {boolean} - * @memberof VscodeResolverConfig - */ - public get organizeOnSave(): boolean { - const typescriptHeroValue = this.workspaceSection.get('organizeOnSave', false); - const editorValue = workspace.getConfiguration('editor', this.resource).get('formatOnSave', false); - return typescriptHeroValue && editorValue; - } - - /** - * Defines if typescript hero import organization (sorting) uses first - * available specifier/alias, when available, instead of library names - * (module paths). - * - * @readonly - * @type {boolean} - * @memberof VscodeResolverConfig - */ - public get organizeSortsByFirstSpecifier(): boolean { - return this.workspaceSection.get('organizeSortsByFirstSpecifier', false); - } - - /** - * Defines if typescript hero should ask the user for default specifiers or duplicate specifier aliases. - * If true, tsh does ask the user. - * - * @readonly - * @type {boolean} - * @memberof VscodeResolverConfig - */ - public get promptForSpecifiers(): boolean { - return this.workspaceSection.get('promptForSpecifiers', false); - } - - constructor(public readonly resource?: Uri) { } -} diff --git a/src/_old/extension/extension.ts b/src/_old/extension/extension.ts deleted file mode 100644 index 84aac90..0000000 --- a/src/_old/extension/extension.ts +++ /dev/null @@ -1,51 +0,0 @@ -import 'reflect-metadata'; - -import { GENERATORS, TypescriptCodeGenerator } from 'typescript-parser'; -import { Disposable, ExtensionContext } from 'vscode'; - -import { KeywordImportGroup, RegexImportGroup, RemainImportGroup } from './import-grouping'; -import { Container } from './IoC'; -import { iocSymbols } from './IoCSymbols'; -import { TypeScriptHero } from './TypeScriptHero'; - -let extension: Disposable; - -function extendGenerator(generator: TypescriptCodeGenerator): void { - function simpleGenerator(generatable: any): string { - const group = generatable as KeywordImportGroup; - if (!group.imports.length) { - return ''; - } - return group.sortedImports - .map(imp => generator.generate(imp)) - .join('\n') + '\n'; - } - - GENERATORS[KeywordImportGroup.name] = simpleGenerator; - GENERATORS[RegexImportGroup.name] = simpleGenerator; - GENERATORS[RemainImportGroup.name] = simpleGenerator; -} - -/** - * Activates TypeScript Hero - * - * @export - * @param {ExtensionContext} context - */ -export async function activate(context: ExtensionContext): Promise { - if (Container.isBound(iocSymbols.extensionContext)) { - Container.unbind(iocSymbols.extensionContext); - } - Container.bind(iocSymbols.extensionContext).toConstantValue(context); - extendGenerator(Container.get<() => TypescriptCodeGenerator>(iocSymbols.generatorFactory)()); - extension = Container.get(TypeScriptHero); -} - -/** - * Deactivates TypeScript Hero - * - * @export - */ -export function deactivate(): void { - extension.dispose(); -} diff --git a/src/_old/extension/extensions/BaseExtension.ts b/src/_old/extension/extensions/BaseExtension.ts deleted file mode 100644 index e7826d4..0000000 --- a/src/_old/extension/extensions/BaseExtension.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { injectable } from 'inversify'; -import { Disposable, ExtensionContext } from 'vscode'; - -/** - * Base extension class. Does provide the basic structure of an extension. - * - * @export - * @abstract - * @class BaseExtension - * @implements {Disposable} - */ -@injectable() -export abstract class BaseExtension implements Disposable { - /** - * Creates an instance of BaseExtension. - * - * @param {ExtensionContext} context - * - * @memberof BaseExtension - */ - constructor(protected readonly context: ExtensionContext) { } - - /** - * Initialize the extension. Should register disposables to the extension context - * and register commands and such operations. - * - * @abstract - * - * @memberof BaseExtension - */ - public abstract initialize(): void; - - /** - * Dispose the extension. - * - * @abstract - * - * @memberof BaseExtension - */ - public abstract dispose(): void; -} diff --git a/src/_old/extension/extensions/CodeActionExtension.ts b/src/_old/extension/extensions/CodeActionExtension.ts deleted file mode 100644 index 328e0c5..0000000 --- a/src/_old/extension/extensions/CodeActionExtension.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { inject, injectable, multiInject } from 'inversify'; -import { - CancellationToken, - CodeActionContext, - CodeActionProvider, - Command, - commands, - ExtensionContext, - languages, - Range, - TextDocument, - window, -} from 'vscode'; - -import { CodeAction } from '../code-actions/CodeAction'; -import { CodeActionCreator } from '../code-actions/CodeActionCreator'; -import { iocSymbols } from '../IoCSymbols'; -import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; -import { Logger } from '../utilities/winstonLogger'; -import { BaseExtension } from './BaseExtension'; - -/** - * Provider instance that is responsible for the "light bulb" feature. - * It provides actions to take when errors occur in the current document (such as missing imports or - * non implemented interfaces.). - * - * @export - * @class CodeActionExtension - * @implements {CodeActionProvider} - */ -@injectable() -export class CodeActionExtension extends BaseExtension implements CodeActionProvider { - constructor( - @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.logger) private logger: Logger, - @multiInject(iocSymbols.codeActionCreators) private actionCreators: CodeActionCreator[], - @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - ) { - super(context); - } - - /** - * Initialized the extension. Registers the commands and other disposables to the context. - * - * @memberof ImportResolveExtension - */ - public initialize(): void { - this.context.subscriptions.push(commands.registerCommand( - 'typescriptHero.codeFix.executeCodeAction', - (codeAction: CodeAction | undefined) => this.executeCodeAction(codeAction), - )); - this.context.subscriptions.push(languages.registerCodeActionsProvider('typescript', this)); - this.context.subscriptions.push(languages.registerCodeActionsProvider('typescriptreact', this)); - - this.logger.info('[%s] initialized', CodeActionCreator.name); - } - - /** - * Disposes the extension. - * - * @memberof ImportResolveExtension - */ - public dispose(): void { - this.logger.info('[%s] disposed', CodeActionCreator.name); - } - - /** - * Provides the commands to execute for a given problem. - * - * @param {TextDocument} document - * @param {Range} range - * @param {CodeActionContext} context - * @param {CancellationToken} token - * @returns {Promise} - * - * @memberof CodeActionExtension - */ - public async provideCodeActions( - document: TextDocument, - _range: Range, - context: CodeActionContext, - _token: CancellationToken, - ): Promise { - const index = this.indices.getIndexForFile(document.uri); - if (!index || !index.indexReady) { - return []; - } - - this.logger.debug( - '[%s] provide code actions for file', - CodeActionCreator.name, - { file: document.fileName }, - ); - const profiler = this.logger.startTimer(); - - let commands: Command[] = []; - for (const diagnostic of context.diagnostics) { - for (const creator of this.actionCreators) { - if (creator.canHandleDiagnostic(diagnostic)) { - commands = await creator.handleDiagnostic(document, commands, diagnostic); - } - } - } - - profiler.done({ message: `[${CodeActionCreator.name}] calculated diagnostics` }); - - return commands; - } - - /** - * Executes a code action. If the result is false, a warning is shown. - * - * @private - * @param {CodeAction} codeAction - * @returns {Promise} - * - * @memberof CodeFixExtension - */ - private async executeCodeAction(codeAction: CodeAction | undefined): Promise { - if (!codeAction) { - this.logger.warn('[%s] executeCodeAction used without param', CodeActionCreator.name); - window.showWarningMessage('This command is for internal use only. It cannot be used from Cmd+P'); - return; - } - if (!await codeAction.execute()) { - this.logger.warn('[%s] code action could not complete', CodeActionCreator.name, { codeAction }); - window.showWarningMessage('The provided code action could not complete. Please see the logs.'); - } - } -} diff --git a/src/_old/extension/extensions/CodeCompletionExtension.ts b/src/_old/extension/extensions/CodeCompletionExtension.ts deleted file mode 100644 index de090c8..0000000 --- a/src/_old/extension/extensions/CodeCompletionExtension.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; -import { - CancellationToken, - commands, - CompletionItem, - CompletionItemProvider, - ExtensionContext, - languages, - Position, - TextDocument, - workspace, -} from 'vscode'; - -import { ConfigFactory } from '../../common/factories'; -import { getDeclarationsFilteredByImports } from '../../common/helpers'; -import { iocSymbols } from '../IoCSymbols'; -import { ImportManager } from '../managers/ImportManager'; -import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; -import { getItemKind, getScriptKind } from '../utilities/utilityFunctions'; -import { Logger } from '../utilities/winstonLogger'; -import { BaseExtension } from './BaseExtension'; - -const REGEX_COMMENT = /^\s*(?:\/\/|\/\*\*|\*\/|\*)/; - -/** - * Extension that provides code completion for typescript files. Uses the calculated index to provide information. - * - * @export - * @class CodeCompletionExtension - * @extends {BaseExtension} - * @implements {CompletionItemProvider} - */ -@injectable() -export class CodeCompletionExtension extends BaseExtension implements CompletionItemProvider { - constructor( - @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.logger) private logger: Logger, - @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - @inject(iocSymbols.configuration) private config: ConfigFactory, - ) { - super(context); - } - - /** - * Initialized the extension. Registers the commands and other disposables to the context. - * - * @memberof CodeCompletionExtension - */ - public initialize(): void { - for (const lang of this.config().possibleLanguages) { - this.context.subscriptions.push(languages.registerCompletionItemProvider(lang, this)); - } - - this.context.subscriptions.push( - commands.registerCommand( - 'typescriptHero.codeCompletion.executeIntellisenseItem', - (document: TextDocument, declaration: DeclarationInfo) => - this.executeIntellisenseItem(document, declaration), - ), - ); - - this.logger.info('[%s] initialized', CodeCompletionExtension.name); - } - - /** - * Disposes the extension. - * - * @memberof CodeCompletionExtension - */ - public dispose(): void { - this.logger.info('[%s] disposed', CodeCompletionExtension.name); - } - - /** - * Provides completion items for a given position in the given document. - * - * @param {TextDocument} document - * @param {Position} position - * @param {CancellationToken} token - * @returns {Promise<(CompletionItem[] | null)>} - * - * @memberof CodeCompletionExtension - */ - public async provideCompletionItems( - document: TextDocument, - position: Position, - token: CancellationToken, - ): Promise { - const index = this.indices.getIndexForFile(document.uri); - const config = this.config(document.uri); - const rootFolder = workspace.getWorkspaceFolder(document.uri); - - if (!index || - !index.indexReady || - !config.resolver.resolverModeLanguages.some(lng => lng === document.languageId) || - !rootFolder - ) { - this.logger.debug('[%s] resolver not ready or no workspace folder selected', CodeCompletionExtension.name); - return null; - } - - const wordAtPosition = document.getWordRangeAtPosition(position); - const lineText = document.lineAt(position.line).text; - - let searchWord = ''; - - if (wordAtPosition && wordAtPosition.start.character < position.character) { - const word = document.getText(wordAtPosition); - searchWord = word.substr(0, position.character - wordAtPosition.start.character); - } - - if (!searchWord || - token.isCancellationRequested || - !index.indexReady || - (lineText.substring(0, position.character).match(/["'`]/g) || []).length % 2 === 1 || - REGEX_COMMENT.test(lineText) || - lineText.startsWith('import ') || - new RegExp(`(?:\w*\.)+${searchWord}`).test(lineText.substring(0, position.character))) { - this.logger.debug( - '[%s] did not match criteria to provide intellisense', - CodeCompletionExtension.name, - { searchWord, lineText, indexReady: index.indexReady }, - ); - return Promise.resolve(null); - } - - this.logger.debug( - '[%s] provide code completion for "%s"', - CodeCompletionExtension.name, - searchWord, - ); - const profiler = this.logger.startTimer(); - - const parsed = await this.parser.parseSource(document.getText(), getScriptKind(document.fileName)); - const declarations = getDeclarationsFilteredByImports( - index.declarationInfos, - document.fileName, - parsed.imports, - rootFolder.uri.fsPath, - ) - .filter(o => !parsed.declarations.some(d => d.name === o.declaration.name)) - .filter(o => !parsed.usages.some(d => d === o.declaration.name)); - - const items: CompletionItem[] = []; - for (const declaration of declarations.filter( - o => o.declaration.name.toLowerCase().indexOf(searchWord.toLowerCase()) >= 0) - ) { - const item = new CompletionItem(declaration.declaration.name, getItemKind(declaration.declaration)); - - item.detail = declaration.from; - item.command = { - arguments: [document, declaration], - title: 'Execute intellisense insert', - command: 'typescriptHero.codeCompletion.executeIntellisenseItem', - }; - if (config.codeCompletion.completionSortMode === 'bottom') { - item.sortText = `9999-${declaration.declaration.name}`; - } - items.push(item); - } - - profiler.done({ message: `[${CodeCompletionExtension.name}] calculated code completions` }); - return items; - } - - /** - * Executes a intellisense item that provided a document and a declaration to add. - * Does make the calculation of the text edits async. - * - * @private - * @param {TextDocument} document - * @param {DeclarationInfo} declaration - * @returns {Promise} - * @memberof CodeCompletionExtension - */ - private async executeIntellisenseItem(document: TextDocument, declaration: DeclarationInfo): Promise { - this.logger.debug( - '[%s] execute code completion action', - CodeCompletionExtension.name, - { specifier: declaration.declaration.name, library: declaration.from }, - ); - const manager = await ImportManager.create(document); - manager.addDeclarationImport(declaration); - await manager.commit(); - } -} diff --git a/src/_old/extension/extensions/DocumentSymbolStructureExtension.ts b/src/_old/extension/extensions/DocumentSymbolStructureExtension.ts deleted file mode 100644 index db01f4a..0000000 --- a/src/_old/extension/extensions/DocumentSymbolStructureExtension.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { File, Node, TypescriptParser } from 'typescript-parser'; -import { - commands, - Event, - EventEmitter, - ExtensionContext, - ProviderResult, - Selection, - TextEditorRevealType, - TreeDataProvider, - window, - workspace, -} from 'vscode'; - -import { ConfigFactory } from '../../common/factories'; -import { iocSymbols } from '../IoCSymbols'; -import { BaseStructureTreeItem } from '../provider-items/document-structure/BaseStructureTreeItem'; -import { DeclarationStructureTreeItem } from '../provider-items/document-structure/DeclarationStructureTreeItem'; -import { DisabledStructureTreeItem } from '../provider-items/document-structure/DisabledStructureTreeItem'; -import { ImportsStructureTreeItem } from '../provider-items/document-structure/ImportsStructureTreeItem'; -import { NotParseableStructureTreeItem } from '../provider-items/document-structure/NotParseableStructureTreeItem'; -import { ResourceStructureTreeItem } from '../provider-items/document-structure/ResourceStructureTreeItem'; -import { getScriptKind } from '../utilities/utilityFunctions'; -import { Logger } from '../utilities/winstonLogger'; -import { BaseExtension } from './BaseExtension'; - -/** - * Extension that provides code completion for typescript files. Uses the calculated index to provide information. - * - * @export - * @class DocumentSymbolStructureExtension - * @extends {BaseExtension} - * @implements {CompletionItemProvider} - */ -@injectable() -export class DocumentSymbolStructureExtension extends BaseExtension implements TreeDataProvider { - public readonly onDidChangeTreeData: Event; - private _onDidChangeTreeData: EventEmitter; - private documentCache: File | undefined; - - constructor( - @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.logger) private logger: Logger, - @inject(iocSymbols.configuration) private config: ConfigFactory, - @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - ) { - super(context); - this._onDidChangeTreeData = new EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - } - - /** - * Initialized the extension. Registers the commands and other disposables to the context. - * - * @memberof DocumentSymbolStructureExtension - */ - public initialize(): void { - this.context.subscriptions.push( - window.registerTreeDataProvider('documentCodeOutline', this), - ); - this.context.subscriptions.push(commands.registerCommand( - 'typescriptHero.documentCodeOutline.gotoNode', - (node: Node | undefined) => this.jumpToNode(node), - )); - this.context.subscriptions.push(this._onDidChangeTreeData); - this.context.subscriptions.push(window.onDidChangeActiveTextEditor(() => this.activeWindowChanged())); - this.context.subscriptions.push(workspace.onDidSaveTextDocument(() => this.activeWindowChanged())); - - this.logger.info('[%s] initialized', DocumentSymbolStructureExtension.name); - } - - /** - * Disposes the extension. - * - * @memberof DocumentSymbolStructureExtension - */ - public dispose(): void { - this.logger.info('[%s] disposed', DocumentSymbolStructureExtension.name); - } - - public getTreeItem(element: BaseStructureTreeItem): BaseStructureTreeItem { - return element; - } - - public async getChildren(element?: BaseStructureTreeItem): Promise> { - if (!window.activeTextEditor) { - return []; - } - - const config = this.config(window.activeTextEditor.document.uri); - - if (!config.codeOutline.outlineEnabled) { - return [new DisabledStructureTreeItem()]; - } - - if (!config.resolver.resolverModeLanguages.some( - lang => lang === window.activeTextEditor!.document.languageId, - )) { - return [new NotParseableStructureTreeItem()]; - } - - if (!this.documentCache) { - try { - this.documentCache = await this.parser.parseSource( - window.activeTextEditor.document.getText(), - getScriptKind(window.activeTextEditor.document.fileName), - ); - } catch (e) { - this.logger.error( - '[%s] document could not be parsed, error: %s', - DocumentSymbolStructureExtension.name, - e, - ); - return []; - } - } - - if (!element) { - const items: BaseStructureTreeItem[] = []; - if (this.documentCache.imports && this.documentCache.imports.length) { - items.push(new ImportsStructureTreeItem(this.documentCache, this.context)); - } - items.push(...this.documentCache.resources.map(r => new ResourceStructureTreeItem(r, this.context))); - items.push(...this.documentCache.declarations.map(d => new DeclarationStructureTreeItem(d, this.context))); - return items; - } - return element.getChildren(); - } - - /** - * Takes a node (or undefined) and jumps to the nodes location. If undefined is passed, a warning message is displayed. - * - * @private - * @param {(Node | undefined)} node - * @returns {Promise} - * - * @memberof DocumentSymbolStructureExtension - */ - private async jumpToNode(node: Node | undefined): Promise { - if (!node) { - this.logger.warn('[%s] jumpToNode used without param', DocumentSymbolStructureExtension.name); - window.showWarningMessage('This command is for internal use only. It cannot be used from Cmd+P'); - return; - } - - if (!window.activeTextEditor || node.start === undefined) { - return; - } - - const newPosition = window.activeTextEditor.document.positionAt(node.start); - window.activeTextEditor.selection = new Selection(newPosition, newPosition); - window.activeTextEditor.revealRange(window.activeTextEditor.selection, TextEditorRevealType.InCenter); - await window.showTextDocument(window.activeTextEditor.document); - } - - /** - * Method that recalculates the current document when the active window changed. - * - * @private - * - * @memberof DocumentSymbolStructureExtension - */ - private activeWindowChanged(): void { - this.logger.debug('[%s] activeWindowChanged, reparsing', DocumentSymbolStructureExtension.name); - this.documentCache = undefined; - this._onDidChangeTreeData.fire(); - } -} diff --git a/src/_old/extension/extensions/ImportResolveExtension.ts b/src/_old/extension/extensions/ImportResolveExtension.ts deleted file mode 100644 index 6e80328..0000000 --- a/src/_old/extension/extensions/ImportResolveExtension.ts +++ /dev/null @@ -1,260 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; -import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace } from 'vscode'; - -import { getDeclarationsFilteredByImports } from '../../common/helpers'; -import { iocSymbols } from '../IoCSymbols'; -import { ImportManager } from '../managers'; -import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; -import { getScriptKind } from '../utilities/utilityFunctions'; -import { Logger } from '../utilities/winstonLogger'; -import { BaseExtension } from './BaseExtension'; - -type MissingDeclarationsForFileOptions = { documentSource: string, documentPath: string }; - -const resolverOk = 'TSH Resolver $(check)'; -const resolverSyncing = 'TSH Resolver $(sync)'; -const resolverErr = 'TSH Resolver $(flame)'; - -/** - * Extension that resolves imports. Contains various actions to add imports to a document, add missing - * imports and organize imports. Also can rebuild the symbol cache. - * - * @export - * @class ImportResolveExtension - * @extends {BaseExtension} - */ -@injectable() -export class ImportResolveExtension extends BaseExtension { - private statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 4); - - constructor( - @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.logger) private logger: Logger, - @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - ) { - super(context); - } - - /** - * Initialized the extension. Registers the commands and other disposables to the context. - * - * @memberof ImportResolveExtension - */ - public initialize(): void { - this.context.subscriptions.push(this.statusBarItem); - - this.statusBarItem.text = resolverOk; - this.statusBarItem.tooltip = 'Click to manually reindex all files'; - this.statusBarItem.command = 'typescriptHero.resolve.rebuildCache'; - this.context.subscriptions.push(this.indices.onStartIndexing(() => { - this.statusBarItem.text = resolverSyncing; - })); - this.context.subscriptions.push(this.indices.onFinishIndexing(() => { - this.statusBarItem.text = resolverOk; - })); - this.context.subscriptions.push(this.indices.onIndexingError(() => { - this.statusBarItem.text = resolverErr; - })); - this.statusBarItem.show(); - - this.commandRegistrations(); - - this.logger.info('[%s] initialized', ImportResolveExtension.name); - } - - /** - * Disposes the extension. - * - * @memberof ImportResolveExtension - */ - public dispose(): void { - this.logger.info('[%s] disposed', ImportResolveExtension.name); - } - - /** - * Adds all missing imports to the actual document if possible. If multiple declarations are found, - * a quick pick list is shown to the user and he needs to decide, which import to use. - * - * @private - * @returns {Promise} - * - * @memberof ImportResolveExtension - */ - private async addMissingImports(): Promise { - if (!window.activeTextEditor) { - return; - } - const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); - if (!index || !index.indexReady) { - this.showCacheWarning(); - return; - } - try { - this.logger.debug( - '[%s] add all missing imports to the document', - ImportResolveExtension.name, - { file: window.activeTextEditor.document.fileName }, - ); - const missing = await this.getMissingDeclarationsForFile({ - documentSource: window.activeTextEditor.document.getText(), - documentPath: window.activeTextEditor.document.fileName, - }); - - if (missing && missing.length) { - const ctrl = await ImportManager.create(window.activeTextEditor.document); - missing.filter(o => o instanceof DeclarationInfo).forEach(o => ctrl.addDeclarationImport(o)); - await ctrl.commit(); - } - } catch (e) { - this.logger.error( - '[%s] missing imports could not be added, error: %s', - ImportResolveExtension.name, - e, - { file: window.activeTextEditor.document.fileName }, - ); - window.showErrorMessage('The operation cannot be completed, there was an error during the process.'); - } - } - - /** - * Organizes the imports of the actual document. Sorts and formats them correctly. - * - * @private - * @returns {Promise} - * - * @memberof ImportResolveExtension - */ - private async organizeImports(): Promise { - if (!window.activeTextEditor) { - return false; - } - try { - this.logger.debug( - '[%s] organize the imports in the document', - ImportResolveExtension.name, - { file: window.activeTextEditor.document.fileName }, - ); - const ctrl = await ImportManager.create(window.activeTextEditor.document); - return await ctrl.organizeImports().commit(); - } catch (e) { - this.logger.error( - '[%s] imports could not be organized, error: %s', - ImportResolveExtension.name, - e, - { file: window.activeTextEditor.document.fileName }, - ); - return false; - } - } - - /** - * Effectifely adds an import quick pick item to a document - * - * @private - * @param {DeclarationInfo} declaration - * @returns {Promise} - * - * @memberof ImportResolveExtension - */ - private async addImportToDocument(declaration: DeclarationInfo): Promise { - if (!window.activeTextEditor) { - return false; - } - const ctrl = await ImportManager.create(window.activeTextEditor.document); - return await ctrl.addDeclarationImport(declaration).commit(); - } - - - - /** - * Shows a user warning if the resolve index is not ready yet. - * - * @private - * - * @memberof ImportResolveExtension - */ - private showCacheWarning(): void { - this.logger.warn( - '[%s] index was not ready or not index for this file found', - ImportResolveExtension.name, - ); - window.showWarningMessage('Please wait a few seconds longer until the symbol cache has been build.'); - } - - /** - * Calculates the missing imports of a document. Parses the documents source and then - * tries to resolve all possible declaration infos for the usages (used identifiers). - * - * @private - * @param {MissingDeclarationsForFileOptions} {documentSource, documentPath} - * @returns {(Promise<(DeclarationInfo | ImportUserDecision)[]>)} - * - * @memberof ImportResolveExtension - */ - private async getMissingDeclarationsForFile( - { documentSource, documentPath }: MissingDeclarationsForFileOptions, - ): Promise<(DeclarationInfo)[]> { - if (!window.activeTextEditor) { - return []; - } - - const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); - const rootFolder = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri); - - if (!index || !index.indexReady || !rootFolder) { - return []; - } - - this.logger.debug( - '[%s] calculate missing imports for document', - ImportResolveExtension.name, - { file: documentPath }, - ); - - const parsedDocument = await this.parser.parseSource(documentSource, getScriptKind(documentPath)); - const missingDeclarations: (DeclarationInfo)[] = []; - const declarations = getDeclarationsFilteredByImports( - index.declarationInfos, - documentPath, - parsedDocument.imports, - rootFolder.uri.fsPath, - ); - - for (const usage of parsedDocument.nonLocalUsages) { - const foundDeclarations = declarations.filter(o => o.declaration.name === usage); - if (foundDeclarations.length <= 0) { - continue; - } else if (foundDeclarations.length === 1) { - missingDeclarations.push(foundDeclarations[0]); - } else { - // TODO handle decisions. - // missingDeclarations.push(...foundDeclarations.map(o => new ImportUserDecision(o, usage))); - } - } - - return missingDeclarations; - } - - /** - * Registers the commands for this extension. - * - * @private - * @memberof ImportResolveExtension - */ - private commandRegistrations(): void { - - this.context.subscriptions.push( - commands.registerTextEditorCommand( - 'typescriptHero.resolve.addMissingImports', () => this.addMissingImports(), - ), - ); - this.context.subscriptions.push( - commands.registerTextEditorCommand('typescriptHero.resolve.organizeImports', () => this.organizeImports()), - ); - this.context.subscriptions.push( - commands.registerCommand('typescriptHero.resolve.rebuildCache', () => this.indices.rebuildAll()), - ); - } -} diff --git a/src/_old/extension/extensions/OrganizeImportsOnSaveExtension.ts b/src/_old/extension/extensions/OrganizeImportsOnSaveExtension.ts deleted file mode 100644 index e7791ef..0000000 --- a/src/_old/extension/extensions/OrganizeImportsOnSaveExtension.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { ExtensionContext, workspace } from 'vscode'; - -import { ConfigFactory } from '../../common/factories'; -import { iocSymbols } from '../IoCSymbols'; -import { ImportManager } from '../managers'; -import { Logger } from '../utilities/winstonLogger'; -import { BaseExtension } from './BaseExtension'; - -/** - * Extension that does sort and organize the imports as soon as a document will be saved. - * - * @export - * @class OrganizeImportsOnSaveExtension - * @extends {BaseExtension} - */ -@injectable() -export class OrganizeImportsOnSaveExtension extends BaseExtension { - private compatibleLanguages: string[] = [ - 'typescript', - 'typescriptreact', - 'javascript', - 'javascriptreact', - ]; - - constructor( - @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.logger) private logger: Logger, - @inject(iocSymbols.configuration) private config: ConfigFactory, - ) { - super(context); - } - - /** - * Initialized the extension. Registers the commands and other disposables to the context. - * - * @memberof OrganizeImportsOnSaveExtension - */ - public initialize(): void { - this.context.subscriptions.push(workspace.onWillSaveTextDocument((event) => { - const config = this.config(event.document.uri); - if (!config.resolver.organizeOnSave) { - this.logger.debug( - '[%s] organizeOnSave is deactivated through config', - OrganizeImportsOnSaveExtension.name, - ); - return; - } - if (this.compatibleLanguages.indexOf(event.document.languageId) < 0) { - this.logger.debug( - '[%s] organizeOnSave not possible for given language', - OrganizeImportsOnSaveExtension.name, - { language: event.document.languageId }, - ); - return; - } - - this.logger.info( - '[%s] organizeOnSave for file', - OrganizeImportsOnSaveExtension.name, - { file: event.document.fileName }, - ); - event.waitUntil( - ImportManager - .create(event.document) - .then(manager => manager.organizeImports().calculateTextEdits()), - ); - })); - - this.logger.info('[%s] initialized', OrganizeImportsOnSaveExtension.name); - } - - /** - * Disposes the extension. - * - * @memberof OrganizeImportsOnSaveExtension - */ - public dispose(): void { - this.logger.info('[%s] disposed', OrganizeImportsOnSaveExtension.name); - } -} diff --git a/src/_old/extension/helpers/index.ts b/src/_old/extension/helpers/index.ts deleted file mode 100644 index 7d72b45..0000000 --- a/src/_old/extension/helpers/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './nodeRangeHelpers'; diff --git a/src/_old/extension/helpers/nodeRangeHelpers.ts b/src/_old/extension/helpers/nodeRangeHelpers.ts deleted file mode 100644 index c056c10..0000000 --- a/src/_old/extension/helpers/nodeRangeHelpers.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Position, Range, TextDocument } from 'vscode'; - -/** - * Returns the range of a node in the given document. If start or end is undefined, - * the document head (aka first line) is returned as range. - * - * @export - * @param {TextDocument} document - * @param {number} [start] - * @param {number} [end] - * @returns {Range} - */ -export function nodeRange(document: TextDocument, start?: number, end?: number): Range { - return start !== undefined && end !== undefined ? - new Range(document.positionAt(start), document.positionAt(end)) : - new Range(new Position(0, 0), new Position(0, 0)); -} diff --git a/src/_old/extension/managers/ClassManager.ts b/src/_old/extension/managers/ClassManager.ts deleted file mode 100644 index ae81cde..0000000 --- a/src/_old/extension/managers/ClassManager.ts +++ /dev/null @@ -1,416 +0,0 @@ -import { - ClassDeclaration, - ConstructorDeclaration, - DeclarationVisibility, - File, - MethodDeclaration, - ParameterDeclaration, - PropertyDeclaration, - TypescriptCodeGenerator, - TypescriptParser, -} from 'typescript-parser'; -import { Position, Range, TextDocument, TextEdit, workspace, WorkspaceEdit } from 'vscode'; - -import { - ClassNotFoundError, - MethodDuplicated, - MethodNotFound, - PropertyDuplicated, - PropertyNotFound, -} from '../../common/errors'; -import { TypescriptCodeGeneratorFactory } from '../../common/factories'; -import { Container } from '../IoC'; -import { iocSymbols } from '../IoCSymbols'; -import { Changeable } from '../proxy-objects/Changeable'; -import { getScriptKind } from '../utilities/utilityFunctions'; -import { Logger } from '../utilities/winstonLogger'; -import { ObjectManager } from './ObjectManager'; - -type VisibleObject = { visibility?: DeclarationVisibility }; - -/** - * Sortfunction for changeable objects. Does sort the objects by visibility. - * - * @param {Changeable} o1 - * @param {Changeable} o2 - * @returns {number} - */ -function sortByVisibility(o1: Changeable, o2: Changeable): number { - const left = o1.object.visibility; - const right = o2.object.visibility; - - if ((left === undefined && right === undefined) || (left === right)) { - return 0; - } - if (left !== undefined && right === undefined) { - return -1; - } - if (left === undefined && right !== undefined) { - return 1; - } - - return right! - left!; -} - -/** - * Manager for classes in files. Is able to modify a written class (add / remove methods and properties). - * On commit, the new typescript is generated and inserted. - * - * @export - * @class ClassManager - * @implements {ObjectManager} - */ -export class ClassManager implements ObjectManager { - private static get parser(): TypescriptParser { - return Container.get(iocSymbols.typescriptParser); - } - - private static get generator(): TypescriptCodeGenerator { - return Container.get(iocSymbols.generatorFactory)(); - } - - private static get logger(): Logger { - return Container.get(iocSymbols.logger); - } - - private ctor: Changeable; - private properties: Changeable[] = []; - private methods: Changeable[] = []; - - private constructor( - public readonly document: TextDocument, - public readonly parsedDocument: File, - private readonly managedClass: ClassDeclaration, - ) { - ClassManager.logger.debug( - '[%s] create class manager', - ClassManager.name, - { file: document.fileName, class: managedClass.name }, - ); - this.ctor = new Changeable(managedClass.ctor); - this.properties = managedClass.properties.map(o => new Changeable(o)); - this.methods = managedClass.methods.map(o => new Changeable(o)); - } - - /** - * Creates an instance of a ClassManager. - * Does parse the document text first and returns a promise that - * resolves to a ClassManager. - * - * @static - * @param {TextDocument} document The document that should be managed - * @param {string} className The name of the class that should be managed - * @returns {Promise} - * - * @memberof ClassManager - */ - public static async create(document: TextDocument, className: string): Promise { - const source = await ClassManager.parser.parseSource(document.getText(), getScriptKind(document.fileName)); - const managedClass = source.declarations.find( - o => o.name === className && o instanceof ClassDeclaration, - ) as ClassDeclaration; - - if (!managedClass) { - throw new ClassNotFoundError(className); - } - return new ClassManager(document, source, managedClass); - } - - /** - * Checks if a property with the given name exists on the virtual class. - * - * @param {string} name - * @returns {boolean} - * - * @memberof ClassManager - */ - public hasProperty(name: string): boolean { - return this.properties.some(o => o.object.name === name && !o.isDeleted); - } - - /** - * Add a property to the virtual class. Creates a Changeable object with the .isNew flag set to true. - * - * @param {(string | PropertyDeclaration)} nameOrDeclaration - * @param {DeclarationVisibility} [visibility] - * @param {string} [type] - * @returns {this} - * - * @memberof ClassManager - */ - public addProperty( - nameOrDeclaration: string | PropertyDeclaration, - visibility?: DeclarationVisibility, - type?: string, - ): this { - let declaration: PropertyDeclaration; - - if (nameOrDeclaration instanceof PropertyDeclaration) { - if (this.properties.some(o => o.object.name === nameOrDeclaration.name && !o.isDeleted)) { - throw new PropertyDuplicated(nameOrDeclaration.name, this.managedClass.name); - } - declaration = nameOrDeclaration; - } else { - if (this.properties.some(o => o.object.name === nameOrDeclaration && !o.isDeleted)) { - throw new PropertyDuplicated(nameOrDeclaration, this.managedClass.name); - } - declaration = new PropertyDeclaration(nameOrDeclaration, visibility, type); - } - - this.properties.push(new Changeable(declaration, true)); - ClassManager.logger.debug( - '[%s] add property to class', - ClassManager.name, - { property: declaration.name, class: this.managedClass.name }, - ); - - return this; - } - - /** - * Remove (aka set isDeleted) a property from the virtual class. - * - * @param {string} name - * @returns {this} - * - * @memberof ClassManager - */ - public removeProperty(name: string): this { - if (!this.properties.some(o => o.object.name === name && !o.isDeleted)) { - throw new PropertyNotFound(name, this.managedClass.name); - } - const property = this.properties.find(o => o.object.name === name); - if (!property) { - return this; - } - property.isDeleted = true; - if (property.isNew) { - this.properties.splice(this.properties.indexOf(property), 1); - } - ClassManager.logger.debug( - '[%s] remove property from class', - ClassManager.name, - { property: name, class: this.managedClass.name }, - ); - return this; - } - - /** - * Checks if a method with the given name does exist on the virtual class. - * - * @param {string} name - * @returns {boolean} - * - * @memberof ClassManager - */ - public hasMethod(name: string): boolean { - return this.methods.some(o => o.object.name === name && !o.isDeleted); - } - - /** - * Add a method to the virtual class. - * - * @param {(string | MethodDeclaration)} nameOrDeclaration - * @param {DeclarationVisibility} [visibility] - * @param {string} [type] - * @param {ParameterDeclaration[]} [parameters] - * @returns {this} - * - * @memberof ClassManager - */ - public addMethod( - nameOrDeclaration: string | MethodDeclaration, - visibility?: DeclarationVisibility, - type?: string, - parameters?: ParameterDeclaration[], - ): this { - let declaration: MethodDeclaration; - - if (nameOrDeclaration instanceof MethodDeclaration) { - if (this.methods.some(o => o.object.name === nameOrDeclaration.name && !o.isDeleted)) { - throw new MethodDuplicated(nameOrDeclaration.name, this.managedClass.name); - } - declaration = nameOrDeclaration; - } else { - if (this.methods.some(o => o.object.name === nameOrDeclaration && !o.isDeleted)) { - throw new MethodDuplicated(nameOrDeclaration, this.managedClass.name); - } - declaration = new MethodDeclaration(nameOrDeclaration, false, visibility, type); - declaration.parameters = parameters || []; - } - - this.methods.push(new Changeable(declaration, true)); - ClassManager.logger.debug( - '[%s] add method to class', - ClassManager.name, - { property: declaration.name, class: this.managedClass.name }, - ); - - return this; - } - - /** - * Removes a method from the virtual class. - * - * @param {string} name - * @returns {this} - * - * @memberof ClassManager - */ - public removeMethod(name: string): this { - if (!this.methods.some(o => o.object.name === name && !o.isDeleted)) { - throw new MethodNotFound(name, this.managedClass.name); - } - const method = this.methods.find(o => o.object.name === name); - if (!method) { - return this; - } - method.isDeleted = true; - if (method.isNew) { - this.methods.splice(this.methods.indexOf(method), 1); - } - ClassManager.logger.debug( - '[%s] remove method from class', - ClassManager.name, - { property: name, class: this.managedClass.name }, - ); - return this; - } - - /** - * Commits the virtual class to the given document. - * The following steps are exectued with properties and methods: - * - Delete properties - * - Update changed properties (still TODO) - * - Insert new properties - * - * @returns {Promise} - * - * @memberof ClassManager - */ - public async commit(): Promise { - const edits = [ - ...this.calculatePropertyEdits(), - ...this.calculateMethodEdits(), - ]; - - const workspaceEdit = new WorkspaceEdit(); - workspaceEdit.set(this.document.uri, edits); - ClassManager.logger.debug( - '[%s] commit the class', - ClassManager.name, - { class: this.managedClass.name }, - ); - return workspace.applyEdit(workspaceEdit); - } - - /** - * Determines if a propertydeclaration is injected by the constructor. - * I.e. constructor(public foo: string)... - * - * @private - * @param {PropertyDeclaration} property - * @returns {boolean} - * - * @memberof ClassManager - */ - private isInConstructor(property: PropertyDeclaration): boolean { - if (!this.ctor || !this.ctor.object) { - return false; - } - - return property.start! >= this.ctor.object.start! && property.end! <= this.ctor.object.end!; - } - - /** - * Calculates TextEdits for properties. - * - * @private - * @returns {TextEdit[]} - * - * @memberof ClassManager - */ - private calculatePropertyEdits(): TextEdit[] { - const edits: TextEdit[] = []; - - for (const property of this.properties.filter(o => o.isDeleted)) { - edits.push(TextEdit.delete( - new Range( - this.document.lineAt( - this.document.positionAt(property.object.start!).line, - ).rangeIncludingLineBreak.start, - this.document.lineAt( - this.document.positionAt(property.object.end!).line, - ).rangeIncludingLineBreak.end, - ), - )); - } - - // TODO update - - for (const property of this.properties.filter(o => o.isNew).sort(sortByVisibility)) { - const lastProperty = this.properties.filter( - o => !o.isNew && - !o.isDeleted && - !this.isInConstructor(o.object) && - o.object.visibility === property.object.visibility, - ).pop(); - const lastPosition = lastProperty ? - this.document.positionAt(lastProperty.object.end!).line + 1 : - this.document.positionAt(this.managedClass.start!).line + 1; - edits.push(TextEdit.insert( - new Position(lastPosition, 0), - ClassManager.generator.generate(property.object), - )); - } - - return edits; - } - - /** - * Calculates TextEdits for methods. - * - * @private - * @returns {TextEdit[]} - * - * @memberof ClassManager - */ - private calculateMethodEdits(): TextEdit[] { - const edits: TextEdit[] = []; - - for (const method of this.methods.filter(o => o.isDeleted)) { - const endPosition = this.document.positionAt(method.object.end!); - let endLine = endPosition.line; - - if (this.document.lineAt(endLine + 1).isEmptyOrWhitespace) { - endLine += 1; - } - - edits.push(TextEdit.delete( - new Range( - this.document.lineAt( - this.document.positionAt(method.object.start!).line, - ).rangeIncludingLineBreak.start, - this.document.lineAt(endLine).rangeIncludingLineBreak.end, - ), - )); - } - - // TODO update - - for (const method of this.methods.filter(o => o.isNew).sort(sortByVisibility)) { - const lastMethod = this.methods.filter( - o => !o.isNew && !o.isDeleted && o.object.visibility === method.object.visibility, - ).pop(); - const lastPosition = lastMethod ? - this.document.positionAt(lastMethod.object.end!).line + 1 : - this.document.positionAt(this.managedClass.end!).line; - edits.push(TextEdit.insert( - new Position(lastPosition, 0), - '\n' + ClassManager.generator.generate(method.object), - )); - } - - return edits; - } -} diff --git a/src/_old/extension/managers/ObjectManager.ts b/src/_old/extension/managers/ObjectManager.ts deleted file mode 100644 index cd769fc..0000000 --- a/src/_old/extension/managers/ObjectManager.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { File } from 'typescript-parser'; -import { TextDocument } from 'vscode'; - -/** - * Base interface for all object managers. Those managers can modify a class / imports / and any other - * coded objects. On calling commit(), the changes must be commited to the provided document. - * - * @export - * @interface ObjectManager - */ -export interface ObjectManager { - readonly document: TextDocument; - readonly parsedDocument: File; - - /** - * Commits the changes made to the given document. - * - * @returns {Promise} - * - * @memberof ObjectManager - */ - commit(): Promise; -} diff --git a/src/_old/extension/managers/index.ts b/src/_old/extension/managers/index.ts deleted file mode 100644 index 83c0323..0000000 --- a/src/_old/extension/managers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './ClassManager'; -export * from './ImportManager'; diff --git a/src/_old/extension/proxy-objects/Changeable.ts b/src/_old/extension/proxy-objects/Changeable.ts deleted file mode 100644 index c740aa8..0000000 --- a/src/_old/extension/proxy-objects/Changeable.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Class that represents an object (virtual object) that can be modified. - * Is used for ClassManager and other ObjectManager classes to keep track on modified objects. - * - * @export - * @class Changeable - * @template T - */ -export class Changeable { - constructor( - public object: T, - public isNew: boolean = false, - public isModified: boolean = false, - public isDeleted: boolean = false, - ) { } -} diff --git a/src/_old/extension/utilities/DeclarationIndexMapper.ts b/src/_old/extension/utilities/DeclarationIndexMapper.ts deleted file mode 100644 index 0e08e9a..0000000 --- a/src/_old/extension/utilities/DeclarationIndexMapper.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { inject, injectable, postConstruct } from 'inversify'; -import { DeclarationIndex, FileChanges, TypescriptParser } from 'typescript-parser'; -import { - Event, - EventEmitter, - ExtensionContext, - FileSystemWatcher, - RelativePattern, - Uri, - workspace, - WorkspaceFolder, - WorkspaceFoldersChangeEvent, -} from 'vscode'; - -import { ConfigFactory } from '../../common/factories'; -import { findFiles } from '../../common/helpers'; -import { iocSymbols } from '../../extension/IoCSymbols'; -import { Logger } from './winstonLogger'; - -interface WorkspaceIndex { - index: DeclarationIndex; - folder: WorkspaceFolder; - watcher: FileSystemWatcher; -} - -// TODO move did change configuration to all indices -// TODO: update index on change of configs - -/** - * Mapping class that manages the different indices for the workspaces. - * - * @export - * @class DeclarationIndexMapper - */ -@injectable() -export class DeclarationIndexMapper { - public readonly onStartIndexing: Event; - public readonly onFinishIndexing: Event; - public readonly onIndexingError: Event<{ index: WorkspaceIndex, error: Error }>; - - private _onStartIndexing: EventEmitter; - private _onFinishIndexing: EventEmitter; - private _onIndexingError: EventEmitter<{ index: WorkspaceIndex, error: Error }>; - - private indizes: { [uri: string]: WorkspaceIndex } = {}; - - constructor( - @inject(iocSymbols.logger) private logger: Logger, - @inject(iocSymbols.extensionContext) private context: ExtensionContext, - @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.configuration) private config: ConfigFactory, - ) { - this._onFinishIndexing = new EventEmitter(); - this._onStartIndexing = new EventEmitter(); - this._onIndexingError = new EventEmitter(); - - this.onFinishIndexing = this._onFinishIndexing.event; - this.onStartIndexing = this._onStartIndexing.event; - this.onIndexingError = this._onIndexingError.event; - - this.context.subscriptions.push(this._onFinishIndexing); - this.context.subscriptions.push(this._onIndexingError); - this.context.subscriptions.push(this._onStartIndexing); - } - - /** - * Init method that runs after the DI construction of the object. - * - * @memberof DeclarationIndexMapper - */ - @postConstruct() - public initialize(): void { - this.context.subscriptions.push(workspace.onDidChangeWorkspaceFolders(e => this.workspaceChanged(e))); - this.logger.info( - '[%s] initializing index mapper for %d workspaces', - DeclarationIndexMapper.name, - (workspace.workspaceFolders || []).length, - ); - - for (const folder of (workspace.workspaceFolders || []).filter(workspace => workspace.uri.scheme === 'file')) { - this.initializeIndex(folder); - } - this.logger.info('[%s] initialized', DeclarationIndexMapper.name); - } - - /** - * Method to rebuild all indices in the system. - * - * @memberof DeclarationIndexMapper - */ - public rebuildAll(): void { - this.logger.info( - '[%s] rebuilding all indices', - DeclarationIndexMapper.name, - ); - for (const index of Object.values(this.indizes)) { - index.watcher.dispose(); - index.index.reset(); - } - this.indizes = {}; - for (const folder of (workspace.workspaceFolders || []).filter(workspace => workspace.uri.scheme === 'file')) { - this.initializeIndex(folder); - } - } - - /** - * Returns the index (or undefined) for a given file URI. - * - * @param {Uri} fileUri - * @returns {(DeclarationIndex | undefined)} - * @memberof DeclarationIndexMapper - */ - public getIndexForFile(fileUri: Uri): DeclarationIndex | undefined { - const workspaceFolder = workspace.getWorkspaceFolder(fileUri); - if (!workspaceFolder || !this.indizes[workspaceFolder.uri.fsPath]) { - this.logger.debug( - '[%s] did not find index for file', - DeclarationIndexMapper.name, - { file: fileUri.fsPath }, - ); - return; - } - - return this.indizes[workspaceFolder.uri.fsPath].index; - } - - /** - * Eventhandler that is called when the workspaces changed (i.e. some where added or removed). - * - * @private - * @param {WorkspaceFoldersChangeEvent} event - * @memberof DeclarationIndexMapper - */ - private workspaceChanged(event: WorkspaceFoldersChangeEvent): void { - this.logger.info( - '[%s] workspaces changed, adjusting indices', - DeclarationIndexMapper.name, - ); - for (const add of event.added) { - this.logger.debug( - '[%s] add workspace for "%s"', - DeclarationIndexMapper.name, - add.uri.fsPath, - ); - if (this.indizes[add.uri.fsPath]) { - this.logger.warn( - '[%s] workspace index "%s" already exists, skipping', - DeclarationIndexMapper.name, - add.uri.fsPath, - ); - continue; - } - this.initializeIndex(add); - } - - for (const remove of event.removed) { - this.logger.debug( - '[%s] remove workspace for "%s"', - DeclarationIndexMapper.name, - remove.uri.fsPath, - ); - this.indizes[remove.uri.fsPath].index.reset(); - this.indizes[remove.uri.fsPath].watcher.dispose(); - delete this.indizes[remove.uri.fsPath]; - } - } - - /** - * Helper method to initialize an index. - * - * @private - * @param {WorkspaceFolder} folder - * @returns {Promise} - * @memberof DeclarationIndexMapper - */ - private async initializeIndex(folder: WorkspaceFolder): Promise { - const profiler = this.logger.startTimer(); - this.logger.debug( - '[%s] initialize index for "%s"', - DeclarationIndexMapper.name, - folder.uri.fsPath, - ); - const index = new DeclarationIndex(this.parser, folder.uri.fsPath); - const config = this.config(folder.uri); - const files = await findFiles(config, folder); - const watcher = workspace.createFileSystemWatcher( - new RelativePattern( - folder, - `{${config.resolver.resolverModeFileGlobs.join(',')},**/package.json,**/typings.json}`, - ), - ); - const workspaceIndex = { - index, - folder, - watcher, - }; - - this._onStartIndexing.fire(workspaceIndex); - - let timeout: NodeJS.Timer | undefined; - let events: FileChanges | undefined; - - const fileWatcherEvent = (event: string, uri: Uri) => { - if (timeout) { - clearTimeout(timeout); - } - if (!events) { - events = { - created: [], - updated: [], - deleted: [], - }; - } - events[event].push(uri.fsPath); - - timeout = setTimeout( - async () => { - if (events) { - const profiler = this.logger.startTimer(); - this.logger.debug( - '[%s] rebuilding index for index "%s"', - DeclarationIndexMapper.name, - folder.uri.fsPath, - ); - await index.reindexForChanges(events); - profiler.done({ - message: `[${DeclarationIndexMapper.name}] rebuilt index for workspace "${folder.name}"`, - }); - events = undefined; - } - }, - 500, - ); - }; - - watcher.onDidCreate(uri => fileWatcherEvent('created', uri)); - watcher.onDidChange(uri => fileWatcherEvent('updated', uri)); - watcher.onDidDelete(uri => fileWatcherEvent('deleted', uri)); - - try { - await index.buildIndex(files); - this.indizes[folder.uri.fsPath] = workspaceIndex; - this._onFinishIndexing.fire(workspaceIndex); - profiler.done({ - message: `[${DeclarationIndexMapper.name}] built index for workspace "${folder.name}"`, - }); - } catch (error) { - this.logger.error( - '[%s] could not build index for workspace "%s", error: %s', - DeclarationIndexMapper.name, - folder.uri.fsPath, - error, - ); - this._onIndexingError.fire({ error, index: workspaceIndex }); - } - } -} diff --git a/src/_old/old-config.json b/src/_old/old-config.json deleted file mode 100644 index b5900e5..0000000 --- a/src/_old/old-config.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "configuration": { - "typescriptHero.codeCompletion.completionSortMode": { - "enum": [ - "default", - "bottom" - ], - "default": "default", - "description": "Defines the sortmode of the code completion in intellisense (bottom means sorted to bottom).", - "scope": "resource" - } - }, - "commands": [ - { - "command": "typescriptHero.resolve.addMissingImports", - "title": "TS Hero: Adds all missing imports for the open document" - }, - { - "command": "typescriptHero.resolve.organizeImports", - "title": "TS Hero: Organize imports (sort and remove unused)" - }, - { - "command": "typescriptHero.resolve.rebuildCache", - "title": "TS Hero: Rebuild the resolver cache" - }, - { - "command": "typescriptHero.codeFix.executeCodeAction", - "title": "TS Hero (internal): Execute a code action" - }, - { - "command": "typescriptHero.codeCompletion.executeIntellisenseItem", - "title": "TS Hero (internal): Execute the command for a intellisense item" - }, - { - "command": "typescriptHero.documentCodeOutline.gotoNode", - "title": "TS Hero (internal): Jump to the given nodes location" - } - ], - "keybindings": [ - { - "command": "typescriptHero.resolve.addMissingImports", - "key": "ctrl+alt+shift+i", - "when": "editorTextFocus" - }, - { - "command": "typescriptHero.resolve.organizeImports", - "key": "ctrl+alt+o", - "when": "editorTextFocus" - } - ] -} diff --git a/src/code-completion/index.ts b/src/code-completion/index.ts new file mode 100644 index 0000000..a8cd4a1 --- /dev/null +++ b/src/code-completion/index.ts @@ -0,0 +1,167 @@ +import { inject, injectable } from 'inversify'; +import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; +import { + CancellationToken, + commands, + CompletionItem, + CompletionItemProvider, + ExtensionContext, + languages, + Position, + TextDocument, + workspace, +} from 'vscode'; + +import Activatable from '../activatable'; +import Configuration from '../configuration'; +import DeclarationManager from '../declarations/declaration-manager'; +import iocSymbols, { ImportManagerProvider } from '../ioc-symbols'; +import { Logger } from '../utilities/logger'; +import { getDeclarationsFilteredByImports, getItemKind, getScriptKind } from '../utilities/utility-functions'; + +const REGEX_COMMENT = /^\s*(?:\/\/|\/\*|\*\/|\*)/; + +/** + * Extension that provides code completion for typescript and javascript files. + * Uses the calculated index to provide information. + * + * @export + * @class CodeCompletion + * @implements {Activatable} + * @implements {CompletionItemProvider} + */ +@injectable() +export class CodeCompletion implements Activatable, CompletionItemProvider { + + constructor( + @inject(iocSymbols.extensionContext) private context: ExtensionContext, + @inject(iocSymbols.logger) private logger: Logger, + @inject(iocSymbols.configuration) private config: Configuration, + @inject(iocSymbols.importManager) private importManagerProvider: ImportManagerProvider, + @inject(iocSymbols.declarationManager) private declarationManager: DeclarationManager, + @inject(iocSymbols.parser) private parser: TypescriptParser, + ) { } + + public setup(): void { + this.logger.debug('[CodeCompletion] Setting up CodeCompletion.'); + this.logger.debug( + '[CodeCompletion] Registering for languages.', + { languages: this.config.parseableLanguages() }, + ); + + for (const lang of this.config.parseableLanguages()) { + this.context.subscriptions.push(languages.registerCompletionItemProvider(lang, this)); + } + + this.context.subscriptions.push( + commands.registerCommand( + 'typescriptHero.codeCompletion.executeIntellisenseItem', + (document: TextDocument, declaration: DeclarationInfo) => + this.executeIntellisenseItem(document, declaration), + ), + ); + } + + public start(): void { + this.logger.info('[CodeCompletion] Starting up CodeCompletion.'); + } + + public stop(): void { + this.logger.info('[CodeCompletion] Stopping CodeCompletion.'); + } + + public dispose(): void { + this.logger.debug('[CodeCompletion] Disposing CodeCompletion.'); + } + + public async provideCompletionItems( + document: TextDocument, + position: Position, + token: CancellationToken, + ): Promise { + const index = this.declarationManager.getIndexForFile(document.uri); + const actualWorkspace = workspace.getWorkspaceFolder(document.uri); + + if (!index || !actualWorkspace || !index.indexReady) { + this.logger.info('[CodeCompletion] index not ready or no workspace folder selected'); + return null; + } + + const wordAtPosition = document.getWordRangeAtPosition(position); + const lineText = document.lineAt(position.line).text; + + let searchWord = ''; + + if (wordAtPosition && wordAtPosition.start.character < position.character) { + const word = document.getText(wordAtPosition); + searchWord = word.substr(0, position.character - wordAtPosition.start.character); + } + + if ( + !searchWord || + token.isCancellationRequested || + (lineText.substring(0, position.character).match(/["'`]/g) || []).length % 2 === 1 || + REGEX_COMMENT.test(lineText) || + lineText.startsWith('import ') || + new RegExp(`(?:\w*\.)+${searchWord}`).test(lineText.substring(0, position.character)) + ) { + this.logger.debug( + '[CodeCompletion] did not match criteria to provide intellisense', + { searchWord, lineText, indexReady: index.indexReady }, + ); + return null; + } + + this.logger.debug(`[CodeCompletion] provide code completion for "${searchWord}"`); + const profiler = this.logger.startTimer(); + + const parsed = await this.parser.parseSource(document.getText(), getScriptKind(document.fileName)); + const declarations = getDeclarationsFilteredByImports( + index.declarationInfos, + document.fileName, + parsed.imports, + actualWorkspace.uri.fsPath, + ) + .filter(o => !parsed.declarations.some(d => d.name === o.declaration.name)) + .filter(o => !parsed.usages.some(d => d === o.declaration.name)); + + const items: CompletionItem[] = []; + for (const declaration of declarations.filter( + o => o.declaration.name.toLowerCase().indexOf(searchWord.toLowerCase()) >= 0) + ) { + const item = new CompletionItem(declaration.declaration.name, getItemKind(declaration.declaration)); + + item.detail = declaration.from; + item.command = { + arguments: [document, declaration], + title: 'Execute intellisense insert', + command: 'typescriptHero.codeCompletion.executeIntellisenseItem', + }; + if (this.config.codeCompletion.completionSortMode(document.uri) === 'bottom') { + item.sortText = `9999-${declaration.declaration.name}`; + } + items.push(item); + } + + profiler.done({ message: `[CodeCompletion] calculated code completions` }); + return items; + } + + /** + * Executes a intellisense item that provided a document and a declaration to add. + * Does make the calculation of the text edits async. + * + * @private + * @param {TextDocument} document + * @param {DeclarationInfo} declaration + * @returns {Promise} + * @memberof CodeCompletion + */ + private async executeIntellisenseItem(document: TextDocument, declaration: DeclarationInfo): Promise { + this.logger.info( + '[CodeCompletion] Execute code completion action.', + { specifier: declaration.declaration.name, library: declaration.from }, + ); + await (await this.importManagerProvider(document)).addDeclarationImport(declaration).commit(); + } +} diff --git a/src/configuration/code-completion-config.ts b/src/configuration/code-completion-config.ts new file mode 100644 index 0000000..8e80359 --- /dev/null +++ b/src/configuration/code-completion-config.ts @@ -0,0 +1,9 @@ +import { Uri, workspace } from 'vscode'; + +const sectionKey = 'typescriptHero.codeCompletion'; + +export class CodeCompletionConfig { + public completionSortMode(resource: Uri): 'default' | 'bottom' { + return workspace.getConfiguration(sectionKey, resource).get('completionSortMode', 'default'); + } +} diff --git a/src/configuration/index.ts b/src/configuration/index.ts index 2e1802f..66127c0 100644 --- a/src/configuration/index.ts +++ b/src/configuration/index.ts @@ -3,6 +3,7 @@ import { MultiLineImportRule, TypescriptGenerationOptions } from 'typescript-par import { Event, EventEmitter, ExtensionContext, Uri, window, workspace } from 'vscode'; import iocSymbols from '../ioc-symbols'; +import { CodeCompletionConfig } from './code-completion-config'; import DocumentOutlineConfig from './document-outline-config'; import ImportsConfig from './imports-config'; import IndexConfig from './index-config'; @@ -12,6 +13,7 @@ const sectionKey = 'typescriptHero'; @injectable() export default class Configuration { public readonly codeOutline: DocumentOutlineConfig = new DocumentOutlineConfig(); + public readonly codeCompletion: CodeCompletionConfig = new CodeCompletionConfig(); public readonly imports: ImportsConfig = new ImportsConfig(); public readonly index: IndexConfig = new IndexConfig(); diff --git a/src/ioc.ts b/src/ioc.ts index 336d66f..9723094 100644 --- a/src/ioc.ts +++ b/src/ioc.ts @@ -5,6 +5,7 @@ import { TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, TextDocument, Uri } from 'vscode'; import Activatable from './activatable'; +import { CodeCompletion } from './code-completion'; import CodeOutline from './code-outline'; import Configuration from './configuration'; import DeclarationManager from './declarations/declaration-manager'; @@ -24,6 +25,7 @@ ioc.bind(TypescriptHero).to(TypescriptHero).inSingletonScope(); ioc.bind(iocSymbols.activatables).to(CodeOutline).inSingletonScope(); ioc.bind(iocSymbols.activatables).to(ImportOrganizer).inSingletonScope(); ioc.bind(iocSymbols.activatables).to(ImportAppender).inSingletonScope(); +ioc.bind(iocSymbols.activatables).to(CodeCompletion).inSingletonScope(); // Configuration ioc.bind(iocSymbols.configuration).to(Configuration).inSingletonScope(); diff --git a/test/_old/_workspace/.gitignore b/test/_old/_workspace/.gitignore deleted file mode 100644 index 288947d..0000000 --- a/test/_old/_workspace/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -!.vscode -!node_modules -!typings -!out diff --git a/test/_old/_workspace/.vscode/settings.json b/test/_old/_workspace/.vscode/settings.json deleted file mode 100644 index 05d0755..0000000 --- a/test/_old/_workspace/.vscode/settings.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "typescriptHero.resolver.importGroups": [ - "Plains", - "Modules", - "/cool-library/", - "/cooler-library/", - "Workspace" - ], - "editor.tabSize": 4, - "files.eol": "\n", - "typescriptHero.verbosity": "warn", - "tslint.enable": false, - "typescriptHero.codeOutline.enabled": true, - "typescriptHero.resolver.organizeOnSave": false, - "typescriptHero.resolver.promptForSpecifiers": true, - "editor.formatOnSave": true, - "typescriptHero.codeCompletion.completionSortMode": "default", - "typescriptHero.resolver.disableImportRemovalOnOrganize": false, - "typescriptHero.resolver.organizeSortsByFirstSpecifier": false -} diff --git a/test/_old/_workspace/build/app.d.ts b/test/_old/_workspace/build/app.d.ts deleted file mode 100644 index 5198b11..0000000 --- a/test/_old/_workspace/build/app.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare class MyCompiledClass { } diff --git a/test/_old/_workspace/build/app.js b/test/_old/_workspace/build/app.js deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/common/helpers/importHelperFile.ts b/test/_old/_workspace/common/helpers/importHelperFile.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/common/ts-parsing/class.ts b/test/_old/_workspace/common/ts-parsing/class.ts deleted file mode 100644 index 8c871cc..0000000 --- a/test/_old/_workspace/common/ts-parsing/class.ts +++ /dev/null @@ -1,32 +0,0 @@ -abstract class AbstractClass { - public method1() { } - - public abstract abstractMethod(): void; -} - -class NonExportedClass { - constructor(public param1: string) { } - - public method1(): void { } - protected method2(): void { } - private method3(): void { - let variable = ''; - } -} - -export class ExportedClass { - private _property: string; - protected protect: string; - public pub: string; - - public get property(): string { - return this._property; - } - - public set property(value: string) { - this._property = value; - } -} - -class Generic { } -class MultiGeneric { } diff --git a/test/_old/_workspace/common/ts-parsing/enum.ts b/test/_old/_workspace/common/ts-parsing/enum.ts deleted file mode 100644 index f9a7cf4..0000000 --- a/test/_old/_workspace/common/ts-parsing/enum.ts +++ /dev/null @@ -1,10 +0,0 @@ -enum Enumeration { - Member1, - Member2, - Member3 -} - -export const enum ConstantEnumeration { - ConstMember1, - ConstMember2 -} diff --git a/test/_old/_workspace/common/ts-parsing/exportsOnly.ts b/test/_old/_workspace/common/ts-parsing/exportsOnly.ts deleted file mode 100644 index 0ef0f5d..0000000 --- a/test/_old/_workspace/common/ts-parsing/exportsOnly.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './OtherFile'; - -export {Specifier, Specifier as Alias} from './AnotherFile'; - -export = Foo; - -export default 'DefaultExport'; diff --git a/test/_old/_workspace/common/ts-parsing/function.ts b/test/_old/_workspace/common/ts-parsing/function.ts deleted file mode 100644 index 13b4d07..0000000 --- a/test/_old/_workspace/common/ts-parsing/function.ts +++ /dev/null @@ -1,16 +0,0 @@ -function function1(param1): string { - let var1 = 'foobar'; - return 'foobar'; -} - -export function function2(param1: string, { objParam1, objParam2 }, [arrParam1, arrParam2]): void { - const constVar1 = 'foobar'; -} - -function withoutReturnType() { - return ''; -} - -function typeGuard(str: any): str is number { - return str.constructor === Number; -} diff --git a/test/_old/_workspace/common/ts-parsing/importsOnly.ts b/test/_old/_workspace/common/ts-parsing/importsOnly.ts deleted file mode 100644 index 98a3308..0000000 --- a/test/_old/_workspace/common/ts-parsing/importsOnly.ts +++ /dev/null @@ -1,10 +0,0 @@ -import 'stringImport'; -import {Specifier1, Specifier2, Specifier3} from 'namedImport'; -import {Specifier1 as Alias1} from 'namedAliasedImport'; -import * as namespaceImport from 'namespace'; -import external = require('externalModule'); -import { - Spec1, - Spec2 as Alias2 -} from 'multiLineImport'; -import Foobar from 'aFile'; diff --git a/test/_old/_workspace/common/ts-parsing/interface.ts b/test/_old/_workspace/common/ts-parsing/interface.ts deleted file mode 100644 index 5a0c8b4..0000000 --- a/test/_old/_workspace/common/ts-parsing/interface.ts +++ /dev/null @@ -1,16 +0,0 @@ -interface NonExportedInterface { - property1: string; - property2: number; - method1(); - method2(param1: string): void; -} - -export interface ExportedInterface { - property1: string; - property2: number; - method1({ param1, param2 }); - method2([param1, param2]): void; -} - -interface Generic { } -interface MultiGeneric { } diff --git a/test/_old/_workspace/common/ts-parsing/module.ts b/test/_old/_workspace/common/ts-parsing/module.ts deleted file mode 100644 index 1f15376..0000000 --- a/test/_old/_workspace/common/ts-parsing/module.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare module 'Module' { - export function modFunc(): void; -} - -declare namespace Namespace { - class NotExported { } - - export enum Exported { - MemberA, - MemberB - } -} diff --git a/test/_old/_workspace/common/ts-parsing/typeAlias.ts b/test/_old/_workspace/common/ts-parsing/typeAlias.ts deleted file mode 100644 index d6a75e2..0000000 --- a/test/_old/_workspace/common/ts-parsing/typeAlias.ts +++ /dev/null @@ -1,3 +0,0 @@ -type Alias = {}; - -export type ExportedAlias = {}; diff --git a/test/_old/_workspace/common/ts-parsing/usagesOnly.ts b/test/_old/_workspace/common/ts-parsing/usagesOnly.ts deleted file mode 100644 index d65059a..0000000 --- a/test/_old/_workspace/common/ts-parsing/usagesOnly.ts +++ /dev/null @@ -1,41 +0,0 @@ -@ClassDecorator -class Class { - @PropertyDecorator() - public notInitializedProperty; - - public typedProperty: TypedPropertyRef; - - public assignedProperty = AssignedProperty; - - @FunctionDecorator() - public func(param: TypedParam, defaultParam = DefaultParam) { - } - - private prv(param): ReturnValue { - let a = PropertyAccess.To.My.Foobar; - - functionCall(MyProperty); - - indexedObject[Indexing]; - - let b; - b = AssignmentToVariable; - - console.log(a); - console.log(b); - - () => () => () => NestedBinaryAssignment === true; - - return null; - } -} - -let a = globalFunction(); - -class Class extends DefaultClass { - -} - -class Class extends GenericClass { - -} diff --git a/test/_old/_workspace/common/ts-parsing/variable.ts b/test/_old/_workspace/common/ts-parsing/variable.ts deleted file mode 100644 index a90d2cb..0000000 --- a/test/_old/_workspace/common/ts-parsing/variable.ts +++ /dev/null @@ -1,12 +0,0 @@ -var NonExportedVariable = ''; - -const NonExportedConst = ''; - -export var ExportedVariable = ''; - -export const ExportedConst = ''; - -export let ExportedLet = ''; - -export let MultiLet1 = '', - MultiLet2 = ''; diff --git a/test/_old/_workspace/extension/extensions/codeActionExtension/empty.ts b/test/_old/_workspace/extension/extensions/codeActionExtension/empty.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/extension/extensions/codeActionExtension/exportedObjects.ts b/test/_old/_workspace/extension/extensions/codeActionExtension/exportedObjects.ts deleted file mode 100644 index 7bbfce0..0000000 --- a/test/_old/_workspace/extension/extensions/codeActionExtension/exportedObjects.ts +++ /dev/null @@ -1,13 +0,0 @@ -export abstract class CodeFixImplementAbstract { - public pubProperty: string; - - public abstract abstractMethod(): void; - public abstract abstractMethodWithParams(p1: string, p2): number; -} - -export interface CodeFixImplementInterface { - property: number; - - interfaceMethod(): string; - interfaceMethodWithParams(p1: string, p2): number; -} diff --git a/test/_old/_workspace/extension/extensions/codeActionExtension/implementInterfaceOrAbstract.ts b/test/_old/_workspace/extension/extensions/codeActionExtension/implementInterfaceOrAbstract.ts deleted file mode 100644 index 33bf0f8..0000000 --- a/test/_old/_workspace/extension/extensions/codeActionExtension/implementInterfaceOrAbstract.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { CodeFixImplementAbstract, CodeFixImplementInterface } from './exportedObjects'; - - -class InterfaceImplement implements CodeFixImplementInterface { -} - -class AbstractImplement extends CodeFixImplementAbstract { -} - -abstract class InternalAbstract { - public method(): void { } - public abstract abstractMethod(): void; -} - -interface InternalInterface { - method(p1: string): void; - methodTwo(); -} - -class InternalInterfaceImplement implements InternalInterface { -} - -class InternalAbstractImplement extends InternalAbstract { -} - -interface GenericInterface { - method(p1: T1): T2; -} - -abstract class GenericAbstractClass { - public abstract abstractMethod(p1: T1): T2; - protected abstract protMethod(p2: T2, p3?: T3); -} - -class ImplementGenericInterface implements GenericInterface { -} - -class ImplementGenericAbstract extends GenericAbstractClass { -} diff --git a/test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionFile.ts b/test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionFile.ts deleted file mode 100644 index 6ec7559..0000000 --- a/test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionFile.ts +++ /dev/null @@ -1,16 +0,0 @@ -"MyCl" -Foobar.Fancie -// isNum -import {isNum} -isNum - -MyClas - -import {AlreadyImported} from './codeCompletionImports'; -ShouldBeImpor - -AlreadyImp - -class YayAClass { } - -YayACla diff --git a/test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionImports.ts b/test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionImports.ts deleted file mode 100644 index 0120b1d..0000000 --- a/test/_old/_workspace/extension/extensions/codeCompletionExtension/codeCompletionImports.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class AlreadyImported { } - -export class ShouldBeImported { } diff --git a/test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts b/test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts deleted file mode 100644 index a76bd2e..0000000 --- a/test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts +++ /dev/null @@ -1,13 +0,0 @@ -import 'string-only'; -import { Foobar } from 'my-lib'; - -class Yay extends Foobar { - public name: string; - - public method(): void { - } -} - -class ArrList { - public method(param: T): T {} -} diff --git a/test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/notParsable.txt b/test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/notParsable.txt deleted file mode 100644 index 0cba08e..0000000 --- a/test/_old/_workspace/extension/extensions/documentSymbolStructureExtension/notParsable.txt +++ /dev/null @@ -1,3 +0,0 @@ -Foobar! - -class foobar {} diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/addImportToDocument.js b/test/_old/_workspace/extension/extensions/importResolveExtension/addImportToDocument.js deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/addImportToDocument.ts b/test/_old/_workspace/extension/extensions/importResolveExtension/addImportToDocument.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/jsfile.js b/test/_old/_workspace/extension/extensions/importResolveExtension/jsfile.js deleted file mode 100644 index fbfae0d..0000000 --- a/test/_old/_workspace/extension/extensions/importResolveExtension/jsfile.js +++ /dev/null @@ -1,9 +0,0 @@ -export class JSFoobar { - constructor() { - this.blub = ''; - } - - getIt() { - return ''; - } -} diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/jsxfile.jsx b/test/_old/_workspace/extension/extensions/importResolveExtension/jsxfile.jsx deleted file mode 100644 index 3a9ebd3..0000000 --- a/test/_old/_workspace/extension/extensions/importResolveExtension/jsxfile.jsx +++ /dev/null @@ -1,15 +0,0 @@ -export function JSXFunction() { - return ( -
- -
- ); -} - -export class JSXClass { - render() { - return ( - - ); - } -} diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/organizeImports.ts b/test/_old/_workspace/extension/extensions/importResolveExtension/organizeImports.ts deleted file mode 100644 index b9b6576..0000000 --- a/test/_old/_workspace/extension/extensions/importResolveExtension/organizeImports.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { StructuralParentClass } from '../subfolderstructure'; -import { Class1, FancierLibraryClass, ExportAlias, MyClass } from '../resourceIndex'; -import 'foo-bar'; - -let foo = new MyClass(); -let a = ExportAlias; -let b = new FancierLibraryClass(); -let c = new StructuralParentClass(); diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/organizeImportsWithExports.ts b/test/_old/_workspace/extension/extensions/importResolveExtension/organizeImportsWithExports.ts deleted file mode 100644 index eea5c77..0000000 --- a/test/_old/_workspace/extension/extensions/importResolveExtension/organizeImportsWithExports.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { moduleFunc } from 'SomeModule'; -import { notUsed } from 'Foobar'; - -export class Test { - constructor() { - init(); - } -} - -function init() { moduleFunc(); } diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/sameDirectory.ts b/test/_old/_workspace/extension/extensions/importResolveExtension/sameDirectory.ts deleted file mode 100644 index 0db5ae8..0000000 --- a/test/_old/_workspace/extension/extensions/importResolveExtension/sameDirectory.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class AddImportSameDirectory { - -} diff --git a/test/_old/_workspace/extension/extensions/importResolveExtension/sub1/sub2/sub3/subFile.ts b/test/_old/_workspace/extension/extensions/importResolveExtension/sub1/sub2/sub3/subFile.ts deleted file mode 100644 index e70a883..0000000 --- a/test/_old/_workspace/extension/extensions/importResolveExtension/sub1/sub2/sub3/subFile.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class SubFileLevel3 { - -} diff --git a/test/_old/_workspace/extension/extensions/organizeImportsOnSaveExtension/organizeFile.ts b/test/_old/_workspace/extension/extensions/organizeImportsOnSaveExtension/organizeFile.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/extension/managers/ClassManagerFile.ts b/test/_old/_workspace/extension/managers/ClassManagerFile.ts deleted file mode 100644 index 1e4f45f..0000000 --- a/test/_old/_workspace/extension/managers/ClassManagerFile.ts +++ /dev/null @@ -1,47 +0,0 @@ - -class ManagedClass { - -} - -class ManagedClassWithCtor { - constructor(public foobar: string, barbaz: number) { } -} - -class ManagedClassWithMethods { - public method(): void { } - - protected whatever(): string { - return ''; - } - - private ohyea(foo: string, bar: number): ManagedClass { - return {} as any; - } -} - -class ManagedClassWithProperties { - public foo: string; - protected bar: string; - private baz: string; -} - -class ManagedClassFull { - public foo: string; - protected bar: string; - private baz: string; - - constructor(public foobar: string, barbaz: number) { } - - public method(): void { } - - protected whatever(): string { - return ''; - } - - private ohyea(foo: string, bar: number): ManagedClass { - return {} as any; - } -} - -class EmptyClass { -} diff --git a/test/_old/_workspace/foobar.ts b/test/_old/_workspace/foobar.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/node_modules/@types/node/README.md b/test/_old/_workspace/node_modules/@types/node/README.md deleted file mode 100644 index 12fe4eb..0000000 --- a/test/_old/_workspace/node_modules/@types/node/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Installation -> `npm install --save @types/node` - -# Summary -This package contains type definitions for Node.js v6.x (http://nodejs.org/). - -# Details -Files were exported from https://www.github.com/DefinitelyTyped/DefinitelyTyped/tree/types-2.0/node - -Additional Details - * Last updated: Thu, 06 Oct 2016 05:24:40 GMT - * File structure: MultipleModules - * Library Dependencies: none - * Module Dependencies: none - * Global values: Buffer, NodeJS, SlowBuffer, __dirname, __filename, clearImmediate, clearInterval, clearTimeout, console, exports, global, module, process, require, setImmediate, setInterval, setTimeout - -# Credits -These definitions were written by Microsoft TypeScript , DefinitelyTyped . diff --git a/test/_old/_workspace/node_modules/@types/node/index.d.ts b/test/_old/_workspace/node_modules/@types/node/index.d.ts deleted file mode 100644 index 445c6f5..0000000 --- a/test/_old/_workspace/node_modules/@types/node/index.d.ts +++ /dev/null @@ -1,3640 +0,0 @@ -// Type definitions for Node.js v6.x -// Project: http://nodejs.org/ -// Definitions by: Microsoft TypeScript , DefinitelyTyped -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -/************************************************ -* * -* Node.js v6.x API * -* * -************************************************/ - -// This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build -interface Console { - Console: typeof NodeJS.Console; - assert(value: any, message?: string, ...optionalParams: any[]): void; - dir(obj: any, options?: {showHidden?: boolean, depth?: number, colors?: boolean}): void; - error(message?: any, ...optionalParams: any[]): void; - info(message?: any, ...optionalParams: any[]): void; - log(message?: any, ...optionalParams: any[]): void; - time(label: string): void; - timeEnd(label: string): void; - trace(message?: any, ...optionalParams: any[]): void; - warn(message?: any, ...optionalParams: any[]): void; -} - -interface Error { - stack?: string; -} - -interface ErrorConstructor { - captureStackTrace(targetObject: Object, constructorOpt?: Function): void; - stackTraceLimit: number; -} - -// compat for TypeScript 1.8 -// if you use with --target es3 or --target es5 and use below definitions, -// use the lib.es6.d.ts that is bundled with TypeScript 1.8. -interface MapConstructor { } -interface WeakMapConstructor { } -interface SetConstructor { } -interface WeakSetConstructor { } - -/************************************************ -* * -* GLOBAL * -* * -************************************************/ -declare var process: NodeJS.Process; -declare var global: NodeJS.Global; -declare var console: Console; - -declare var __filename: string; -declare var __dirname: string; - -declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; -declare function clearTimeout(timeoutId: NodeJS.Timer): void; -declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; -declare function clearInterval(intervalId: NodeJS.Timer): void; -declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; -declare function clearImmediate(immediateId: any): void; - -interface NodeRequireFunction { - (id: string): any; -} - -interface NodeRequire extends NodeRequireFunction { - resolve(id: string): string; - cache: any; - extensions: any; - main: any; -} - -declare var require: NodeRequire; - -interface NodeModule { - exports: any; - require: NodeRequireFunction; - id: string; - filename: string; - loaded: boolean; - parent: any; - children: any[]; -} - -declare var module: NodeModule; - -// Same as module.exports -declare var exports: any; -declare var SlowBuffer: { - new (str: string, encoding?: string): Buffer; - new (size: number): Buffer; - new (size: Uint8Array): Buffer; - new (array: any[]): Buffer; - prototype: Buffer; - isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; - concat(list: Buffer[], totalLength?: number): Buffer; -}; - - -// Buffer class -type BufferEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "binary" | "hex"; -interface Buffer extends NodeBuffer { } - -/** - * Raw data is stored in instances of the Buffer class. - * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. - * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' - */ -declare var Buffer: { - /** - * Allocates a new buffer containing the given {str}. - * - * @param str String to store in buffer. - * @param encoding encoding to use, optional. Default is 'utf8' - */ - new (str: string, encoding?: string): Buffer; - /** - * Allocates a new buffer of {size} octets. - * - * @param size count of octets to allocate. - */ - new (size: number): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - */ - new (array: Uint8Array): Buffer; - /** - * Produces a Buffer backed by the same allocated memory as - * the given {ArrayBuffer}. - * - * - * @param arrayBuffer The ArrayBuffer with which to share memory. - */ - new (arrayBuffer: ArrayBuffer): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - */ - new (array: any[]): Buffer; - /** - * Copies the passed {buffer} data onto a new {Buffer} instance. - * - * @param buffer The buffer to copy. - */ - new (buffer: Buffer): Buffer; - prototype: Buffer; - /** - * Allocates a new Buffer using an {array} of octets. - * - * @param array - */ - from(array: any[]): Buffer; - /** - * When passed a reference to the .buffer property of a TypedArray instance, - * the newly created Buffer will share the same allocated memory as the TypedArray. - * The optional {byteOffset} and {length} arguments specify a memory range - * within the {arrayBuffer} that will be shared by the Buffer. - * - * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() - * @param byteOffset - * @param length - */ - from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; - /** - * Copies the passed {buffer} data onto a new Buffer instance. - * - * @param buffer - */ - from(buffer: Buffer): Buffer; - /** - * Creates a new Buffer containing the given JavaScript string {str}. - * If provided, the {encoding} parameter identifies the character encoding. - * If not provided, {encoding} defaults to 'utf8'. - * - * @param str - */ - from(str: string, encoding?: string): Buffer; - /** - * Returns true if {obj} is a Buffer - * - * @param obj object to test. - */ - isBuffer(obj: any): obj is Buffer; - /** - * Returns true if {encoding} is a valid encoding argument. - * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' - * - * @param encoding string to test. - */ - isEncoding(encoding: string): boolean; - /** - * Gives the actual byte length of a string. encoding defaults to 'utf8'. - * This is not the same as String.prototype.length since that returns the number of characters in a string. - * - * @param string string to test. - * @param encoding encoding used to evaluate (defaults to 'utf8') - */ - byteLength(string: string, encoding?: string): number; - /** - * Returns a buffer which is the result of concatenating all the buffers in the list together. - * - * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. - * If the list has exactly one item, then the first item of the list is returned. - * If the list has more than one item, then a new Buffer is created. - * - * @param list An array of Buffer objects to concatenate - * @param totalLength Total length of the buffers when concatenated. - * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. - */ - concat(list: Buffer[], totalLength?: number): Buffer; - /** - * The same as buf1.compare(buf2). - */ - compare(buf1: Buffer, buf2: Buffer): number; - /** - * Allocates a new buffer of {size} octets. - * - * @param size count of octets to allocate. - * @param fill if specified, buffer will be initialized by calling buf.fill(fill). - * If parameter is omitted, buffer will be filled with zeros. - * @param encoding encoding used for call to buf.fill while initalizing - */ - alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; - /** - * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents - * of the newly created Buffer are unknown and may contain sensitive data. - * - * @param size count of octets to allocate - */ - allocUnsafe(size: number): Buffer; - /** - * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents - * of the newly created Buffer are unknown and may contain sensitive data. - * - * @param size count of octets to allocate - */ - allocUnsafeSlow(size: number): Buffer; -}; - -/************************************************ -* * -* GLOBAL INTERFACES * -* * -************************************************/ -declare namespace NodeJS { - export var Console: { - prototype: Console; - new(stdout: WritableStream, stderr?: WritableStream): Console; - } - - export interface ErrnoException extends Error { - errno?: string; - code?: string; - path?: string; - syscall?: string; - stack?: string; - } - - export class EventEmitter { - addListener(event: string | symbol, listener: Function): this; - on(event: string | symbol, listener: Function): this; - once(event: string | symbol, listener: Function): this; - removeListener(event: string | symbol, listener: Function): this; - removeAllListeners(event?: string | symbol): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string | symbol): Function[]; - emit(event: string | symbol, ...args: any[]): boolean; - listenerCount(type: string | symbol): number; - // Added in Node 6... - prependListener(event: string | symbol, listener: Function): this; - prependOnceListener(event: string | symbol, listener: Function): this; - eventNames(): (string | symbol)[]; - } - - export interface ReadableStream extends EventEmitter { - readable: boolean; - read(size?: number): string | Buffer; - setEncoding(encoding: string | null): void; - pause(): ReadableStream; - resume(): ReadableStream; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: string): void; - unshift(chunk: Buffer): void; - wrap(oldStream: ReadableStream): ReadableStream; - } - - export interface WritableStream extends EventEmitter { - writable: boolean; - write(buffer: Buffer | string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } - - export interface ReadWriteStream extends ReadableStream, WritableStream { - pause(): ReadWriteStream; - resume(): ReadWriteStream; - } - - export interface Events extends EventEmitter { } - - export interface Domain extends Events { - run(fn: Function): void; - add(emitter: Events): void; - remove(emitter: Events): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; - - addListener(event: string, listener: Function): this; - on(event: string, listener: Function): this; - once(event: string, listener: Function): this; - removeListener(event: string, listener: Function): this; - removeAllListeners(event?: string): this; - } - - export interface MemoryUsage { - rss: number; - heapTotal: number; - heapUsed: number; - } - - export interface ProcessVersions { - http_parser: string; - node: string; - v8: string; - ares: string; - uv: string; - zlib: string; - modules: string; - openssl: string; - } - - export interface Process extends EventEmitter { - stdout: WritableStream; - stderr: WritableStream; - stdin: ReadableStream; - argv: string[]; - execArgv: string[]; - execPath: string; - abort(): void; - chdir(directory: string): void; - cwd(): string; - env: any; - exit(code?: number): void; - exitCode: number; - getgid(): number; - setgid(id: number): void; - setgid(id: string): void; - getuid(): number; - setuid(id: number): void; - setuid(id: string): void; - version: string; - versions: ProcessVersions; - config: { - target_defaults: { - cflags: any[]; - default_configuration: string; - defines: string[]; - include_dirs: string[]; - libraries: string[]; - }; - variables: { - clang: number; - host_arch: string; - node_install_npm: boolean; - node_install_waf: boolean; - node_prefix: string; - node_shared_openssl: boolean; - node_shared_v8: boolean; - node_shared_zlib: boolean; - node_use_dtrace: boolean; - node_use_etw: boolean; - node_use_openssl: boolean; - target_arch: string; - v8_no_strict_aliasing: number; - v8_use_snapshot: boolean; - visibility: string; - }; - }; - kill(pid: number, signal?: string | number): void; - pid: number; - title: string; - arch: string; - platform: string; - memoryUsage(): MemoryUsage; - nextTick(callback: Function, ...args: any[]): void; - umask(mask?: number): number; - uptime(): number; - hrtime(time?: [number, number]): [number, number]; - domain: Domain; - - // Worker - send?(message: any, sendHandle?: any): void; - disconnect(): void; - connected: boolean; - } - - export interface Global { - Array: typeof Array; - ArrayBuffer: typeof ArrayBuffer; - Boolean: typeof Boolean; - Buffer: typeof Buffer; - DataView: typeof DataView; - Date: typeof Date; - Error: typeof Error; - EvalError: typeof EvalError; - Float32Array: typeof Float32Array; - Float64Array: typeof Float64Array; - Function: typeof Function; - GLOBAL: Global; - Infinity: typeof Infinity; - Int16Array: typeof Int16Array; - Int32Array: typeof Int32Array; - Int8Array: typeof Int8Array; - Intl: typeof Intl; - JSON: typeof JSON; - Map: MapConstructor; - Math: typeof Math; - NaN: typeof NaN; - Number: typeof Number; - Object: typeof Object; - Promise: Function; - RangeError: typeof RangeError; - ReferenceError: typeof ReferenceError; - RegExp: typeof RegExp; - Set: SetConstructor; - String: typeof String; - Symbol: Function; - SyntaxError: typeof SyntaxError; - TypeError: typeof TypeError; - URIError: typeof URIError; - Uint16Array: typeof Uint16Array; - Uint32Array: typeof Uint32Array; - Uint8Array: typeof Uint8Array; - Uint8ClampedArray: Function; - WeakMap: WeakMapConstructor; - WeakSet: WeakSetConstructor; - clearImmediate: (immediateId: any) => void; - clearInterval: (intervalId: NodeJS.Timer) => void; - clearTimeout: (timeoutId: NodeJS.Timer) => void; - console: typeof console; - decodeURI: typeof decodeURI; - decodeURIComponent: typeof decodeURIComponent; - encodeURI: typeof encodeURI; - encodeURIComponent: typeof encodeURIComponent; - escape: (str: string) => string; - eval: typeof eval; - global: Global; - isFinite: typeof isFinite; - isNaN: typeof isNaN; - parseFloat: typeof parseFloat; - parseInt: typeof parseInt; - process: Process; - root: Global; - setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => any; - setInterval: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - setTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - undefined: typeof undefined; - unescape: (str: string) => string; - gc: () => void; - v8debug?: any; - } - - export interface Timer { - ref(): void; - unref(): void; - } -} - -interface IterableIterator { } - -/** - * @deprecated - */ -interface NodeBuffer extends Uint8Array { - write(string: string, offset?: number, length?: number, encoding?: string): number; - toString(encoding?: string, start?: number, end?: number): string; - toJSON(): { type: 'Buffer', data: any[] }; - equals(otherBuffer: Buffer): boolean; - compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; - copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; - slice(start?: number, end?: number): Buffer; - writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readUInt8(offset: number, noAssert?: boolean): number; - readUInt16LE(offset: number, noAssert?: boolean): number; - readUInt16BE(offset: number, noAssert?: boolean): number; - readUInt32LE(offset: number, noAssert?: boolean): number; - readUInt32BE(offset: number, noAssert?: boolean): number; - readInt8(offset: number, noAssert?: boolean): number; - readInt16LE(offset: number, noAssert?: boolean): number; - readInt16BE(offset: number, noAssert?: boolean): number; - readInt32LE(offset: number, noAssert?: boolean): number; - readInt32BE(offset: number, noAssert?: boolean): number; - readFloatLE(offset: number, noAssert?: boolean): number; - readFloatBE(offset: number, noAssert?: boolean): number; - readDoubleLE(offset: number, noAssert?: boolean): number; - readDoubleBE(offset: number, noAssert?: boolean): number; - swap16(): Buffer; - swap32(): Buffer; - swap64(): Buffer; - writeUInt8(value: number, offset: number, noAssert?: boolean): number; - writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; - writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; - writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; - writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; - writeInt8(value: number, offset: number, noAssert?: boolean): number; - writeInt16LE(value: number, offset: number, noAssert?: boolean): number; - writeInt16BE(value: number, offset: number, noAssert?: boolean): number; - writeInt32LE(value: number, offset: number, noAssert?: boolean): number; - writeInt32BE(value: number, offset: number, noAssert?: boolean): number; - writeFloatLE(value: number, offset: number, noAssert?: boolean): number; - writeFloatBE(value: number, offset: number, noAssert?: boolean): number; - writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; - writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; - fill(value: any, offset?: number, end?: number): this; - indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; - lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; - entries(): IterableIterator<[number, number]>; - includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; - keys(): IterableIterator; - values(): IterableIterator; -} - -/************************************************ -* * -* MODULES * -* * -************************************************/ -declare module "buffer" { - export var INSPECT_MAX_BYTES: number; - var BuffType: typeof Buffer; - var SlowBuffType: typeof SlowBuffer; - export { BuffType as Buffer, SlowBuffType as SlowBuffer }; -} - -declare module "querystring" { - export interface StringifyOptions { - encodeURIComponent?: Function; - } - - export interface ParseOptions { - maxKeys?: number; - decodeURIComponent?: Function; - } - - export function stringify(obj: T, sep?: string, eq?: string, options?: StringifyOptions): string; - export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): any; - export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): T; - export function escape(str: string): string; - export function unescape(str: string): string; -} - -declare module "events" { - export class EventEmitter extends NodeJS.EventEmitter { - static EventEmitter: EventEmitter; - static listenerCount(emitter: EventEmitter, event: string | symbol): number; // deprecated - static defaultMaxListeners: number; - - addListener(event: string | symbol, listener: Function): this; - on(event: string | symbol, listener: Function): this; - once(event: string | symbol, listener: Function): this; - prependListener(event: string | symbol, listener: Function): this; - prependOnceListener(event: string | symbol, listener: Function): this; - removeListener(event: string | symbol, listener: Function): this; - removeAllListeners(event?: string | symbol): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string | symbol): Function[]; - emit(event: string | symbol, ...args: any[]): boolean; - eventNames(): (string | symbol)[]; - listenerCount(type: string | symbol): number; - } -} - -declare module "http" { - import * as events from "events"; - import * as net from "net"; - import * as stream from "stream"; - - export interface RequestOptions { - protocol?: string; - host?: string; - hostname?: string; - family?: number; - port?: number; - localAddress?: string; - socketPath?: string; - method?: string; - path?: string; - headers?: { [key: string]: any }; - auth?: string; - agent?: Agent | boolean; - } - - export interface Server extends net.Server { - setTimeout(msecs: number, callback: Function): void; - maxHeadersCount: number; - timeout: number; - listening: boolean; - } - /** - * @deprecated Use IncomingMessage - */ - export interface ServerRequest extends IncomingMessage { - connection: net.Socket; - } - export interface ServerResponse extends stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - writeContinue(): void; - writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; - writeHead(statusCode: number, headers?: any): void; - statusCode: number; - statusMessage: string; - headersSent: boolean; - setHeader(name: string, value: string | string[]): void; - setTimeout(msecs: number, callback: Function): ServerResponse; - sendDate: boolean; - getHeader(name: string): string; - removeHeader(name: string): void; - write(chunk: any, encoding?: string): any; - addTrailers(headers: any): void; - finished: boolean; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface ClientRequest extends stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - write(chunk: any, encoding?: string): void; - abort(): void; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; - - setHeader(name: string, value: string | string[]): void; - getHeader(name: string): string; - removeHeader(name: string): void; - addTrailers(headers: any): void; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface IncomingMessage extends stream.Readable { - httpVersion: string; - httpVersionMajor: number; - httpVersionMinor: number; - connection: net.Socket; - headers: any; - rawHeaders: string[]; - trailers: any; - rawTrailers: any; - setTimeout(msecs: number, callback: Function): NodeJS.Timer; - /** - * Only valid for request obtained from http.Server. - */ - method?: string; - /** - * Only valid for request obtained from http.Server. - */ - url?: string; - /** - * Only valid for response obtained from http.ClientRequest. - */ - statusCode?: number; - /** - * Only valid for response obtained from http.ClientRequest. - */ - statusMessage?: string; - socket: net.Socket; - destroy(error?: Error): void; - } - /** - * @deprecated Use IncomingMessage - */ - export interface ClientResponse extends IncomingMessage { } - - export interface AgentOptions { - /** - * Keep sockets around in a pool to be used by other requests in the future. Default = false - */ - keepAlive?: boolean; - /** - * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. - * Only relevant if keepAlive is set to true. - */ - keepAliveMsecs?: number; - /** - * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity - */ - maxSockets?: number; - /** - * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. - */ - maxFreeSockets?: number; - } - - export class Agent { - maxSockets: number; - sockets: any; - requests: any; - - constructor(opts?: AgentOptions); - - /** - * Destroy any sockets that are currently in use by the agent. - * It is usually not necessary to do this. However, if you are using an agent with KeepAlive enabled, - * then it is best to explicitly shut down the agent when you know that it will no longer be used. Otherwise, - * sockets may hang open for quite a long time before the server terminates them. - */ - destroy(): void; - } - - export var METHODS: string[]; - - export var STATUS_CODES: { - [errorCode: number]: string; - [errorCode: string]: string; - }; - export function createServer(requestListener?: (request: IncomingMessage, response: ServerResponse) => void): Server; - export function createClient(port?: number, host?: string): any; - export function request(options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; - export function get(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; - export var globalAgent: Agent; -} - -declare module "cluster" { - import * as child from "child_process"; - import * as events from "events"; - import * as net from "net"; - - // interfaces - export interface ClusterSettings { - execArgv?: string[]; // default: process.execArgv - exec?: string; - args?: string[]; - silent?: boolean; - stdio?: any[]; - uid?: number; - gid?: number; - } - - export interface ClusterSetupMasterSettings { - exec?: string; // default: process.argv[1] - args?: string[]; // default: process.argv.slice(2) - silent?: boolean; // default: false - stdio?: any[]; - } - - export interface Address { - address: string; - port: number; - addressType: number | "udp4" | "udp6"; // 4, 6, -1, "udp4", "udp6" - } - - export class Worker extends events.EventEmitter { - id: string; - process: child.ChildProcess; - suicide: boolean; - send(message: any, sendHandle?: any): boolean; - kill(signal?: string): void; - destroy(signal?: string): void; - disconnect(): void; - isConnected(): boolean; - isDead(): boolean; - exitedAfterDisconnect: boolean; - - /** - * events.EventEmitter - * 1. disconnect - * 2. error - * 3. exit - * 4. listening - * 5. message - * 6. online - */ - addListener(event: string, listener: Function): this; - addListener(event: "disconnect", listener: () => void): this; - addListener(event: "error", listener: (code: number, signal: string) => void): this; - addListener(event: "exit", listener: (code: number, signal: string) => void): this; - addListener(event: "listening", listener: (address: Address) => void): this; - addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - addListener(event: "online", listener: () => void): this; - - emit(event: string, listener: Function): boolean - emit(event: "disconnect", listener: () => void): boolean - emit(event: "error", listener: (code: number, signal: string) => void): boolean - emit(event: "exit", listener: (code: number, signal: string) => void): boolean - emit(event: "listening", listener: (address: Address) => void): boolean - emit(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): boolean - emit(event: "online", listener: () => void): boolean - - on(event: string, listener: Function): this; - on(event: "disconnect", listener: () => void): this; - on(event: "error", listener: (code: number, signal: string) => void): this; - on(event: "exit", listener: (code: number, signal: string) => void): this; - on(event: "listening", listener: (address: Address) => void): this; - on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - on(event: "online", listener: () => void): this; - - once(event: string, listener: Function): this; - once(event: "disconnect", listener: () => void): this; - once(event: "error", listener: (code: number, signal: string) => void): this; - once(event: "exit", listener: (code: number, signal: string) => void): this; - once(event: "listening", listener: (address: Address) => void): this; - once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - once(event: "online", listener: () => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "disconnect", listener: () => void): this; - prependListener(event: "error", listener: (code: number, signal: string) => void): this; - prependListener(event: "exit", listener: (code: number, signal: string) => void): this; - prependListener(event: "listening", listener: (address: Address) => void): this; - prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependListener(event: "online", listener: () => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "disconnect", listener: () => void): this; - prependOnceListener(event: "error", listener: (code: number, signal: string) => void): this; - prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this; - prependOnceListener(event: "listening", listener: (address: Address) => void): this; - prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependOnceListener(event: "online", listener: () => void): this; - } - - export interface Cluster extends events.EventEmitter { - Worker: Worker; - disconnect(callback?: Function): void; - fork(env?: any): Worker; - isMaster: boolean; - isWorker: boolean; - // TODO: cluster.schedulingPolicy - settings: ClusterSettings; - setupMaster(settings?: ClusterSetupMasterSettings): void; - worker: Worker; - workers: { - [index: string]: Worker - }; - - /** - * events.EventEmitter - * 1. disconnect - * 2. exit - * 3. fork - * 4. listening - * 5. message - * 6. online - * 7. setup - */ - addListener(event: string, listener: Function): this; - addListener(event: "disconnect", listener: (worker: Worker) => void): this; - addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - addListener(event: "fork", listener: (worker: Worker) => void): this; - addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - addListener(event: "online", listener: (worker: Worker) => void): this; - addListener(event: "setup", listener: (settings: any) => void): this; - - emit(event: string, listener: Function): boolean; - emit(event: "disconnect", listener: (worker: Worker) => void): boolean; - emit(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): boolean; - emit(event: "fork", listener: (worker: Worker) => void): boolean; - emit(event: "listening", listener: (worker: Worker, address: Address) => void): boolean; - emit(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): boolean; - emit(event: "online", listener: (worker: Worker) => void): boolean; - emit(event: "setup", listener: (settings: any) => void): boolean; - - on(event: string, listener: Function): this; - on(event: "disconnect", listener: (worker: Worker) => void): this; - on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - on(event: "fork", listener: (worker: Worker) => void): this; - on(event: "listening", listener: (worker: Worker, address: Address) => void): this; - on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - on(event: "online", listener: (worker: Worker) => void): this; - on(event: "setup", listener: (settings: any) => void): this; - - once(event: string, listener: Function): this; - once(event: "disconnect", listener: (worker: Worker) => void): this; - once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - once(event: "fork", listener: (worker: Worker) => void): this; - once(event: "listening", listener: (worker: Worker, address: Address) => void): this; - once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - once(event: "online", listener: (worker: Worker) => void): this; - once(event: "setup", listener: (settings: any) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "disconnect", listener: (worker: Worker) => void): this; - prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - prependListener(event: "fork", listener: (worker: Worker) => void): this; - prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependListener(event: "online", listener: (worker: Worker) => void): this; - prependListener(event: "setup", listener: (settings: any) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this; - prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - prependOnceListener(event: "fork", listener: (worker: Worker) => void): this; - prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependOnceListener(event: "online", listener: (worker: Worker) => void): this; - prependOnceListener(event: "setup", listener: (settings: any) => void): this; - - } - - export function disconnect(callback?: Function): void; - export function fork(env?: any): Worker; - export var isMaster: boolean; - export var isWorker: boolean; - // TODO: cluster.schedulingPolicy - export var settings: ClusterSettings; - export function setupMaster(settings?: ClusterSetupMasterSettings): void; - export var worker: Worker; - export var workers: { - [index: string]: Worker - }; - - /** - * events.EventEmitter - * 1. disconnect - * 2. exit - * 3. fork - * 4. listening - * 5. message - * 6. online - * 7. setup - */ - export function addListener(event: string, listener: Function): Cluster; - export function addListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function addListener(event: "fork", listener: (worker: Worker) => void): Cluster; - export function addListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function addListener(event: "online", listener: (worker: Worker) => void): Cluster; - export function addListener(event: "setup", listener: (settings: any) => void): Cluster; - - export function emit(event: string, listener: Function): boolean; - export function emit(event: "disconnect", listener: (worker: Worker) => void): boolean; - export function emit(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): boolean; - export function emit(event: "fork", listener: (worker: Worker) => void): boolean; - export function emit(event: "listening", listener: (worker: Worker, address: Address) => void): boolean; - export function emit(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): boolean; - export function emit(event: "online", listener: (worker: Worker) => void): boolean; - export function emit(event: "setup", listener: (settings: any) => void): boolean; - - export function on(event: string, listener: Function): Cluster; - export function on(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function on(event: "fork", listener: (worker: Worker) => void): Cluster; - export function on(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function on(event: "online", listener: (worker: Worker) => void): Cluster; - export function on(event: "setup", listener: (settings: any) => void): Cluster; - - export function once(event: string, listener: Function): Cluster; - export function once(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function once(event: "fork", listener: (worker: Worker) => void): Cluster; - export function once(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function once(event: "online", listener: (worker: Worker) => void): Cluster; - export function once(event: "setup", listener: (settings: any) => void): Cluster; - - export function removeListener(event: string, listener: Function): Cluster; - export function removeAllListeners(event?: string): Cluster; - export function setMaxListeners(n: number): Cluster; - export function getMaxListeners(): number; - export function listeners(event: string): Function[]; - export function listenerCount(type: string): number; - - export function prependListener(event: string, listener: Function): Cluster; - export function prependListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function prependListener(event: "fork", listener: (worker: Worker) => void): Cluster; - export function prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function prependListener(event: "online", listener: (worker: Worker) => void): Cluster; - export function prependListener(event: "setup", listener: (settings: any) => void): Cluster; - - export function prependOnceListener(event: string, listener: Function): Cluster; - export function prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function prependOnceListener(event: "fork", listener: (worker: Worker) => void): Cluster; - export function prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function prependOnceListener(event: "online", listener: (worker: Worker) => void): Cluster; - export function prependOnceListener(event: "setup", listener: (settings: any) => void): Cluster; - - export function eventNames(): string[]; -} - -declare module "zlib" { - import * as stream from "stream"; - export interface ZlibOptions { chunkSize?: number; windowBits?: number; level?: number; memLevel?: number; strategy?: number; dictionary?: any; finishFlush?: number } - - export interface Gzip extends stream.Transform { } - export interface Gunzip extends stream.Transform { } - export interface Deflate extends stream.Transform { } - export interface Inflate extends stream.Transform { } - export interface DeflateRaw extends stream.Transform { } - export interface InflateRaw extends stream.Transform { } - export interface Unzip extends stream.Transform { } - - export function createGzip(options?: ZlibOptions): Gzip; - export function createGunzip(options?: ZlibOptions): Gunzip; - export function createDeflate(options?: ZlibOptions): Deflate; - export function createInflate(options?: ZlibOptions): Inflate; - export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; - export function createInflateRaw(options?: ZlibOptions): InflateRaw; - export function createUnzip(options?: ZlibOptions): Unzip; - - export function deflate(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function deflateSync(buf: Buffer, options?: ZlibOptions): any; - export function deflateRaw(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function deflateRawSync(buf: Buffer, options?: ZlibOptions): any; - export function gzip(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function gzipSync(buf: Buffer, options?: ZlibOptions): any; - export function gunzip(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function gunzipSync(buf: Buffer, options?: ZlibOptions): any; - export function inflate(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function inflateSync(buf: Buffer, options?: ZlibOptions): any; - export function inflateRaw(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function inflateRawSync(buf: Buffer, options?: ZlibOptions): any; - export function unzip(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function unzipSync(buf: Buffer, options?: ZlibOptions): any; - - // Constants - export var Z_NO_FLUSH: number; - export var Z_PARTIAL_FLUSH: number; - export var Z_SYNC_FLUSH: number; - export var Z_FULL_FLUSH: number; - export var Z_FINISH: number; - export var Z_BLOCK: number; - export var Z_TREES: number; - export var Z_OK: number; - export var Z_STREAM_END: number; - export var Z_NEED_DICT: number; - export var Z_ERRNO: number; - export var Z_STREAM_ERROR: number; - export var Z_DATA_ERROR: number; - export var Z_MEM_ERROR: number; - export var Z_BUF_ERROR: number; - export var Z_VERSION_ERROR: number; - export var Z_NO_COMPRESSION: number; - export var Z_BEST_SPEED: number; - export var Z_BEST_COMPRESSION: number; - export var Z_DEFAULT_COMPRESSION: number; - export var Z_FILTERED: number; - export var Z_HUFFMAN_ONLY: number; - export var Z_RLE: number; - export var Z_FIXED: number; - export var Z_DEFAULT_STRATEGY: number; - export var Z_BINARY: number; - export var Z_TEXT: number; - export var Z_ASCII: number; - export var Z_UNKNOWN: number; - export var Z_DEFLATED: number; - export var Z_NULL: number; -} - -declare module "os" { - export interface CpuInfo { - model: string; - speed: number; - times: { - user: number; - nice: number; - sys: number; - idle: number; - irq: number; - }; - } - - export interface NetworkInterfaceInfo { - address: string; - netmask: string; - family: string; - mac: string; - internal: boolean; - } - - export function hostname(): string; - export function loadavg(): number[]; - export function uptime(): number; - export function freemem(): number; - export function totalmem(): number; - export function cpus(): CpuInfo[]; - export function type(): string; - export function release(): string; - export function networkInterfaces(): { [index: string]: NetworkInterfaceInfo[] }; - export function homedir(): string; - export function userInfo(options?: { encoding: string }): { username: string, uid: number, gid: number, shell: any, homedir: string } - export var constants: { - UV_UDP_REUSEADDR: number, - errno: { - SIGHUP: number; - SIGINT: number; - SIGQUIT: number; - SIGILL: number; - SIGTRAP: number; - SIGABRT: number; - SIGIOT: number; - SIGBUS: number; - SIGFPE: number; - SIGKILL: number; - SIGUSR1: number; - SIGSEGV: number; - SIGUSR2: number; - SIGPIPE: number; - SIGALRM: number; - SIGTERM: number; - SIGCHLD: number; - SIGSTKFLT: number; - SIGCONT: number; - SIGSTOP: number; - SIGTSTP: number; - SIGTTIN: number; - SIGTTOU: number; - SIGURG: number; - SIGXCPU: number; - SIGXFSZ: number; - SIGVTALRM: number; - SIGPROF: number; - SIGWINCH: number; - SIGIO: number; - SIGPOLL: number; - SIGPWR: number; - SIGSYS: number; - SIGUNUSED: number; - }, - signals: { - E2BIG: number; - EACCES: number; - EADDRINUSE: number; - EADDRNOTAVAIL: number; - EAFNOSUPPORT: number; - EAGAIN: number; - EALREADY: number; - EBADF: number; - EBADMSG: number; - EBUSY: number; - ECANCELED: number; - ECHILD: number; - ECONNABORTED: number; - ECONNREFUSED: number; - ECONNRESET: number; - EDEADLK: number; - EDESTADDRREQ: number; - EDOM: number; - EDQUOT: number; - EEXIST: number; - EFAULT: number; - EFBIG: number; - EHOSTUNREACH: number; - EIDRM: number; - EILSEQ: number; - EINPROGRESS: number; - EINTR: number; - EINVAL: number; - EIO: number; - EISCONN: number; - EISDIR: number; - ELOOP: number; - EMFILE: number; - EMLINK: number; - EMSGSIZE: number; - EMULTIHOP: number; - ENAMETOOLONG: number; - ENETDOWN: number; - ENETRESET: number; - ENETUNREACH: number; - ENFILE: number; - ENOBUFS: number; - ENODATA: number; - ENODEV: number; - ENOENT: number; - ENOEXEC: number; - ENOLCK: number; - ENOLINK: number; - ENOMEM: number; - ENOMSG: number; - ENOPROTOOPT: number; - ENOSPC: number; - ENOSR: number; - ENOSTR: number; - ENOSYS: number; - ENOTCONN: number; - ENOTDIR: number; - ENOTEMPTY: number; - ENOTSOCK: number; - ENOTSUP: number; - ENOTTY: number; - ENXIO: number; - EOPNOTSUPP: number; - EOVERFLOW: number; - EPERM: number; - EPIPE: number; - EPROTO: number; - EPROTONOSUPPORT: number; - EPROTOTYPE: number; - ERANGE: number; - EROFS: number; - ESPIPE: number; - ESRCH: number; - ESTALE: number; - ETIME: number; - ETIMEDOUT: number; - ETXTBSY: number; - EWOULDBLOCK: number; - EXDEV: number; - }, - }; - export function arch(): string; - export function platform(): string; - export function tmpdir(): string; - export var EOL: string; - export function endianness(): "BE" | "LE"; -} - -declare module "https" { - import * as tls from "tls"; - import * as events from "events"; - import * as http from "http"; - - export interface ServerOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - crl?: any; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: any; - SNICallback?: (servername: string, cb: (err: Error, ctx: tls.SecureContext) => any) => any; - } - - export interface RequestOptions extends http.RequestOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - secureProtocol?: string; - } - - export interface Agent extends http.Agent { } - - export interface AgentOptions extends http.AgentOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - secureProtocol?: string; - maxCachedSessions?: number; - } - - export var Agent: { - new (options?: AgentOptions): Agent; - }; - export interface Server extends tls.Server { } - export function createServer(options: ServerOptions, requestListener?: Function): Server; - export function request(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; - export function get(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; - export var globalAgent: Agent; -} - -declare module "punycode" { - export function decode(string: string): string; - export function encode(string: string): string; - export function toUnicode(domain: string): string; - export function toASCII(domain: string): string; - export var ucs2: ucs2; - interface ucs2 { - decode(string: string): number[]; - encode(codePoints: number[]): string; - } - export var version: any; -} - -declare module "repl" { - import * as stream from "stream"; - import * as readline from "readline"; - - export interface ReplOptions { - prompt?: string; - input?: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - terminal?: boolean; - eval?: Function; - useColors?: boolean; - useGlobal?: boolean; - ignoreUndefined?: boolean; - writer?: Function; - completer?: Function; - replMode?: any; - breakEvalOnSigint?: any; - } - - export interface REPLServer extends readline.ReadLine { - defineCommand(keyword: string, cmd: Function | { help: string, action: Function }): void; - displayPrompt(preserveCursor?: boolean): void - } - - export function start(options: ReplOptions): REPLServer; -} - -declare module "readline" { - import * as events from "events"; - import * as stream from "stream"; - - export interface Key { - sequence?: string; - name?: string; - ctrl?: boolean; - meta?: boolean; - shift?: boolean; - } - - export interface ReadLine extends events.EventEmitter { - setPrompt(prompt: string): void; - prompt(preserveCursor?: boolean): void; - question(query: string, callback: (answer: string) => void): void; - pause(): ReadLine; - resume(): ReadLine; - close(): void; - write(data: string | Buffer, key?: Key): void; - } - - export interface Completer { - (line: string): CompleterResult; - (line: string, callback: (err: any, result: CompleterResult) => void): any; - } - - export type CompleterResult = [string[], string]; - - export interface ReadLineOptions { - input: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - completer?: Completer; - terminal?: boolean; - historySize?: number; - } - - export function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer, terminal?: boolean): ReadLine; - export function createInterface(options: ReadLineOptions): ReadLine; - - export function cursorTo(stream: NodeJS.WritableStream, x: number, y: number): void; - export function moveCursor(stream: NodeJS.WritableStream, dx: number | string, dy: number | string): void; - export function clearLine(stream: NodeJS.WritableStream, dir: number): void; - export function clearScreenDown(stream: NodeJS.WritableStream): void; -} - -declare module "vm" { - export interface Context { } - export interface ScriptOptions { - filename?: string; - lineOffset?: number; - columnOffset?: number; - displayErrors?: boolean; - timeout?: number; - cachedData?: Buffer; - produceCachedData?: boolean; - } - export interface RunningScriptOptions { - filename?: string; - lineOffset?: number; - columnOffset?: number; - displayErrors?: boolean; - timeout?: number; - } - export class Script { - constructor(code: string, options?: ScriptOptions); - runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; - runInNewContext(sandbox?: Context, options?: RunningScriptOptions): any; - runInThisContext(options?: RunningScriptOptions): any; - } - export function createContext(sandbox?: Context): Context; - export function isContext(sandbox: Context): boolean; - export function runInContext(code: string, contextifiedSandbox: Context, options?: RunningScriptOptions): any; - export function runInDebugContext(code: string): any; - export function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions): any; - export function runInThisContext(code: string, options?: RunningScriptOptions): any; -} - -declare module "child_process" { - import * as events from "events"; - import * as stream from "stream"; - - export interface ChildProcess extends events.EventEmitter { - stdin: stream.Writable; - stdout: stream.Readable; - stderr: stream.Readable; - stdio: [stream.Writable, stream.Readable, stream.Readable]; - pid: number; - kill(signal?: string): void; - send(message: any, sendHandle?: any): boolean; - connected: boolean; - disconnect(): void; - unref(): void; - ref(): void; - } - - export interface SpawnOptions { - cwd?: string; - env?: any; - stdio?: any; - detached?: boolean; - uid?: number; - gid?: number; - shell?: boolean | string; - } - export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess; - - export interface ExecOptions { - cwd?: string; - env?: any; - shell?: string; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - uid?: number; - gid?: number; - } - export interface ExecOptionsWithStringEncoding extends ExecOptions { - encoding: BufferEncoding; - } - export interface ExecOptionsWithBufferEncoding extends ExecOptions { - encoding: string; // specify `null`. - } - export function exec(command: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function exec(command: string, options: ExecOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.exec("tsc", {encoding: null as string}, (err, stdout, stderr) => {}); - export function exec(command: string, options: ExecOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function exec(command: string, options: ExecOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - - export interface ExecFileOptions { - cwd?: string; - env?: any; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - uid?: number; - gid?: number; - } - export interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { - encoding: BufferEncoding; - } - export interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { - encoding: string; // specify `null`. - } - export function execFile(file: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.execFile("file.sh", {encoding: null as string}, (err, stdout, stderr) => {}); - export function execFile(file: string, options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function execFile(file: string, options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, args?: string[], callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.execFile("file.sh", ["foo"], {encoding: null as string}, (err, stdout, stderr) => {}); - export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function execFile(file: string, args?: string[], options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - - export interface ForkOptions { - cwd?: string; - env?: any; - execPath?: string; - execArgv?: string[]; - silent?: boolean; - uid?: number; - gid?: number; - } - export function fork(modulePath: string, args?: string[], options?: ForkOptions): ChildProcess; - - export interface SpawnSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - shell?: boolean | string; - } - export interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { - encoding: BufferEncoding; - } - export interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { - encoding: string; // specify `null`. - } - export interface SpawnSyncReturns { - pid: number; - output: string[]; - stdout: T; - stderr: T; - status: number; - signal: string; - error: Error; - } - export function spawnSync(command: string): SpawnSyncReturns; - export function spawnSync(command: string, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; - export function spawnSync(command: string, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; - export function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptions): SpawnSyncReturns; - - export interface ExecSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - shell?: string; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - } - export interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { - encoding: BufferEncoding; - } - export interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { - encoding: string; // specify `null`. - } - export function execSync(command: string): Buffer; - export function execSync(command: string, options?: ExecSyncOptionsWithStringEncoding): string; - export function execSync(command: string, options?: ExecSyncOptionsWithBufferEncoding): Buffer; - export function execSync(command: string, options?: ExecSyncOptions): Buffer; - - export interface ExecFileSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - } - export interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { - encoding: BufferEncoding; - } - export interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { - encoding: string; // specify `null`. - } - export function execFileSync(command: string): Buffer; - export function execFileSync(command: string, options?: ExecFileSyncOptionsWithStringEncoding): string; - export function execFileSync(command: string, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; - export function execFileSync(command: string, options?: ExecFileSyncOptions): Buffer; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithStringEncoding): string; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptions): Buffer; -} - -declare module "url" { - export interface Url { - href?: string; - protocol?: string; - auth?: string; - hostname?: string; - port?: string; - host?: string; - pathname?: string; - search?: string; - query?: string | any; - slashes?: boolean; - hash?: string; - path?: string; - } - - export function parse(urlStr: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): Url; - export function format(url: Url): string; - export function resolve(from: string, to: string): string; -} - -declare module "dns" { - export interface MxRecord { - exchange: string, - priority: number - } - - export function lookup(domain: string, family: number, callback: (err: Error, address: string, family: number) => void): string; - export function lookup(domain: string, callback: (err: Error, address: string, family: number) => void): string; - export function resolve(domain: string, rrtype: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolve(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolve4(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolve6(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveMx(domain: string, callback: (err: Error, addresses: MxRecord[]) => void): string[]; - export function resolveTxt(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveSrv(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveNs(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveCname(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function reverse(ip: string, callback: (err: Error, domains: string[]) => void): string[]; - export function setServers(servers: string[]): void; - - //Error codes - export var NODATA: string; - export var FORMERR: string; - export var SERVFAIL: string; - export var NOTFOUND: string; - export var NOTIMP: string; - export var REFUSED: string; - export var BADQUERY: string; - export var BADNAME: string; - export var BADFAMILY: string; - export var BADRESP: string; - export var CONNREFUSED: string; - export var TIMEOUT: string; - export var EOF: string; - export var FILE: string; - export var NOMEM: string; - export var DESTRUCTION: string; - export var BADSTR: string; - export var BADFLAGS: string; - export var NONAME: string; - export var BADHINTS: string; - export var NOTINITIALIZED: string; - export var LOADIPHLPAPI: string; - export var ADDRGETNETWORKPARAMS: string; - export var CANCELLED: string; -} - -declare module "net" { - import * as stream from "stream"; - - export interface Socket extends stream.Duplex { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - connect(port: number, host?: string, connectionListener?: Function): void; - connect(path: string, connectionListener?: Function): void; - bufferSize: number; - setEncoding(encoding?: string): void; - write(data: any, encoding?: string, callback?: Function): void; - destroy(): void; - pause(): Socket; - resume(): Socket; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setKeepAlive(enable?: boolean, initialDelay?: number): void; - address(): { port: number; family: string; address: string; }; - unref(): void; - ref(): void; - - remoteAddress: string; - remoteFamily: string; - remotePort: number; - localAddress: string; - localPort: number; - bytesRead: number; - bytesWritten: number; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - - /** - * events.EventEmitter - * 1. close - * 2. connect - * 3. data - * 4. drain - * 5. end - * 6. error - * 7. lookup - * 8. timeout - */ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: (had_error: boolean) => void): this; - addListener(event: "connect", listener: () => void): this; - addListener(event: "data", listener: (data: Buffer) => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - addListener(event: "timeout", listener: () => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close", had_error: boolean): boolean; - emit(event: "connect"): boolean; - emit(event: "data", data: Buffer): boolean; - emit(event: "drain"): boolean; - emit(event: "end"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "lookup", err: Error, address: string, family: string | number, host: string): boolean; - emit(event: "timeout"): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: (had_error: boolean) => void): this; - on(event: "connect", listener: () => void): this; - on(event: "data", listener: (data: Buffer) => void): this; - on(event: "drain", listener: () => void): this; - on(event: "end", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - on(event: "timeout", listener: () => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: (had_error: boolean) => void): this; - once(event: "connect", listener: () => void): this; - once(event: "data", listener: (data: Buffer) => void): this; - once(event: "drain", listener: () => void): this; - once(event: "end", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - once(event: "timeout", listener: () => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: (had_error: boolean) => void): this; - prependListener(event: "connect", listener: () => void): this; - prependListener(event: "data", listener: (data: Buffer) => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - prependListener(event: "timeout", listener: () => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: (had_error: boolean) => void): this; - prependOnceListener(event: "connect", listener: () => void): this; - prependOnceListener(event: "data", listener: (data: Buffer) => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - prependOnceListener(event: "timeout", listener: () => void): this; - } - - export var Socket: { - new (options?: { fd?: string; type?: string; allowHalfOpen?: boolean; }): Socket; - }; - - export interface ListenOptions { - port?: number; - host?: string; - backlog?: number; - path?: string; - exclusive?: boolean; - } - - export interface Server extends Socket { - listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function): Server; - listen(port: number, hostname?: string, listeningListener?: Function): Server; - listen(port: number, backlog?: number, listeningListener?: Function): Server; - listen(port: number, listeningListener?: Function): Server; - listen(path: string, backlog?: number, listeningListener?: Function): Server; - listen(path: string, listeningListener?: Function): Server; - listen(handle: any, backlog?: number, listeningListener?: Function): Server; - listen(handle: any, listeningListener?: Function): Server; - listen(options: ListenOptions, listeningListener?: Function): Server; - close(callback?: Function): Server; - address(): { port: number; family: string; address: string; }; - getConnections(cb: (error: Error, count: number) => void): void; - ref(): Server; - unref(): Server; - maxConnections: number; - connections: number; - - /** - * events.EventEmitter - * 1. close - * 2. connection - * 3. error - * 4. listening - */ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "connection", listener: (socket: Socket) => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "listening", listener: () => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "connection", socket: Socket): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "listening"): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "connection", listener: (socket: Socket) => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "listening", listener: () => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "connection", listener: (socket: Socket) => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "listening", listener: () => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "connection", listener: (socket: Socket) => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "listening", listener: () => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "connection", listener: (socket: Socket) => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "listening", listener: () => void): this; - } - export function createServer(connectionListener?: (socket: Socket) => void): Server; - export function createServer(options?: { allowHalfOpen?: boolean; }, connectionListener?: (socket: Socket) => void): Server; - export function connect(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function connect(port: number, host?: string, connectionListener?: Function): Socket; - export function connect(path: string, connectionListener?: Function): Socket; - export function createConnection(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; - export function createConnection(path: string, connectionListener?: Function): Socket; - export function isIP(input: string): number; - export function isIPv4(input: string): boolean; - export function isIPv6(input: string): boolean; -} - -declare module "dgram" { - import * as events from "events"; - - interface RemoteInfo { - address: string; - family: string; - port: number; - } - - interface AddressInfo { - address: string; - family: string; - port: number; - } - - interface BindOptions { - port: number; - address?: string; - exclusive?: boolean; - } - - interface SocketOptions { - type: "udp4" | "udp6"; - reuseAddr?: boolean; - } - - export function createSocket(type: string, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - export function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - - export interface Socket extends events.EventEmitter { - send(msg: Buffer | String | any[], port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - send(msg: Buffer | String | any[], offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - bind(port?: number, address?: string, callback?: () => void): void; - bind(options: BindOptions, callback?: Function): void; - close(callback?: any): void; - address(): AddressInfo; - setBroadcast(flag: boolean): void; - setTTL(ttl: number): void; - setMulticastTTL(ttl: number): void; - setMulticastLoopback(flag: boolean): void; - addMembership(multicastAddress: string, multicastInterface?: string): void; - dropMembership(multicastAddress: string, multicastInterface?: string): void; - ref(): void; - unref(): void; - - /** - * events.EventEmitter - * 1. close - * 2. error - * 3. listening - * 4. message - **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "listening", listener: () => void): this; - addListener(event: "message", listener: (msg: string, rinfo: AddressInfo) => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "listening"): boolean; - emit(event: "message", msg: string, rinfo: AddressInfo): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "listening", listener: () => void): this; - on(event: "message", listener: (msg: string, rinfo: AddressInfo) => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "listening", listener: () => void): this; - once(event: "message", listener: (msg: string, rinfo: AddressInfo) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "listening", listener: () => void): this; - prependListener(event: "message", listener: (msg: string, rinfo: AddressInfo) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "listening", listener: () => void): this; - prependOnceListener(event: "message", listener: (msg: string, rinfo: AddressInfo) => void): this; - } -} - -declare module "fs" { - import * as stream from "stream"; - import * as events from "events"; - - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; - } - - interface FSWatcher extends events.EventEmitter { - close(): void; - - /** - * events.EventEmitter - * 1. change - * 2. error - */ - addListener(event: string, listener: Function): this; - addListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - addListener(event: "error", listener: (code: number, signal: string) => void): this; - - on(event: string, listener: Function): this; - on(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - on(event: "error", listener: (code: number, signal: string) => void): this; - - once(event: string, listener: Function): this; - once(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - once(event: "error", listener: (code: number, signal: string) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - prependListener(event: "error", listener: (code: number, signal: string) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - prependOnceListener(event: "error", listener: (code: number, signal: string) => void): this; - } - - export interface ReadStream extends stream.Readable { - close(): void; - destroy(): void; - - /** - * events.EventEmitter - * 1. open - * 2. close - */ - addListener(event: string, listener: Function): this; - addListener(event: "open", listener: (fd: number) => void): this; - addListener(event: "close", listener: () => void): this; - - on(event: string, listener: Function): this; - on(event: "open", listener: (fd: number) => void): this; - on(event: "close", listener: () => void): this; - - once(event: string, listener: Function): this; - once(event: "open", listener: (fd: number) => void): this; - once(event: "close", listener: () => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "open", listener: (fd: number) => void): this; - prependListener(event: "close", listener: () => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "open", listener: (fd: number) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - } - - export interface WriteStream extends stream.Writable { - close(): void; - bytesWritten: number; - path: string | Buffer; - - /** - * events.EventEmitter - * 1. open - * 2. close - */ - addListener(event: string, listener: Function): this; - addListener(event: "open", listener: (fd: number) => void): this; - addListener(event: "close", listener: () => void): this; - - on(event: string, listener: Function): this; - on(event: "open", listener: (fd: number) => void): this; - on(event: "close", listener: () => void): this; - - once(event: string, listener: Function): this; - once(event: "open", listener: (fd: number) => void): this; - once(event: "close", listener: () => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "open", listener: (fd: number) => void): this; - prependListener(event: "close", listener: () => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "open", listener: (fd: number) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - } - - /** - * Asynchronous rename. - * @param oldPath - * @param newPath - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /** - * Synchronous rename - * @param oldPath - * @param newPath - */ - export function renameSync(oldPath: string, newPath: string): void; - export function truncate(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncate(path: string | Buffer, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncateSync(path: string | Buffer, len?: number): void; - export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncateSync(fd: number, len?: number): void; - export function chown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chownSync(path: string | Buffer, uid: number, gid: number): void; - export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchownSync(fd: number, uid: number, gid: number): void; - export function lchown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchownSync(path: string | Buffer, uid: number, gid: number): void; - export function chmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmodSync(path: string | Buffer, mode: number): void; - export function chmodSync(path: string | Buffer, mode: string): void; - export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmodSync(fd: number, mode: number): void; - export function fchmodSync(fd: number, mode: string): void; - export function lchmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmodSync(path: string | Buffer, mode: number): void; - export function lchmodSync(path: string | Buffer, mode: string): void; - export function stat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function lstat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function statSync(path: string | Buffer): Stats; - export function lstatSync(path: string | Buffer): Stats; - export function fstatSync(fd: number): Stats; - export function link(srcpath: string | Buffer, dstpath: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function linkSync(srcpath: string | Buffer, dstpath: string | Buffer): void; - export function symlink(srcpath: string | Buffer, dstpath: string | Buffer, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function symlinkSync(srcpath: string | Buffer, dstpath: string | Buffer, type?: string): void; - export function readlink(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; - export function readlinkSync(path: string | Buffer): string; - export function realpath(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpath(path: string | Buffer, cache: { [path: string]: string }, callback: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpathSync(path: string | Buffer, cache?: { [path: string]: string }): string; - /* - * Asynchronous unlink - deletes the file specified in {path} - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function unlink(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous unlink - deletes the file specified in {path} - * - * @param path - */ - export function unlinkSync(path: string | Buffer): void; - /* - * Asynchronous rmdir - removes the directory specified in {path} - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function rmdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous rmdir - removes the directory specified in {path} - * - * @param path - */ - export function rmdirSync(path: string | Buffer): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdirSync(path: string | Buffer, mode?: number): void; - /* - * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdirSync(path: string | Buffer, mode?: string): void; - /* - * Asynchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. - * - * @param prefix - * @param callback The created folder path is passed as a string to the callback's second parameter. - */ - export function mkdtemp(prefix: string, callback?: (err: NodeJS.ErrnoException, folder: string) => void): void; - /* - * Synchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. - * - * @param prefix - * @returns Returns the created folder path. - */ - export function mkdtempSync(prefix: string): string; - export function readdir(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, files: string[]) => void): void; - export function readdirSync(path: string | Buffer): string[]; - export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function closeSync(fd: number): void; - export function open(path: string | Buffer, flags: string | number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; - export function open(path: string | Buffer, flags: string | number, mode: number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; - export function openSync(path: string | Buffer, flags: string | number, mode?: number): number; - export function utimes(path: string | Buffer, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimes(path: string | Buffer, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimesSync(path: string | Buffer, atime: number, mtime: number): void; - export function utimesSync(path: string | Buffer, atime: Date, mtime: Date): void; - export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimesSync(fd: number, atime: number, mtime: number): void; - export function futimesSync(fd: number, atime: Date, mtime: Date): void; - export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fsyncSync(fd: number): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, data: any, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function write(fd: number, data: any, offset: number, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function write(fd: number, data: any, offset: number, encoding: string, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; - export function writeSync(fd: number, data: any, position?: number, enconding?: string): number; - export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; - export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param encoding - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param encoding - */ - export function readFileSync(filename: string, encoding: string): string; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. - */ - export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. - */ - export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; - export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; - export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; - export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; - export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; - export function watch(filename: string, encoding: string, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; - export function watch(filename: string, options: { persistent?: boolean; recursive?: boolean; encoding?: string }, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; - export function exists(path: string | Buffer, callback?: (exists: boolean) => void): void; - export function existsSync(path: string | Buffer): boolean; - - interface Constants { - /** Constant for fs.access(). File is visible to the calling process. */ - F_OK: number; - - /** Constant for fs.access(). File can be read by the calling process. */ - R_OK: number; - - /** Constant for fs.access(). File can be written by the calling process. */ - W_OK: number; - - /** Constant for fs.access(). File can be executed by the calling process. */ - X_OK: number; - } - - export const constants: Constants; - - /** Tests a user's permissions for the file specified by path. */ - export function access(path: string | Buffer, callback: (err: NodeJS.ErrnoException) => void): void; - export function access(path: string | Buffer, mode: number, callback: (err: NodeJS.ErrnoException) => void): void; - /** Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise. */ - export function accessSync(path: string | Buffer, mode?: number): void; - export function createReadStream(path: string | Buffer, options?: { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - autoClose?: boolean; - start?: number; - end?: number; - }): ReadStream; - export function createWriteStream(path: string | Buffer, options?: { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - autoClose?: boolean; - start?: number; - }): WriteStream; - export function fdatasync(fd: number, callback: Function): void; - export function fdatasyncSync(fd: number): void; -} - -declare module "path" { - - /** - * A parsed path object generated by path.parse() or consumed by path.format(). - */ - export interface ParsedPath { - /** - * The root of the path such as '/' or 'c:\' - */ - root: string; - /** - * The full directory path such as '/home/user/dir' or 'c:\path\dir' - */ - dir: string; - /** - * The file name including extension (if any) such as 'index.html' - */ - base: string; - /** - * The file extension (if any) such as '.html' - */ - ext: string; - /** - * The file name without extension (if any) such as 'index' - */ - name: string; - } - - /** - * Normalize a string path, reducing '..' and '.' parts. - * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. - * - * @param p string path to normalize. - */ - export function normalize(p: string): string; - /** - * Join all arguments together and normalize the resulting path. - * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. - * - * @param paths string paths to join. - */ - export function join(...paths: any[]): string; - /** - * Join all arguments together and normalize the resulting path. - * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. - * - * @param paths string paths to join. - */ - export function join(...paths: string[]): string; - /** - * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. - * - * Starting from leftmost {from} paramter, resolves {to} to an absolute path. - * - * If {to} isn't already absolute, {from} arguments are prepended in right to left order, until an absolute path is found. If after using all {from} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory. - * - * @param pathSegments string paths to join. Non-string arguments are ignored. - */ - export function resolve(...pathSegments: any[]): string; - /** - * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. - * - * @param path path to test. - */ - export function isAbsolute(path: string): boolean; - /** - * Solve the relative path from {from} to {to}. - * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. - * - * @param from - * @param to - */ - export function relative(from: string, to: string): string; - /** - * Return the directory name of a path. Similar to the Unix dirname command. - * - * @param p the path to evaluate. - */ - export function dirname(p: string): string; - /** - * Return the last portion of a path. Similar to the Unix basename command. - * Often used to extract the file name from a fully qualified path. - * - * @param p the path to evaluate. - * @param ext optionally, an extension to remove from the result. - */ - export function basename(p: string, ext?: string): string; - /** - * Return the extension of the path, from the last '.' to end of string in the last portion of the path. - * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string - * - * @param p the path to evaluate. - */ - export function extname(p: string): string; - /** - * The platform-specific file separator. '\\' or '/'. - */ - export var sep: string; - /** - * The platform-specific file delimiter. ';' or ':'. - */ - export var delimiter: string; - /** - * Returns an object from a path string - the opposite of format(). - * - * @param pathString path to evaluate. - */ - export function parse(pathString: string): ParsedPath; - /** - * Returns a path string from an object - the opposite of parse(). - * - * @param pathString path to evaluate. - */ - export function format(pathObject: ParsedPath): string; - - export module posix { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } - - export module win32 { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } -} - -declare module "string_decoder" { - export interface NodeStringDecoder { - write(buffer: Buffer): string; - end(buffer?: Buffer): string; - } - export var StringDecoder: { - new (encoding?: string): NodeStringDecoder; - }; -} - -declare module "tls" { - import * as crypto from "crypto"; - import * as net from "net"; - import * as stream from "stream"; - - var CLIENT_RENEG_LIMIT: number; - var CLIENT_RENEG_WINDOW: number; - - export interface Certificate { - /** - * Country code. - */ - C: string; - /** - * Street. - */ - ST: string; - /** - * Locality. - */ - L: string; - /** - * Organization. - */ - O: string; - /** - * Organizational unit. - */ - OU: string; - /** - * Common name. - */ - CN: string; - } - - export interface CipherNameAndProtocol { - /** - * The cipher name. - */ - name: string; - /** - * SSL/TLS protocol version. - */ - version: string; - } - - export class TLSSocket extends stream.Duplex { - /** - * Returns the bound address, the address family name and port of the underlying socket as reported by - * the operating system. - * @returns {any} - An object with three properties, e.g. { port: 12346, family: 'IPv4', address: '127.0.0.1' }. - */ - address(): { port: number; family: string; address: string }; - /** - * A boolean that is true if the peer certificate was signed by one of the specified CAs, otherwise false. - */ - authorized: boolean; - /** - * The reason why the peer's certificate has not been verified. - * This property becomes available only when tlsSocket.authorized === false. - */ - authorizationError: Error; - /** - * Static boolean value, always true. - * May be used to distinguish TLS sockets from regular ones. - */ - encrypted: boolean; - /** - * Returns an object representing the cipher name and the SSL/TLS protocol version of the current connection. - * @returns {CipherNameAndProtocol} - Returns an object representing the cipher name - * and the SSL/TLS protocol version of the current connection. - */ - getCipher(): CipherNameAndProtocol; - /** - * Returns an object representing the peer's certificate. - * The returned object has some properties corresponding to the field of the certificate. - * If detailed argument is true the full chain with issuer property will be returned, - * if false only the top certificate without issuer property. - * If the peer does not provide a certificate, it returns null or an empty object. - * @param {boolean} detailed - If true; the full chain with issuer property will be returned. - * @returns {any} - An object representing the peer's certificate. - */ - getPeerCertificate(detailed?: boolean): { - subject: Certificate; - issuerInfo: Certificate; - issuer: Certificate; - raw: any; - valid_from: string; - valid_to: string; - fingerprint: string; - serialNumber: string; - }; - /** - * Could be used to speed up handshake establishment when reconnecting to the server. - * @returns {any} - ASN.1 encoded TLS session or undefined if none was negotiated. - */ - getSession(): any; - /** - * NOTE: Works only with client TLS sockets. - * Useful only for debugging, for session reuse provide session option to tls.connect(). - * @returns {any} - TLS session ticket or undefined if none was negotiated. - */ - getTLSTicket(): any; - /** - * The string representation of the local IP address. - */ - localAddress: string; - /** - * The numeric representation of the local port. - */ - localPort: string; - /** - * The string representation of the remote IP address. - * For example, '74.125.127.100' or '2001:4860:a005::68'. - */ - remoteAddress: string; - /** - * The string representation of the remote IP family. 'IPv4' or 'IPv6'. - */ - remoteFamily: string; - /** - * The numeric representation of the remote port. For example, 443. - */ - remotePort: number; - /** - * Initiate TLS renegotiation process. - * - * NOTE: Can be used to request peer's certificate after the secure connection has been established. - * ANOTHER NOTE: When running as the server, socket will be destroyed with an error after handshakeTimeout timeout. - * @param {TlsOptions} options - The options may contain the following fields: rejectUnauthorized, - * requestCert (See tls.createServer() for details). - * @param {Function} callback - callback(err) will be executed with null as err, once the renegotiation - * is successfully completed. - */ - renegotiate(options: TlsOptions, callback: (err: Error) => any): any; - /** - * Set maximum TLS fragment size (default and maximum value is: 16384, minimum is: 512). - * Smaller fragment size decreases buffering latency on the client: large fragments are buffered by - * the TLS layer until the entire fragment is received and its integrity is verified; - * large fragments can span multiple roundtrips, and their processing can be delayed due to packet - * loss or reordering. However, smaller fragments add extra TLS framing bytes and CPU overhead, - * which may decrease overall server throughput. - * @param {number} size - TLS fragment size (default and maximum value is: 16384, minimum is: 512). - * @returns {boolean} - Returns true on success, false otherwise. - */ - setMaxSendFragment(size: number): boolean; - - /** - * events.EventEmitter - * 1. OCSPResponse - * 2. secureConnect - **/ - addListener(event: string, listener: Function): this; - addListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; - addListener(event: "secureConnect", listener: () => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "OCSPResponse", response: Buffer): boolean; - emit(event: "secureConnect"): boolean; - - on(event: string, listener: Function): this; - on(event: "OCSPResponse", listener: (response: Buffer) => void): this; - on(event: "secureConnect", listener: () => void): this; - - once(event: string, listener: Function): this; - once(event: "OCSPResponse", listener: (response: Buffer) => void): this; - once(event: "secureConnect", listener: () => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; - prependListener(event: "secureConnect", listener: () => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; - prependOnceListener(event: "secureConnect", listener: () => void): this; - } - - export interface TlsOptions { - host?: string; - port?: number; - pfx?: string | Buffer[]; - key?: string | string[] | Buffer | any[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | string[] | Buffer | Buffer[]; - crl?: string | string[]; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: string[] | Buffer; - SNICallback?: (servername: string, cb: (err: Error, ctx: SecureContext) => any) => any; - ecdhCurve?: string; - dhparam?: string | Buffer; - handshakeTimeout?: number; - ALPNProtocols?: string[] | Buffer; - sessionTimeout?: number; - ticketKeys?: any; - sessionIdContext?: string; - secureProtocol?: string; - } - - export interface ConnectionOptions { - host?: string; - port?: number; - socket?: net.Socket; - pfx?: string | Buffer - key?: string | string[] | Buffer | Buffer[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | Buffer | (string | Buffer)[]; - rejectUnauthorized?: boolean; - NPNProtocols?: (string | Buffer)[]; - servername?: string; - path?: string; - ALPNProtocols?: (string | Buffer)[]; - checkServerIdentity?: (servername: string, cert: string | Buffer | (string | Buffer)[]) => any; - secureProtocol?: string; - secureContext?: Object; - session?: Buffer; - minDHSize?: number; - } - - export interface Server extends net.Server { - close(): Server; - address(): { port: number; family: string; address: string; }; - addContext(hostName: string, credentials: { - key: string; - cert: string; - ca: string; - }): void; - maxConnections: number; - connections: number; - - /** - * events.EventEmitter - * 1. tlsClientError - * 2. newSession - * 3. OCSPRequest - * 4. resumeSession - * 5. secureConnection - **/ - addListener(event: string, listener: Function): this; - addListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - addListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - addListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - addListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - addListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "tlsClientError", err: Error, tlsSocket: TLSSocket): boolean; - emit(event: "newSession", sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void): boolean; - emit(event: "OCSPRequest", certificate: Buffer, issuer: Buffer, callback: Function): boolean; - emit(event: "resumeSession", sessionId: any, callback: (err: Error, sessionData: any) => void): boolean; - emit(event: "secureConnection", tlsSocket: TLSSocket): boolean; - - on(event: string, listener: Function): this; - on(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - on(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - on(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - on(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - on(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - - once(event: string, listener: Function): this; - once(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - once(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - once(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - once(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - once(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - prependListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - prependListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - prependListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - prependListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - prependOnceListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - prependOnceListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - prependOnceListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - prependOnceListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - } - - export interface ClearTextStream extends stream.Duplex { - authorized: boolean; - authorizationError: Error; - getPeerCertificate(): any; - getCipher: { - name: string; - version: string; - }; - address: { - port: number; - family: string; - address: string; - }; - remoteAddress: string; - remotePort: number; - } - - export interface SecurePair { - encrypted: any; - cleartext: any; - } - - export interface SecureContextOptions { - pfx?: string | Buffer; - key?: string | Buffer; - passphrase?: string; - cert?: string | Buffer; - ca?: string | Buffer; - crl?: string | string[] - ciphers?: string; - honorCipherOrder?: boolean; - } - - export interface SecureContext { - context: any; - } - - export function createServer(options: TlsOptions, secureConnectionListener?: (cleartextStream: ClearTextStream) => void): Server; - export function connect(options: ConnectionOptions, secureConnectionListener?: () => void): ClearTextStream; - export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () => void): ClearTextStream; - export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): ClearTextStream; - export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; - export function createSecureContext(details: SecureContextOptions): SecureContext; -} - -declare module "crypto" { - export interface Certificate { - exportChallenge(spkac: string | Buffer): Buffer; - exportPublicKey(spkac: string | Buffer): Buffer; - verifySpkac(spkac: Buffer): boolean; - } - export var Certificate: { - new (): Certificate; - (): Certificate; - } - - export var fips: boolean; - - export interface CredentialDetails { - pfx: string; - key: string; - passphrase: string; - cert: string; - ca: string | string[]; - crl: string | string[]; - ciphers: string; - } - export interface Credentials { context?: any; } - export function createCredentials(details: CredentialDetails): Credentials; - export function createHash(algorithm: string): Hash; - export function createHmac(algorithm: string, key: string | Buffer): Hmac; - - type Utf8AsciiLatin1Encoding = "utf8" | "ascii" | "latin1"; - type HexBase64Latin1Encoding = "latin1" | "hex" | "base64"; - type Utf8AsciiBinaryEncoding = "utf8" | "ascii" | "binary"; - type HexBase64BinaryEncoding = "binary" | "base64" | "hex"; - type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid"; - - export interface Hash extends NodeJS.ReadWriteStream { - update(data: string | Buffer): Hash; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hash; - digest(): Buffer; - digest(encoding: HexBase64Latin1Encoding): string; - } - export interface Hmac extends NodeJS.ReadWriteStream { - update(data: string | Buffer): Hmac; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hmac; - digest(): Buffer; - digest(encoding: HexBase64Latin1Encoding): string; - } - export function createCipher(algorithm: string, password: any): Cipher; - export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; - export interface Cipher extends NodeJS.ReadWriteStream { - update(data: Buffer): Buffer; - update(data: string, input_encoding: Utf8AsciiBinaryEncoding): Buffer; - update(data: Buffer, input_encoding: any, output_encoding: HexBase64BinaryEncoding): string; - update(data: string, input_encoding: Utf8AsciiBinaryEncoding, output_encoding: HexBase64BinaryEncoding): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding?: boolean): void; - getAuthTag(): Buffer; - setAAD(buffer: Buffer): void; - } - export function createDecipher(algorithm: string, password: any): Decipher; - export function createDecipheriv(algorithm: string, key: any, iv: any): Decipher; - export interface Decipher extends NodeJS.ReadWriteStream { - update(data: Buffer): Buffer; - update(data: string, input_encoding: HexBase64BinaryEncoding): Buffer; - update(data: Buffer, input_encoding: any, output_encoding: Utf8AsciiBinaryEncoding): string; - update(data: string, input_encoding: HexBase64BinaryEncoding, output_encoding: Utf8AsciiBinaryEncoding): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding?: boolean): void; - setAuthTag(tag: Buffer): void; - setAAD(buffer: Buffer): void; - } - export function createSign(algorithm: string): Signer; - export interface Signer extends NodeJS.WritableStream { - update(data: string | Buffer): Signer; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Signer; - sign(private_key: string | { key: string; passphrase: string }): Buffer; - sign(private_key: string | { key: string; passphrase: string }, output_format: HexBase64Latin1Encoding): string; - } - export function createVerify(algorith: string): Verify; - export interface Verify extends NodeJS.WritableStream { - update(data: string | Buffer): Verify; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Verify; - verify(object: string, signature: Buffer): boolean; - verify(object: string, signature: string, signature_format: HexBase64Latin1Encoding): boolean; - } - export function createDiffieHellman(prime_length: number, generator?: number): DiffieHellman; - export function createDiffieHellman(prime: Buffer): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: number | Buffer): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: string, generator_encoding: HexBase64Latin1Encoding): DiffieHellman; - export interface DiffieHellman { - generateKeys(): Buffer; - generateKeys(encoding: HexBase64Latin1Encoding): string; - computeSecret(other_public_key: Buffer): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; - getPrime(): Buffer; - getPrime(encoding: HexBase64Latin1Encoding): string; - getGenerator(): Buffer; - getGenerator(encoding: HexBase64Latin1Encoding): string; - getPublicKey(): Buffer; - getPublicKey(encoding: HexBase64Latin1Encoding): string; - getPrivateKey(): Buffer; - getPrivateKey(encoding: HexBase64Latin1Encoding): string; - setPublicKey(public_key: Buffer): void; - setPublicKey(public_key: string, encoding: string): void; - setPrivateKey(private_key: Buffer): void; - setPrivateKey(private_key: string, encoding: string): void; - verifyError: number; - } - export function getDiffieHellman(group_name: string): DiffieHellman; - export function pbkdf2(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string, callback: (err: Error, derivedKey: Buffer) => any): void; - export function pbkdf2Sync(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string): Buffer; - export function randomBytes(size: number): Buffer; - export function randomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; - export function pseudoRandomBytes(size: number): Buffer; - export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; - export interface RsaPublicKey { - key: string; - padding?: number; - } - export interface RsaPrivateKey { - key: string; - passphrase?: string, - padding?: number; - } - export function publicEncrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer - export function privateDecrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer - export function privateEncrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer - export function publicDecrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer - export function getCiphers(): string[]; - export function getCurves(): string[]; - export function getHashes(): string[]; - export interface ECDH { - generateKeys(): Buffer; - generateKeys(encoding: HexBase64Latin1Encoding): string; - generateKeys(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; - computeSecret(other_public_key: Buffer): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; - getPrivateKey(): Buffer; - getPrivateKey(encoding: HexBase64Latin1Encoding): string; - getPublicKey(): Buffer; - getPublicKey(encoding: HexBase64Latin1Encoding): string; - getPublicKey(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; - setPrivateKey(private_key: Buffer): void; - setPrivateKey(private_key: string, encoding: HexBase64Latin1Encoding): void; - } - export function createECDH(curve_name: string): ECDH; - export function timingSafeEqual(a: Buffer, b: Buffer): boolean; - export var DEFAULT_ENCODING: string; -} - -declare module "stream" { - import * as events from "events"; - - class internal extends events.EventEmitter { - pipe(destination: T, options?: { end?: boolean; }): T; - } - namespace internal { - - export class Stream extends internal { } - - export interface ReadableOptions { - highWaterMark?: number; - encoding?: string; - objectMode?: boolean; - read?: (size?: number) => any; - } - - export class Readable extends events.EventEmitter implements NodeJS.ReadableStream { - readable: boolean; - constructor(opts?: ReadableOptions); - _read(size: number): void; - read(size?: number): any; - setEncoding(encoding: string): void; - pause(): Readable; - resume(): Readable; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: any): void; - wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; - push(chunk: any, encoding?: string): boolean; - - /** - * Event emitter - * The defined events on documents including: - * 1. close - * 2. data - * 3. end - * 4. readable - * 5. error - **/ - addListener(event: string, listener: Function): this; - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: Buffer | string) => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "data", chunk: Buffer | string): boolean; - emit(event: "end"): boolean; - emit(event: "readable"): boolean; - emit(event: "error", err: Error): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: Buffer | string) => void): this; - on(event: "end", listener: () => void): this; - on(event: "readable", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: Buffer | string) => void): this; - once(event: "end", listener: () => void): this; - once(event: "readable", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - - removeListener(event: string, listener: Function): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "data", listener: (chunk: Buffer | string) => void): this; - removeListener(event: "end", listener: () => void): this; - removeListener(event: "readable", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - } - - export interface WritableOptions { - highWaterMark?: number; - decodeStrings?: boolean; - objectMode?: boolean; - write?: (chunk: string | Buffer, encoding: string, callback: Function) => any; - writev?: (chunks: { chunk: string | Buffer, encoding: string }[], callback: Function) => any; - } - - export class Writable extends events.EventEmitter implements NodeJS.WritableStream { - writable: boolean; - constructor(opts?: WritableOptions); - _write(chunk: any, encoding: string, callback: Function): void; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - - /** - * Event emitter - * The defined events on documents including: - * 1. close - * 2. drain - * 3. error - * 4. finish - * 5. pipe - * 6. unpipe - **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "finish", listener: () => void): this; - addListener(event: "pipe", listener: (src: Readable) => void): this; - addListener(event: "unpipe", listener: (src: Readable) => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "drain", chunk: Buffer | string): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "finish"): boolean; - emit(event: "pipe", src: Readable): boolean; - emit(event: "unpipe", src: Readable): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "drain", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "pipe", listener: (src: Readable) => void): this; - on(event: "unpipe", listener: (src: Readable) => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "drain", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "pipe", listener: (src: Readable) => void): this; - once(event: "unpipe", listener: (src: Readable) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "pipe", listener: (src: Readable) => void): this; - prependListener(event: "unpipe", listener: (src: Readable) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; - prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; - - removeListener(event: string, listener: Function): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "drain", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "finish", listener: () => void): this; - removeListener(event: "pipe", listener: (src: Readable) => void): this; - removeListener(event: "unpipe", listener: (src: Readable) => void): this; - } - - export interface DuplexOptions extends ReadableOptions, WritableOptions { - allowHalfOpen?: boolean; - readableObjectMode?: boolean; - writableObjectMode?: boolean; - } - - // Note: Duplex extends both Readable and Writable. - export class Duplex extends Readable implements NodeJS.ReadWriteStream { - // Readable - pause(): Duplex; - resume(): Duplex; - // Writeable - writable: boolean; - constructor(opts?: DuplexOptions); - _write(chunk: any, encoding: string, callback: Function): void; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - } - - export interface TransformOptions extends ReadableOptions, WritableOptions { - transform?: (chunk: string | Buffer, encoding: string, callback: Function) => any; - flush?: (callback: Function) => any; - } - - // Note: Transform lacks the _read and _write methods of Readable/Writable. - export class Transform extends events.EventEmitter implements NodeJS.ReadWriteStream { - readable: boolean; - writable: boolean; - constructor(opts?: TransformOptions); - _transform(chunk: any, encoding: string, callback: Function): void; - _flush(callback: Function): void; - read(size?: number): any; - setEncoding(encoding: string): void; - pause(): Transform; - resume(): Transform; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: any): void; - wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; - push(chunk: any, encoding?: string): boolean; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - } - - export class PassThrough extends Transform { } - } - - export = internal; -} - -declare module "util" { - export interface InspectOptions { - showHidden?: boolean; - depth?: number; - colors?: boolean; - customInspect?: boolean; - } - - export function format(format: any, ...param: any[]): string; - export function debug(string: string): void; - export function error(...param: any[]): void; - export function puts(...param: any[]): void; - export function print(...param: any[]): void; - export function log(string: string): void; - export function inspect(object: any, showHidden?: boolean, depth?: number, color?: boolean): string; - export function inspect(object: any, options: InspectOptions): string; - export function isArray(object: any): boolean; - export function isRegExp(object: any): boolean; - export function isDate(object: any): boolean; - export function isError(object: any): boolean; - export function inherits(constructor: any, superConstructor: any): void; - export function debuglog(key: string): (msg: string, ...param: any[]) => void; - export function isBoolean(object: any): boolean; - export function isBuffer(object: any): boolean; - export function isFunction(object: any): boolean; - export function isNull(object: any): boolean; - export function isNullOrUndefined(object: any): boolean; - export function isNumber(object: any): boolean; - export function isObject(object: any): boolean; - export function isPrimitive(object: any): boolean; - export function isString(object: any): boolean; - export function isSymbol(object: any): boolean; - export function isUndefined(object: any): boolean; - export function deprecate(fn: Function, message: string): Function; -} - -declare module "assert" { - function internal(value: any, message?: string): void; - namespace internal { - export class AssertionError implements Error { - name: string; - message: string; - actual: any; - expected: any; - operator: string; - generatedMessage: boolean; - - constructor(options?: { - message?: string; actual?: any; expected?: any; - operator?: string; stackStartFunction?: Function - }); - } - - export function fail(actual: any, expected: any, message: string, operator: string): void; - export function ok(value: any, message?: string): void; - export function equal(actual: any, expected: any, message?: string): void; - export function notEqual(actual: any, expected: any, message?: string): void; - export function deepEqual(actual: any, expected: any, message?: string): void; - export function notDeepEqual(acutal: any, expected: any, message?: string): void; - export function strictEqual(actual: any, expected: any, message?: string): void; - export function notStrictEqual(actual: any, expected: any, message?: string): void; - export function deepStrictEqual(actual: any, expected: any, message?: string): void; - export function notDeepStrictEqual(actual: any, expected: any, message?: string): void; - export var throws: { - (block: Function, message?: string): void; - (block: Function, error: Function, message?: string): void; - (block: Function, error: RegExp, message?: string): void; - (block: Function, error: (err: any) => boolean, message?: string): void; - }; - - export var doesNotThrow: { - (block: Function, message?: string): void; - (block: Function, error: Function, message?: string): void; - (block: Function, error: RegExp, message?: string): void; - (block: Function, error: (err: any) => boolean, message?: string): void; - }; - - export function ifError(value: any): void; - } - - export = internal; -} - -declare module "tty" { - import * as net from "net"; - - export function isatty(fd: number): boolean; - export interface ReadStream extends net.Socket { - isRaw: boolean; - setRawMode(mode: boolean): void; - isTTY: boolean; - } - export interface WriteStream extends net.Socket { - columns: number; - rows: number; - isTTY: boolean; - } -} - -declare module "domain" { - import * as events from "events"; - - export class Domain extends events.EventEmitter implements NodeJS.Domain { - run(fn: Function): void; - add(emitter: events.EventEmitter): void; - remove(emitter: events.EventEmitter): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; - members: any[]; - enter(): void; - exit(): void; - } - - export function create(): Domain; -} - -declare module "constants" { - export var E2BIG: number; - export var EACCES: number; - export var EADDRINUSE: number; - export var EADDRNOTAVAIL: number; - export var EAFNOSUPPORT: number; - export var EAGAIN: number; - export var EALREADY: number; - export var EBADF: number; - export var EBADMSG: number; - export var EBUSY: number; - export var ECANCELED: number; - export var ECHILD: number; - export var ECONNABORTED: number; - export var ECONNREFUSED: number; - export var ECONNRESET: number; - export var EDEADLK: number; - export var EDESTADDRREQ: number; - export var EDOM: number; - export var EEXIST: number; - export var EFAULT: number; - export var EFBIG: number; - export var EHOSTUNREACH: number; - export var EIDRM: number; - export var EILSEQ: number; - export var EINPROGRESS: number; - export var EINTR: number; - export var EINVAL: number; - export var EIO: number; - export var EISCONN: number; - export var EISDIR: number; - export var ELOOP: number; - export var EMFILE: number; - export var EMLINK: number; - export var EMSGSIZE: number; - export var ENAMETOOLONG: number; - export var ENETDOWN: number; - export var ENETRESET: number; - export var ENETUNREACH: number; - export var ENFILE: number; - export var ENOBUFS: number; - export var ENODATA: number; - export var ENODEV: number; - export var ENOENT: number; - export var ENOEXEC: number; - export var ENOLCK: number; - export var ENOLINK: number; - export var ENOMEM: number; - export var ENOMSG: number; - export var ENOPROTOOPT: number; - export var ENOSPC: number; - export var ENOSR: number; - export var ENOSTR: number; - export var ENOSYS: number; - export var ENOTCONN: number; - export var ENOTDIR: number; - export var ENOTEMPTY: number; - export var ENOTSOCK: number; - export var ENOTSUP: number; - export var ENOTTY: number; - export var ENXIO: number; - export var EOPNOTSUPP: number; - export var EOVERFLOW: number; - export var EPERM: number; - export var EPIPE: number; - export var EPROTO: number; - export var EPROTONOSUPPORT: number; - export var EPROTOTYPE: number; - export var ERANGE: number; - export var EROFS: number; - export var ESPIPE: number; - export var ESRCH: number; - export var ETIME: number; - export var ETIMEDOUT: number; - export var ETXTBSY: number; - export var EWOULDBLOCK: number; - export var EXDEV: number; - export var WSAEINTR: number; - export var WSAEBADF: number; - export var WSAEACCES: number; - export var WSAEFAULT: number; - export var WSAEINVAL: number; - export var WSAEMFILE: number; - export var WSAEWOULDBLOCK: number; - export var WSAEINPROGRESS: number; - export var WSAEALREADY: number; - export var WSAENOTSOCK: number; - export var WSAEDESTADDRREQ: number; - export var WSAEMSGSIZE: number; - export var WSAEPROTOTYPE: number; - export var WSAENOPROTOOPT: number; - export var WSAEPROTONOSUPPORT: number; - export var WSAESOCKTNOSUPPORT: number; - export var WSAEOPNOTSUPP: number; - export var WSAEPFNOSUPPORT: number; - export var WSAEAFNOSUPPORT: number; - export var WSAEADDRINUSE: number; - export var WSAEADDRNOTAVAIL: number; - export var WSAENETDOWN: number; - export var WSAENETUNREACH: number; - export var WSAENETRESET: number; - export var WSAECONNABORTED: number; - export var WSAECONNRESET: number; - export var WSAENOBUFS: number; - export var WSAEISCONN: number; - export var WSAENOTCONN: number; - export var WSAESHUTDOWN: number; - export var WSAETOOMANYREFS: number; - export var WSAETIMEDOUT: number; - export var WSAECONNREFUSED: number; - export var WSAELOOP: number; - export var WSAENAMETOOLONG: number; - export var WSAEHOSTDOWN: number; - export var WSAEHOSTUNREACH: number; - export var WSAENOTEMPTY: number; - export var WSAEPROCLIM: number; - export var WSAEUSERS: number; - export var WSAEDQUOT: number; - export var WSAESTALE: number; - export var WSAEREMOTE: number; - export var WSASYSNOTREADY: number; - export var WSAVERNOTSUPPORTED: number; - export var WSANOTINITIALISED: number; - export var WSAEDISCON: number; - export var WSAENOMORE: number; - export var WSAECANCELLED: number; - export var WSAEINVALIDPROCTABLE: number; - export var WSAEINVALIDPROVIDER: number; - export var WSAEPROVIDERFAILEDINIT: number; - export var WSASYSCALLFAILURE: number; - export var WSASERVICE_NOT_FOUND: number; - export var WSATYPE_NOT_FOUND: number; - export var WSA_E_NO_MORE: number; - export var WSA_E_CANCELLED: number; - export var WSAEREFUSED: number; - export var SIGHUP: number; - export var SIGINT: number; - export var SIGILL: number; - export var SIGABRT: number; - export var SIGFPE: number; - export var SIGKILL: number; - export var SIGSEGV: number; - export var SIGTERM: number; - export var SIGBREAK: number; - export var SIGWINCH: number; - export var SSL_OP_ALL: number; - export var SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; - export var SSL_OP_CIPHER_SERVER_PREFERENCE: number; - export var SSL_OP_CISCO_ANYCONNECT: number; - export var SSL_OP_COOKIE_EXCHANGE: number; - export var SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; - export var SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; - export var SSL_OP_EPHEMERAL_RSA: number; - export var SSL_OP_LEGACY_SERVER_CONNECT: number; - export var SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; - export var SSL_OP_MICROSOFT_SESS_ID_BUG: number; - export var SSL_OP_MSIE_SSLV2_RSA_PADDING: number; - export var SSL_OP_NETSCAPE_CA_DN_BUG: number; - export var SSL_OP_NETSCAPE_CHALLENGE_BUG: number; - export var SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NO_COMPRESSION: number; - export var SSL_OP_NO_QUERY_MTU: number; - export var SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; - export var SSL_OP_NO_SSLv2: number; - export var SSL_OP_NO_SSLv3: number; - export var SSL_OP_NO_TICKET: number; - export var SSL_OP_NO_TLSv1: number; - export var SSL_OP_NO_TLSv1_1: number; - export var SSL_OP_NO_TLSv1_2: number; - export var SSL_OP_PKCS1_CHECK_1: number; - export var SSL_OP_PKCS1_CHECK_2: number; - export var SSL_OP_SINGLE_DH_USE: number; - export var SSL_OP_SINGLE_ECDH_USE: number; - export var SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; - export var SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; - export var SSL_OP_TLS_BLOCK_PADDING_BUG: number; - export var SSL_OP_TLS_D5_BUG: number; - export var SSL_OP_TLS_ROLLBACK_BUG: number; - export var ENGINE_METHOD_DSA: number; - export var ENGINE_METHOD_DH: number; - export var ENGINE_METHOD_RAND: number; - export var ENGINE_METHOD_ECDH: number; - export var ENGINE_METHOD_ECDSA: number; - export var ENGINE_METHOD_CIPHERS: number; - export var ENGINE_METHOD_DIGESTS: number; - export var ENGINE_METHOD_STORE: number; - export var ENGINE_METHOD_PKEY_METHS: number; - export var ENGINE_METHOD_PKEY_ASN1_METHS: number; - export var ENGINE_METHOD_ALL: number; - export var ENGINE_METHOD_NONE: number; - export var DH_CHECK_P_NOT_SAFE_PRIME: number; - export var DH_CHECK_P_NOT_PRIME: number; - export var DH_UNABLE_TO_CHECK_GENERATOR: number; - export var DH_NOT_SUITABLE_GENERATOR: number; - export var NPN_ENABLED: number; - export var RSA_PKCS1_PADDING: number; - export var RSA_SSLV23_PADDING: number; - export var RSA_NO_PADDING: number; - export var RSA_PKCS1_OAEP_PADDING: number; - export var RSA_X931_PADDING: number; - export var RSA_PKCS1_PSS_PADDING: number; - export var POINT_CONVERSION_COMPRESSED: number; - export var POINT_CONVERSION_UNCOMPRESSED: number; - export var POINT_CONVERSION_HYBRID: number; - export var O_RDONLY: number; - export var O_WRONLY: number; - export var O_RDWR: number; - export var S_IFMT: number; - export var S_IFREG: number; - export var S_IFDIR: number; - export var S_IFCHR: number; - export var S_IFBLK: number; - export var S_IFIFO: number; - export var S_IFSOCK: number; - export var S_IRWXU: number; - export var S_IRUSR: number; - export var S_IWUSR: number; - export var S_IXUSR: number; - export var S_IRWXG: number; - export var S_IRGRP: number; - export var S_IWGRP: number; - export var S_IXGRP: number; - export var S_IRWXO: number; - export var S_IROTH: number; - export var S_IWOTH: number; - export var S_IXOTH: number; - export var S_IFLNK: number; - export var O_CREAT: number; - export var O_EXCL: number; - export var O_NOCTTY: number; - export var O_DIRECTORY: number; - export var O_NOATIME: number; - export var O_NOFOLLOW: number; - export var O_SYNC: number; - export var O_SYMLINK: number; - export var O_DIRECT: number; - export var O_NONBLOCK: number; - export var O_TRUNC: number; - export var O_APPEND: number; - export var F_OK: number; - export var R_OK: number; - export var W_OK: number; - export var X_OK: number; - export var UV_UDP_REUSEADDR: number; - export var SIGQUIT: number; - export var SIGTRAP: number; - export var SIGIOT: number; - export var SIGBUS: number; - export var SIGUSR1: number; - export var SIGUSR2: number; - export var SIGPIPE: number; - export var SIGALRM: number; - export var SIGCHLD: number; - export var SIGSTKFLT: number; - export var SIGCONT: number; - export var SIGSTOP: number; - export var SIGTSTP: number; - export var SIGTTIN: number; - export var SIGTTOU: number; - export var SIGURG: number; - export var SIGXCPU: number; - export var SIGXFSZ: number; - export var SIGVTALRM: number; - export var SIGPROF: number; - export var SIGIO: number; - export var SIGPOLL: number; - export var SIGPWR: number; - export var SIGSYS: number; - export var SIGUNUSED: number; - export var defaultCoreCipherList: string; - export var defaultCipherList: string; - export var ENGINE_METHOD_RSA: number; - export var ALPN_ENABLED: number; -} - -declare module "process" { - export = process; -} - -declare module "v8" { - interface HeapSpaceInfo { - space_name: string; - space_size: number; - space_used_size: number; - space_available_size: number; - physical_space_size: number; - } - export function getHeapStatistics(): { total_heap_size: number, total_heap_size_executable: number, total_physical_size: number, total_avaialble_size: number, used_heap_size: number, heap_size_limit: number }; - export function getHeapSpaceStatistics(): HeapSpaceInfo[]; - export function setFlagsFromString(flags: string): void; -} - -declare module "timers" { - export function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; - export function clearTimeout(timeoutId: NodeJS.Timer): void; - export function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; - export function clearInterval(intervalId: NodeJS.Timer): void; - export function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; - export function clearImmediate(immediateId: any): void; -} - -declare module "console" { - export = console; -} diff --git a/test/_old/_workspace/node_modules/@types/node/package.json b/test/_old/_workspace/node_modules/@types/node/package.json deleted file mode 100644 index 519a2d3..0000000 --- a/test/_old/_workspace/node_modules/@types/node/package.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "_args": [ - [ - { - "raw": "@types/node", - "scope": "@types", - "escapedName": "@types%2fnode", - "name": "@types/node", - "rawSpec": "", - "spec": "latest", - "type": "tag" - }, - "/Users/christoph/Documents/Development/typescript-hero/.test" - ] - ], - "_from": "@types/node@latest", - "_id": "@types/node@6.0.45", - "_inCache": true, - "_installable": true, - "_location": "/@types/node", - "_npmOperationalInternal": { - "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/node-6.0.45.tgz_1475731505724_0.04699689312838018" - }, - "_npmUser": { - "name": "types", - "email": "ts-npm-types@microsoft.com" - }, - "_phantomChildren": {}, - "_requested": { - "raw": "@types/node", - "scope": "@types", - "escapedName": "@types%2fnode", - "name": "@types/node", - "rawSpec": "", - "spec": "latest", - "type": "tag" - }, - "_requiredBy": [ - "#USER" - ], - "_resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.45.tgz", - "_shasum": "c4842a9d653d767831e4ff495b6008cc0d579966", - "_shrinkwrap": null, - "_spec": "@types/node", - "_where": "/Users/christoph/Documents/Development/typescript-hero/.test", - "author": { - "name": "Microsoft TypeScript", - "email": "http://typescriptlang.org" - }, - "dependencies": {}, - "description": "TypeScript definitions for Node.js v6.x", - "devDependencies": {}, - "directories": {}, - "dist": { - "shasum": "c4842a9d653d767831e4ff495b6008cc0d579966", - "tarball": "https://registry.npmjs.org/@types/node/-/node-6.0.45.tgz" - }, - "license": "MIT", - "main": "", - "maintainers": [ - { - "name": "types", - "email": "ryan.cavanaugh@microsoft.com" - } - ], - "name": "@types/node", - "optionalDependencies": {}, - "peerDependencies": {}, - "readme": "ERROR: No README data found!", - "repository": { - "type": "git", - "url": "https://www.github.com/DefinitelyTyped/DefinitelyTyped.git" - }, - "scripts": {}, - "typesPublisherContentHash": "fda14253379f4199d5502086dcf3ba9815fbe03810dbb1abbe31f39c6c66ada6", - "typings": "index.d.ts", - "version": "6.0.45" -} diff --git a/test/_old/_workspace/node_modules/@types/node/types-metadata.json b/test/_old/_workspace/node_modules/@types/node/types-metadata.json deleted file mode 100644 index 6adb571..0000000 --- a/test/_old/_workspace/node_modules/@types/node/types-metadata.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "authors": "Microsoft TypeScript , DefinitelyTyped ", - "definitionFilename": "index.d.ts", - "libraryDependencies": [], - "moduleDependencies": [], - "libraryMajorVersion": "6", - "libraryMinorVersion": "0", - "libraryName": "Node.js v6.x", - "typingsPackageName": "node", - "projectName": "http://nodejs.org/", - "sourceRepoURL": "https://www.github.com/DefinitelyTyped/DefinitelyTyped", - "sourceBranch": "types-2.0", - "kind": "MultipleModules", - "globals": [ - "Buffer", - "NodeJS", - "SlowBuffer", - "__dirname", - "__filename", - "clearImmediate", - "clearInterval", - "clearTimeout", - "console", - "exports", - "global", - "module", - "process", - "require", - "setImmediate", - "setInterval", - "setTimeout" - ], - "declaredModules": [ - "buffer", - "querystring", - "events", - "http", - "cluster", - "zlib", - "os", - "https", - "punycode", - "repl", - "readline", - "vm", - "child_process", - "url", - "dns", - "net", - "dgram", - "fs", - "path", - "string_decoder", - "tls", - "crypto", - "stream", - "util", - "assert", - "tty", - "domain", - "constants", - "process", - "v8", - "timers", - "console" - ], - "files": [ - "index.d.ts" - ], - "hasPackageJson": false, - "contentHash": "fda14253379f4199d5502086dcf3ba9815fbe03810dbb1abbe31f39c6c66ada6" -} \ No newline at end of file diff --git a/test/_old/_workspace/node_modules/fancy-library/FancierLibraryClass.d.ts b/test/_old/_workspace/node_modules/fancy-library/FancierLibraryClass.d.ts deleted file mode 100644 index b599970..0000000 --- a/test/_old/_workspace/node_modules/fancy-library/FancierLibraryClass.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare class FancierLibraryClass { - public doSomethingAwesome(): void; -} diff --git a/test/_old/_workspace/node_modules/fancy-library/FancyLibraryClass.d.ts b/test/_old/_workspace/node_modules/fancy-library/FancyLibraryClass.d.ts deleted file mode 100644 index a8f9872..0000000 --- a/test/_old/_workspace/node_modules/fancy-library/FancyLibraryClass.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export declare class FancyLibraryClass { - private foobar: string; - - constructor(); - - public doSomething(): void; -} \ No newline at end of file diff --git a/test/_old/_workspace/node_modules/fancy-library/controllers/MyController.d.ts b/test/_old/_workspace/node_modules/fancy-library/controllers/MyController.d.ts deleted file mode 100644 index 6b7eac9..0000000 --- a/test/_old/_workspace/node_modules/fancy-library/controllers/MyController.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export declare class MyController { - constructor(); - public doSomeControlling(): void; -} - -export declare class MyOtherController { - constructor(); - public doSomeControlling(): void; -} diff --git a/test/_old/_workspace/node_modules/fancy-library/index.d.ts b/test/_old/_workspace/node_modules/fancy-library/index.d.ts deleted file mode 100644 index 3b01208..0000000 --- a/test/_old/_workspace/node_modules/fancy-library/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './FancyLibraryClass'; -export {MyController} from './controllers/MyController'; diff --git a/test/_old/_workspace/node_modules/some-lib/dist/SomeDeclaration.d.ts b/test/_old/_workspace/node_modules/some-lib/dist/SomeDeclaration.d.ts deleted file mode 100644 index 10fa7bd..0000000 --- a/test/_old/_workspace/node_modules/some-lib/dist/SomeDeclaration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare class NestedDistDeclaration { - constrcutor(); - public itDoesSomething(): Promise; -} \ No newline at end of file diff --git a/test/_old/_workspace/out/out.d.ts b/test/_old/_workspace/out/out.d.ts deleted file mode 100644 index ca405eb..0000000 --- a/test/_old/_workspace/out/out.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare class MyCompiledOutClass { } diff --git a/test/_old/_workspace/out/out.js b/test/_old/_workspace/out/out.js deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace/package.json b/test/_old/_workspace/package.json deleted file mode 100644 index 4880a40..0000000 --- a/test/_old/_workspace/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "workspace", - "version": "1.0.0", - "description": "", - "main": "index.js", - "dependencies": { - "fancy-library": "1.0.0", - "some-lib": "1.0.0" - }, - "devDependencies": { - "@types/node": "1.0.0" - }, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC" -} diff --git a/test/_old/_workspace/server/indices/HelperFunctions.ts b/test/_old/_workspace/server/indices/HelperFunctions.ts deleted file mode 100644 index 20c3402..0000000 --- a/test/_old/_workspace/server/indices/HelperFunctions.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function isString(str: any): str is string { - return str.constructor === String; -} - -export function isNumber(str: any): str is number { - return str.constructor === Number; -} diff --git a/test/_old/_workspace/server/indices/MyClass.ts b/test/_old/_workspace/server/indices/MyClass.ts deleted file mode 100644 index 9261ab1..0000000 --- a/test/_old/_workspace/server/indices/MyClass.ts +++ /dev/null @@ -1,17 +0,0 @@ -export class MyClass { - public doSomething(): void { } -} - -export class FancierLibraryClass { - public doSomethingAwesome(): void { } -} - -export class Class1 { } -export class Class2 { } -export class Class3 { } -export class Class4 { } -export class Class5 { } -export class Class6 { } -export class Class7 { } -export class Class8 { } -export class Class9 { } diff --git a/test/_old/_workspace/server/indices/MyReactTemplate.tsx b/test/_old/_workspace/server/indices/MyReactTemplate.tsx deleted file mode 100644 index c1fa45b..0000000 --- a/test/_old/_workspace/server/indices/MyReactTemplate.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from "react"; - -export const myComponent = (test: string) => { - return
Hello World: {test}
; -} diff --git a/test/_old/_workspace/server/indices/NotBarelExported.ts b/test/_old/_workspace/server/indices/NotBarelExported.ts deleted file mode 100644 index acbabb2..0000000 --- a/test/_old/_workspace/server/indices/NotBarelExported.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class NotBarelExported { - -} diff --git a/test/_old/_workspace/server/indices/SpecialExports.ts b/test/_old/_workspace/server/indices/SpecialExports.ts deleted file mode 100644 index 867b2af..0000000 --- a/test/_old/_workspace/server/indices/SpecialExports.ts +++ /dev/null @@ -1 +0,0 @@ -export class ExportedAsAlias { } diff --git a/test/_old/_workspace/server/indices/circularExport/circularExport1.ts b/test/_old/_workspace/server/indices/circularExport/circularExport1.ts deleted file mode 100644 index d3121d7..0000000 --- a/test/_old/_workspace/server/indices/circularExport/circularExport1.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class ExportedCircularClass1 { - -} - -export * from './circularExport2'; diff --git a/test/_old/_workspace/server/indices/circularExport/circularExport2.ts b/test/_old/_workspace/server/indices/circularExport/circularExport2.ts deleted file mode 100644 index 7c3b03a..0000000 --- a/test/_old/_workspace/server/indices/circularExport/circularExport2.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class ExportedCircularClass2 { - -} - -export * from './circularExport1'; diff --git a/test/_old/_workspace/server/indices/defaultExport/codefile.ts b/test/_old/_workspace/server/indices/defaultExport/codefile.ts deleted file mode 100644 index c30cd3d..0000000 --- a/test/_old/_workspace/server/indices/defaultExport/codefile.ts +++ /dev/null @@ -1 +0,0 @@ -import defaultImport from './lateDefaultExportedElement'; diff --git a/test/_old/_workspace/server/indices/defaultExport/lateDefaultExportedElement.ts b/test/_old/_workspace/server/indices/defaultExport/lateDefaultExportedElement.ts deleted file mode 100644 index d5c91f7..0000000 --- a/test/_old/_workspace/server/indices/defaultExport/lateDefaultExportedElement.ts +++ /dev/null @@ -1,3 +0,0 @@ -function myDefaultExportedFunction() { } - -export default myDefaultExportedFunction; diff --git a/test/_old/_workspace/server/indices/defaultExport/multiExport.ts b/test/_old/_workspace/server/indices/defaultExport/multiExport.ts deleted file mode 100644 index 8388038..0000000 --- a/test/_old/_workspace/server/indices/defaultExport/multiExport.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class MultiExportClass { - -} - -export default class { - -} diff --git a/test/_old/_workspace/server/indices/defaultExport/namelessClass.ts b/test/_old/_workspace/server/indices/defaultExport/namelessClass.ts deleted file mode 100644 index 9a9bac0..0000000 --- a/test/_old/_workspace/server/indices/defaultExport/namelessClass.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default class { - public foobar: string; -} diff --git a/test/_old/_workspace/server/indices/defaultExport/namelessFunction.ts b/test/_old/_workspace/server/indices/defaultExport/namelessFunction.ts deleted file mode 100644 index ed0b428..0000000 --- a/test/_old/_workspace/server/indices/defaultExport/namelessFunction.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function () { - return ''; -} diff --git a/test/_old/_workspace/server/indices/defaultExport/namelessVariable.ts b/test/_old/_workspace/server/indices/defaultExport/namelessVariable.ts deleted file mode 100644 index b547fee..0000000 --- a/test/_old/_workspace/server/indices/defaultExport/namelessVariable.ts +++ /dev/null @@ -1 +0,0 @@ -export default 'FOOBAR'; diff --git a/test/_old/_workspace/server/indices/index.ts b/test/_old/_workspace/server/indices/index.ts deleted file mode 100644 index ffd1122..0000000 --- a/test/_old/_workspace/server/indices/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './MyClass'; -export {ExportedAsAlias as ExportAlias} from './SpecialExports'; diff --git a/test/_old/_workspace/server/indices/proto.ts b/test/_old/_workspace/server/indices/proto.ts deleted file mode 100644 index 0a84ec4..0000000 --- a/test/_old/_workspace/server/indices/proto.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function toString(): string { - return ''; -} - -export function hasOwnProperty(): boolean { - return false; -} diff --git a/test/_old/_workspace/typings/globals/body-parser/index.d.ts b/test/_old/_workspace/typings/globals/body-parser/index.d.ts deleted file mode 100644 index 45391cb..0000000 --- a/test/_old/_workspace/typings/globals/body-parser/index.d.ts +++ /dev/null @@ -1,133 +0,0 @@ -// Generated by typings -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/6227a28e56f9c085733635ed1c9189f17e425431/body-parser/body-parser.d.ts -declare module "body-parser" { - import * as express from "express"; - - /** - * bodyParser: use individual json/urlencoded middlewares - * @deprecated - */ - - function bodyParser(options?: { - /** - * if deflated bodies will be inflated. (default: true) - */ - inflate?: boolean; - /** - * maximum request body size. (default: '100kb') - */ - limit?: any; - /** - * function to verify body content, the parsing can be aborted by throwing an error. - */ - verify?: (req: express.Request, res: express.Response, buf: Buffer, encoding: string) => void; - /** - * only parse objects and arrays. (default: true) - */ - strict?: boolean; - /** - * passed to JSON.parse(). - */ - reviver?: (key: string, value: any) => any; - /** - * parse extended syntax with the qs module. (default: true) - */ - extended?: boolean; - }): express.RequestHandler; - - namespace bodyParser { - export function json(options?: { - /** - * if deflated bodies will be inflated. (default: true) - */ - inflate?: boolean; - /** - * maximum request body size. (default: '100kb') - */ - limit?: any; - /** - * request content-type to parse, passed directly to the type-is library. (default: 'json') - */ - type?: any; - /** - * function to verify body content, the parsing can be aborted by throwing an error. - */ - verify?: (req: express.Request, res: express.Response, buf: Buffer, encoding: string) => void; - /** - * only parse objects and arrays. (default: true) - */ - strict?: boolean; - /** - * passed to JSON.parse(). - */ - reviver?: (key: string, value: any) => any; - }): express.RequestHandler; - - export function raw(options?: { - /** - * if deflated bodies will be inflated. (default: true) - */ - inflate?: boolean; - /** - * maximum request body size. (default: '100kb') - */ - limit?: any; - /** - * request content-type to parse, passed directly to the type-is library. (default: 'application/octet-stream') - */ - type?: any; - /** - * function to verify body content, the parsing can be aborted by throwing an error. - */ - verify?: (req: express.Request, res: express.Response, buf: Buffer, encoding: string) => void; - }): express.RequestHandler; - - export function text(options?: { - /** - * if deflated bodies will be inflated. (default: true) - */ - inflate?: boolean; - /** - * maximum request body size. (default: '100kb') - */ - limit?: any; - /** - * request content-type to parse, passed directly to the type-is library. (default: 'text/plain') - */ - type?: any; - /** - * function to verify body content, the parsing can be aborted by throwing an error. - */ - verify?: (req: express.Request, res: express.Response, buf: Buffer, encoding: string) => void; - /** - * the default charset to parse as, if not specified in content-type. (default: 'utf-8') - */ - defaultCharset?: string; - }): express.RequestHandler; - - export function urlencoded(options: { - /** - * if deflated bodies will be inflated. (default: true) - */ - inflate?: boolean; - /** - * maximum request body size. (default: '100kb') - */ - limit?: any; - /** - * request content-type to parse, passed directly to the type-is library. (default: 'urlencoded') - */ - type?: any; - /** - * function to verify body content, the parsing can be aborted by throwing an error. - */ - verify?: (req: express.Request, res: express.Response, buf: Buffer, encoding: string) => void; - /** - * parse extended syntax with the qs module. - */ - extended: boolean; - }): express.RequestHandler; - } - - export = bodyParser; -} \ No newline at end of file diff --git a/test/_old/_workspace_2/file1.ts b/test/_old/_workspace_2/file1.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/_old/_workspace_2/file2.ts b/test/_old/_workspace_2/file2.ts deleted file mode 100644 index 5ef1a5e..0000000 --- a/test/_old/_workspace_2/file2.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class ClassInFile2 { } - -export default class DefaultClassInFile2 { } diff --git a/test/_old/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts b/test/_old/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts deleted file mode 100644 index 25df25f..0000000 --- a/test/_old/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts +++ /dev/null @@ -1,509 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import * as sinon from 'sinon'; -import sinonChai = require('sinon-chai'); -import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; -import { ExtensionContext, Position, Range, TextDocument, window, workspace } from 'vscode'; - -import { ConfigFactory } from '../../../../src/common/factories'; -import { AddImportCodeAction, CodeAction, ImplementPolymorphElements } from '../../../../src/extension/code-actions'; -import { - MissingImplementationInClassCreator, -} from '../../../../src/extension/code-actions/MissingImplementationInClassCreator'; -import { MissingImportCreator } from '../../../../src/extension/code-actions/MissingImportCreator'; -import { CodeActionExtension } from '../../../../src/extension/extensions/CodeActionExtension'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; -import { Logger } from '../../../../src/extension/utilities/winstonLogger'; - -chai.should(); -chai.use(sinonChai); - -class SpyCodeAction implements CodeAction { - constructor(private spy: sinon.SinonSpy, private result: boolean) { } - - public async execute(): Promise { - this.spy(); - return this.result; - } -} - -describe('CodeActionExtension', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - let extension: any; - - before(async () => { - const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.logger); - const parser = Container.get(iocSymbols.typescriptParser); - const config = Container.get(iocSymbols.configuration); - const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - - const index = new DeclarationIndex(parser, rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'server/indices/MyClass.ts', - ), - join( - rootPath, - 'extension/extensions/codeActionExtension/exportedObjects.ts', - ), - join( - rootPath, - 'extension/extensions/codeActionExtension/implementInterfaceOrAbstract.ts', - ), - join( - rootPath, - 'node_modules/fancy-library/FancierLibraryClass.d.ts', - ), - ], - ); - - fakeMapper.getIndexForFile = sinon.spy(() => index); - - const creators = [ - new MissingImportCreator(fakeMapper, logger), - new MissingImplementationInClassCreator(parser, fakeMapper, logger), - ]; - - extension = new CodeActionExtension(ctx, logger, creators, fakeMapper); - }); - - describe('executeCodeAction', () => { - - const file = join( - rootPath, - 'extension/extensions/codeActionExtension/empty.ts', - ); - let document: TextDocument; - - before(async () => { - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - }); - - afterEach(async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('should call the execute method of a code action', async () => { - const spy = sinon.spy(); - await extension.executeCodeAction(new SpyCodeAction(spy, true)); - spy.should.be.calledOnce; - }); - - it('should warn the user if the result is false', async () => { - const stub = sinon.stub(window, 'showWarningMessage').callsFake(() => { - return Promise.resolve(); - }); - - try { - await extension.executeCodeAction(new SpyCodeAction(sinon.spy(), false)); - stub.should.be.calledWith('The provided code action could not complete. Please see the logs.'); - } finally { - stub.restore(); - } - }); - - }); - - describe('missingImport', () => { - - const file = join( - rootPath, - 'extension/extensions/codeActionExtension/empty.ts', - ); - let document: TextDocument; - - before(async () => { - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - }); - - afterEach(async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('should add a missing import to a document', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `Cannot find name 'Class1'.` }] }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(0).text.should.equal(`import { Class1 } from '../../../server/indices/MyClass';`); - }); - - }); - - describe('missingPolymorphicElements', () => { - const file = join(rootPath, 'extension/extensions/codeActionExtension/implementInterfaceOrAbstract.ts'); - let document: TextDocument; - let documentText: string; - - before(async () => { - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - documentText = document.getText(); - }); - - afterEach(async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new Position(0, 0), documentText); - }); - }); - - it('should resolve missing implementations of an interface to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `class 'Foobar' incorrectly implements 'CodeFixImplementInterface'.` }] }, - null, - ); - - cmds.should.have.lengthOf(1); - const action = cmds[0]; - action.title.should.equal('Implement missing elements from "CodeFixImplementInterface".'); - action.arguments[0].should.be.an.instanceof(ImplementPolymorphElements); - }); - - it('should resolve missing implementations of an abstract class to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { - message: - `non-abstract class 'Foobar' implement inherited from class 'CodeFixImplementAbstract'.`, - }, - ], - }, - null, - ); - - cmds.should.have.lengthOf(1); - const action = cmds[0]; - action.title.should.equal('Implement missing elements from "CodeFixImplementAbstract".'); - action.arguments[0].should.be.an.instanceof(ImplementPolymorphElements); - }); - - it('should resolve missing implementations of a local interface to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `class 'Foobar' incorrectly implements 'InternalInterface'.` }] }, - null, - ); - - cmds.should.have.lengthOf(1); - const action = cmds[0]; - action.title.should.equal('Implement missing elements from "InternalInterface".'); - action.arguments[0].should.be.an.instanceof(ImplementPolymorphElements); - }); - - it('should resolve missing implementations of a local abstract class to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { message: `non-abstract class 'Foobar' implement inherited from class 'InternalAbstract'.` }, - ], - }, - null, - ); - - cmds.should.have.lengthOf(1); - const action = cmds[0]; - action.title.should.equal('Implement missing elements from "InternalAbstract".'); - action.arguments[0].should.be.an.instanceof(ImplementPolymorphElements); - }); - - it('should resolve missing implementations of a generic interface to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `class 'Foobar' incorrectly implements 'GenericInterface'.` }] }, - null, - ); - - cmds.should.have.lengthOf(1); - const action = cmds[0]; - action.title.should.equal('Implement missing elements from "GenericInterface".'); - action.arguments[0].should.be.an.instanceof(ImplementPolymorphElements); - }); - - it('should resolve missing implementations of a generic abstract class to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { - message: `non-abstract class 'Foobar' ` + - `implement inherited from class 'GenericAbstractClass'.`, - }, - ], - }, - null, - ); - - cmds.should.have.lengthOf(1); - const action = cmds[0]; - action.title.should.equal('Implement missing elements from "GenericAbstractClass".'); - action.arguments[0].should.be.an.instanceof(ImplementPolymorphElements); - }); - - it('should resolve missing to a NOOP if the interface / class is not found', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `non-abstract class 'Foobar' implement inherited from class 'FOOOOBAR'.` }] }, - null, - ); - - cmds.should.have.lengthOf(1); - cmds[0].title.should.equal('Cannot find "FOOOOBAR" in the index or the actual file.'); - }); - - it('should add interface elements to a class', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { message: `class 'InterfaceImplement' incorrectly implements 'CodeFixImplementInterface'.` }, - ], - }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(3).text.should.equal(`class InterfaceImplement implements CodeFixImplementInterface {`); - document.lineAt(4).text.should.equal(` public property: number;`); - document.lineAt(6).text.should.equal(` public interfaceMethod(): string {`); - document.lineAt(7).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(8).text.should.equal(` }`); - document.lineAt(10).text.should.equal(` public interfaceMethodWithParams(p1: string, p2): number {`); - document.lineAt(11).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(12).text.should.equal(` }`); - document.lineAt(13).text.should.equal(`}`); - }); - - it('should add abstract class elements to a class', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { - message: `non-abstract class 'AbstractImplement' ` + - `implement inherited from class 'CodeFixImplementAbstract'.`, - }, - ], - }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(6).text.should.equal(`class AbstractImplement extends CodeFixImplementAbstract {`); - document.lineAt(7).text.should.equal(` public pubProperty: string;`); - document.lineAt(9).text.should.equal(` public abstractMethod(): void {`); - document.lineAt(10).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(11).text.should.equal(` }`); - document.lineAt(13).text.should.equal(` public abstractMethodWithParams(p1: string, p2): number {`); - document.lineAt(14).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(15).text.should.equal(` }`); - document.lineAt(16).text.should.equal(`}`); - }); - - it('should add local interface elements to a class', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { message: `class 'InternalInterfaceImplement' incorrectly implements 'InternalInterface'.` }, - ], - }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(19).text.should.equal(`class InternalInterfaceImplement implements InternalInterface {`); - document.lineAt(21).text.should.equal(` public method(p1: string): void {`); - document.lineAt(22).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(23).text.should.equal(` }`); - document.lineAt(25).text.should.equal(` public methodTwo() {`); - document.lineAt(26).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(27).text.should.equal(` }`); - document.lineAt(28).text.should.equal(`}`); - }); - - it('should add local abstract class elements to a class', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { - message: - `non-abstract class 'InternalAbstractImplement' ` + - `implement inherited from class 'InternalAbstract'.`, - }, - ], - }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(22).text.should.equal(`class InternalAbstractImplement extends InternalAbstract {`); - document.lineAt(24).text.should.equal(` public abstractMethod(): void {`); - document.lineAt(25).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(26).text.should.equal(` }`); - document.lineAt(27).text.should.equal(`}`); - }); - - it('should add generic interface elements with types to a class', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { - message: `class 'ImplementGenericInterface' incorrectly ` + - `implements 'GenericInterface'.`, - }, - ], - }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(34).text.should.equal( - `class ImplementGenericInterface implements GenericInterface {`, - ); - document.lineAt(36).text.should.equal(` public method(p1: string): number {`); - document.lineAt(37).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(38).text.should.equal(` }`); - document.lineAt(39).text.should.equal(`}`); - }); - - it('should add generic abstract elements with types to a class', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { - diagnostics: [ - { - message: - `non-abstract class 'ImplementGenericAbstract' ` + - `implement inherited from class 'GenericAbstractClass'.`, - }, - ], - }, - null, - ); - await extension.executeCodeAction(cmds[0].arguments[0]); - document.lineAt(37).text.should.equal( - `class ImplementGenericAbstract extends GenericAbstractClass {`, - ); - document.lineAt(39).text.should.equal(` public abstractMethod(p1: string): number {`); - document.lineAt(40).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(41).text.should.equal(` }`); - document.lineAt(43).text.should.equal(` protected protMethod(p2: number, p3: boolean) {`); - document.lineAt(44).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(45).text.should.equal(` }`); - document.lineAt(46).text.should.equal(`}`); - }); - - }); - - describe('provideCodeActions', () => { - - const file = join( - rootPath, - 'extension/extensions/codeActionExtension/empty.ts', - ); - let document: TextDocument; - - before(async () => { - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - }); - - it('should not resolve to a code action if the problem is not recognized', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `I really do have a problem mate..` }] }, - null, - ); - cmds.should.have.lengthOf(0); - }); - - describe('missing import actions', () => { - - it('should resolve a missing import problem to a code action', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `Cannot find name 'Class1'.` }] }, - null, - ); - - cmds.should.have.lengthOf(2); - const action = cmds[0]; - action.title.should.equal('Import "Class1" from "/server/indices/MyClass".'); - action.arguments[0].should.be.an.instanceof(AddImportCodeAction); - }); - - it('should resolve to a NOOP code action if the missing import is not found in the index', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `Cannot find name 'FOOOOBAR'.` }] }, - null, - ); - cmds.should.have.lengthOf(1); - cmds[0].title.should.equal('Cannot find "FOOOOBAR" in the index.'); - }); - - it('should add multiple code actions for multiple declarations found', async () => { - const cmds = await extension.provideCodeActions( - document, - new Range(new Position(0, 0), new Position(0, 0)), - { diagnostics: [{ message: `Cannot find name 'FancierLibraryClass'.` }] }, - null, - ); - - cmds.should.have.lengthOf(3); - let action = cmds[0]; - action.title.should.equal('Import "FancierLibraryClass" from "/server/indices/MyClass".'); - action.arguments[0].should.be.an.instanceof(AddImportCodeAction); - - action = cmds[1]; - action.title.should.equal('Import "FancierLibraryClass" from "fancy-library/FancierLibraryClass".'); - action.arguments[0].should.be.an.instanceof(AddImportCodeAction); - }); - - }); - - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts b/test/_old/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts deleted file mode 100644 index 0580541..0000000 --- a/test/_old/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import * as sinon from 'sinon'; -import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; -import * as vscode from 'vscode'; - -import { ConfigFactory } from '../../../../src/common/factories'; -import { VscodeExtensionConfig } from '../../../../src/extension/config/VscodeExtensionConfig'; -import { CodeCompletionExtension } from '../../../../src/extension/extensions/CodeCompletionExtension'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; -import { Logger } from '../../../../src/extension/utilities/winstonLogger'; - -const should = chai.should(); - -describe('CodeCompletionExtension', () => { - - const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - const token = new vscode.CancellationTokenSource().token; - let document: vscode.TextDocument; - let extension: CodeCompletionExtension; - - before(async () => { - const file = join( - rootPath, - 'extension/extensions/codeCompletionExtension/codeCompletionFile.ts', - ); - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - - const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.logger); - const parser = Container.get(iocSymbols.typescriptParser); - const config = Container.get(iocSymbols.configuration); - const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - - const index = new DeclarationIndex(parser, rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'extension/extensions/codeCompletionExtension/codeCompletionImports.ts', - ), - join( - rootPath, - 'server/indices/MyClass.ts', - ), - ], - ); - - fakeMapper.getIndexForFile = sinon.spy(() => index); - - extension = new CodeCompletionExtension(ctx, logger, parser, fakeMapper, config); - }); - - it('shoud resolve to null if typing in a string', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(0, 2), token); - - should.not.exist(result); - }); - - it('shoud resolve to null if after a "." (PropertyAccess)', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(1, 9), token); - - should.not.exist(result); - }); - - it('shoud resolve to null if in a comment', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(2, 4), token); - - should.not.exist(result); - }); - - it('shoud resolve to null if writing an import', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(3, 10), token); - - should.not.exist(result); - }); - - it('shoud create a completion list', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(6, 5), token); - - should.exist(result); - result![0].label.should.equal('MyClass'); - result![0].detail!.should.equal('/server/indices/MyClass'); - - should.not.exist(result![0].sortText); - }); - - it('should use custom sort order when config.completionSortMode is bottom', async () => { - const orig = (extension as any).config; - const config = new VscodeExtensionConfig(); - (config as any).codeCompletionConfig = { - completionSortMode: 'bottom', - }; - - (extension as any).config = sinon.spy(() => config); - - try { - const result = await extension.provideCompletionItems(document, new vscode.Position(6, 5), token); - should.exist(result![0].sortText); - result![0].sortText!.should.equal('9999-MyClass'); - } finally { - (extension as any).config = orig; - } - }); - - it('shoud add an insert command text edit if import would be new', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(6, 5), token); - - should.exist(result); - result![0].command!.command.should.equal('typescriptHero.codeCompletion.executeIntellisenseItem'); - result![0].command!.arguments![1].declaration.name.should.equal('MyClass'); - }); - - it('shoud add a replace command text edit if import will be updated with new specifier', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(9, 10), token); - - should.exist(result); - result![0].command!.command.should.equal('typescriptHero.codeCompletion.executeIntellisenseItem'); - result![0].command!.arguments![1].declaration.name.should.equal('ShouldBeImported'); - }); - - it('shoud resolve to no import if import is already imported', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(11, 9), token); - - should.exist(result); - result!.should.be.an('array').with.lengthOf(0); - }); - - it('shoud not suggeset an item from the own file', async () => { - const result = await extension.provideCompletionItems(document, new vscode.Position(15, 5), token); - - should.exist(result); - result!.should.be.an('array').with.lengthOf(0); - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts b/test/_old/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts deleted file mode 100644 index ce312d2..0000000 --- a/test/_old/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import { DeclarationIndex } from 'typescript-parser'; -import * as vscode from 'vscode'; - -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { ImportManager } from '../../../../src/extension/managers'; - -chai.should(); - - -describe('OrganizeImportsOnSaveExtension', () => { - - const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - let document: vscode.TextDocument; - let documentText: string; - let index: DeclarationIndex; - - before(async () => { - const file = join( - rootPath, - 'extension/extensions/organizeImportsOnSaveExtension/organizeFile.ts', - ); - document = await vscode.workspace.openTextDocument(file); - documentText = document.getText() - - await vscode.window.showTextDocument(document); - - index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); - await index.buildIndex( - [ - join( - rootPath, - 'server/indices/MyClass.ts', - ), - ], - ); - - const config = vscode.workspace.getConfiguration('typescriptHero'); - await config.update('resolver.organizeOnSave', true); - }); - - after(async () => { - const config = vscode.workspace.getConfiguration('typescriptHero'); - await config.update('resolver.organizeOnSave', false); - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new vscode.Position(0, 0), documentText); - }); - await document.save() - }); - - afterEach(async () => { - await vscode.window.activeTextEditor!.edit((builder) => { - builder.delete(new vscode.Range( - new vscode.Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - }); - }); - - it('should remove an unused import on save', async function () { - this.timeout(4000); - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class1'); - ctrl.addDeclarationImport(declaration!); - await ctrl.commit(); - - document.lineAt(0).text.should.equals( - `import { Class1 } from '../../../server/indices/MyClass';`, - ); - - await document.save(); - - document.lineAt(0).text.should.equals(''); - }); - - it('should not remove a used import on save', async function () { - this.timeout(4000); - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class1'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); - await ctrl.commit(); - - document.lineAt(0).text.should.equals( - `import { Class1, Class2 } from '../../../server/indices/MyClass';`, - ); - - await vscode.window.activeTextEditor!.edit((builder) => { - builder.insert( - new vscode.Position(1, 0), - 'let a = new Class2()', - ); - }); - - await document.save(); - - document.lineAt(0).text.should.equals( - `import { Class2 } from '../../../server/indices/MyClass';`, - ); - }); - - it('should not remove an unused import on save when disableImportRemovalOnOrganize is true', async () => { - const config = vscode.workspace.getConfiguration('typescriptHero'); - await config.update('resolver.disableImportRemovalOnOrganize', true); - - const ctrl = await ImportManager.create(document); - const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class1'); - const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'Class2'); - ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); - await ctrl.commit(); - - document.lineAt(0).text.should.equals( - `import { Class1, Class2 } from '../../../server/indices/MyClass';`, - ); - - await vscode.window.activeTextEditor!.edit((builder) => { - builder.insert( - new vscode.Position(1, 0), - 'let a = new Class2()', - ); - }); - - await document.save(); - - document.lineAt(0).text.should.equals( - `import { Class1, Class2 } from '../../../server/indices/MyClass';`, - ); - - await config.update('resolver.disableImportRemovalOnOrganize', false); - }); - -}); diff --git a/test/_old/single-workspace-tests/extension/managers/ClassManager.test.ts b/test/_old/single-workspace-tests/extension/managers/ClassManager.test.ts deleted file mode 100644 index 3abddcd..0000000 --- a/test/_old/single-workspace-tests/extension/managers/ClassManager.test.ts +++ /dev/null @@ -1,502 +0,0 @@ -import * as chai from 'chai'; -import { join } from 'path'; -import sinonChai = require('sinon-chai'); -import { - ClassDeclaration, - DeclarationIndex, - DeclarationVisibility, - MethodDeclaration, - ParameterDeclaration, -} from 'typescript-parser'; -import { Position, Range, TextDocument, window, workspace } from 'vscode'; - -import { findFiles } from '../../../../src/common/helpers'; -import { VscodeExtensionConfig } from '../../../../src/extension/config/VscodeExtensionConfig'; -import { Container } from '../../../../src/extension/IoC'; -import { iocSymbols } from '../../../../src/extension/IoCSymbols'; -import { ClassManager } from '../../../../src/extension/managers/ClassManager'; - -const should = chai.should(); -chai.use(sinonChai); - -describe('ClassManager', () => { - - const rootPath = workspace.workspaceFolders![0].uri.fsPath; - const file = join(rootPath, 'extension/managers/ClassManagerFile.ts'); - let document: TextDocument; - let documentText: string; - let index: DeclarationIndex; - let files: string[]; - - before(async () => { - const config = new VscodeExtensionConfig(workspace.workspaceFolders![0].uri); - files = await findFiles(config, workspace.workspaceFolders![0]); - - index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); - await index.buildIndex(files); - - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - documentText = document.getText(); - }); - - describe('static create()', () => { - - it('should create an instance of a class manager', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClass'); - ctrl.should.be.an.instanceof(ClassManager); - }); - - it('should select the correct class that should be managed', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClass'); - const declaration = (ctrl as any).managedClass as ClassDeclaration; - - should.exist(declaration); - declaration.name.should.equal('ManagedClass'); - declaration.should.be.an.instanceof(ClassDeclaration); - }); - - it('should throw when a class is not found', (done) => { - const fn = async () => await ClassManager.create(document, 'NonExistingClass'); - - fn() - .then(() => done(new Error('did not throw.'))) - .catch(() => done()); - }); - - }); - - describe('addProperty()', () => { - - it('should add a property to the class array', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - (ctrl as any).properties.should.have.lengthOf(3); - ctrl.addProperty('newProperty', DeclarationVisibility.Public, 'string'); - (ctrl as any).properties.should.have.lengthOf(4); - ((ctrl as any).properties.every(o => !!o.object)).should.be.true; - }); - - it('should set the isNew flag of Changeable', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.addProperty('newProperty', DeclarationVisibility.Public, 'string'); - (ctrl as any).properties[3].isNew.should.be.true; - }); - - it('should not set the other flags of Changeable', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.addProperty('newProperty', DeclarationVisibility.Public, 'string'); - (ctrl as any).properties[3].isModified.should.be.false; - (ctrl as any).properties[3].isDeleted.should.be.false; - }); - - it('should throw when adding a duplicate property', (done) => { - const fn = async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - ctrl.addProperty('foo', DeclarationVisibility.Public, 'string'); - }; - - fn() - .then(() => done(new Error('did not throw.'))) - .catch(() => done()); - }); - - }); - - describe('removeProperty()', () => { - - it('should set the deleted flag of Changeable', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - (ctrl as any).properties[0].isDeleted.should.be.false; - ctrl.removeProperty('foo'); - (ctrl as any).properties[0].isDeleted.should.be.true; - }); - - it('should not remove the element from the array when not new', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - (ctrl as any).properties.should.have.lengthOf(3); - ctrl.removeProperty('foo'); - (ctrl as any).properties.should.have.lengthOf(3); - }); - - it('should remove a new property when deleted immediatly', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - (ctrl as any).properties.should.have.lengthOf(3); - ctrl.addProperty('newProp', DeclarationVisibility.Public, 'string'); - (ctrl as any).properties.should.have.lengthOf(4); - ctrl.removeProperty('newProp'); - (ctrl as any).properties.should.have.lengthOf(3); - }); - - it('should throw when a property is not found', (done) => { - const fn = async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - ctrl.removeProperty('whatever'); - }; - - fn() - .then(() => done(new Error('did not throw.'))) - .catch(() => done()); - }); - - }); - - describe('addMethod()', () => { - - it('should add a method to the class array with a name', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - (ctrl as any).methods.should.have.lengthOf(3); - ctrl.addMethod('newMethod'); - (ctrl as any).methods.should.have.lengthOf(4); - ((ctrl as any).methods.every(o => !!o.object)).should.be.true; - }); - - it('should add a method to the class array with a declaration', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - const decl = new MethodDeclaration('newMethod', false, DeclarationVisibility.Public, 'string'); - - (ctrl as any).methods.should.have.lengthOf(3); - ctrl.addMethod(decl); - (ctrl as any).methods.should.have.lengthOf(4); - ((ctrl as any).methods.every(o => !!o.object)).should.be.true; - }); - - it('should set the isNew flag of Changeable', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.addMethod('newMethod'); - (ctrl as any).methods[3].isNew.should.be.true; - }); - - it('should throw when adding a duplicate method', (done) => { - const fn = async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - ctrl.addMethod('whatever'); - }; - - fn() - .then(() => done(new Error('did not throw.'))) - .catch(() => done()); - }); - - }); - - describe('removeMethod()', () => { - - it('should set the deleted flag of Changeable', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - (ctrl as any).methods[0].isDeleted.should.be.false; - ctrl.removeMethod('method'); - (ctrl as any).methods[0].isDeleted.should.be.true; - }); - - it('should not remove the element from the array when not new', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - (ctrl as any).methods.should.have.lengthOf(3); - ctrl.removeMethod('method'); - (ctrl as any).methods.should.have.lengthOf(3); - }); - - it('should remove a new method when deleted immediatly', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - (ctrl as any).methods.should.have.lengthOf(3); - ctrl.addMethod('randomMethod'); - (ctrl as any).methods.should.have.lengthOf(4); - ctrl.removeMethod('randomMethod'); - (ctrl as any).methods.should.have.lengthOf(3); - }); - - it('should throw when a method is not found', (done) => { - const fn = async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - ctrl.removeMethod('foobar'); - }; - - fn() - .then(() => done(new Error('did not throw.'))) - .catch(() => done()); - }); - - }); - - describe('commit()', () => { - - afterEach(async () => { - await window.activeTextEditor!.edit((builder) => { - builder.delete(new Range( - new Position(0, 0), - document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, - )); - builder.insert(new Position(0, 0), documentText); - }); - }); - - it('should not touch anything if there has nothing changed', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - await window.activeTextEditor!.edit((builder) => { - builder.replace(document.lineAt(10).rangeIncludingLineBreak, `public fooobar(): string { }`); - }); - - (await ctrl.commit()).should.be.true; - - document.lineAt(10).text.should.equal(`public fooobar(): string { }`); - }); - - it('should add a new property to a class without properties', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.addProperty('newProp', DeclarationVisibility.Private, 'myType'); - (await ctrl.commit()).should.be.true; - - document.lineAt(10).text.should.equal(` private newProp: myType;`); - }); - - it('should add a new property to a class with properties', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.addProperty('newProp', DeclarationVisibility.Public, 'taip'); - (await ctrl.commit()).should.be.true; - - document.lineAt(23).text.should.equal(` public newProp: taip;`); - }); - - it('should add a property to an empty class', async () => { - const ctrl = await ClassManager.create(document, 'EmptyClass'); - - ctrl.addProperty('newProp', DeclarationVisibility.Protected, 'number'); - (await ctrl.commit()).should.be.true; - - document.lineAt(46).text.should.equal(` protected newProp: number;`); - }); - - it('should remove a property from a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - document.lineAt(22).text.should.equal(' public foo: string;'); - ctrl.removeProperty('foo'); - (await ctrl.commit()).should.be.true; - - document.lineAt(22).text.should.equal(' protected bar: string;'); - }); - - it('should add multiple properties to a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.addProperty('newProp', DeclarationVisibility.Protected, 'number') - .addProperty('pubProp', DeclarationVisibility.Public, 'string'); - (await ctrl.commit()).should.be.true; - - document.lineAt(10).text.should.equal(` public pubProp: string;`); - document.lineAt(11).text.should.equal(` protected newProp: number;`); - }); - - it('should add multiple properties to an empty class', async () => { - const ctrl = await ClassManager.create(document, 'EmptyClass'); - - ctrl.addProperty('newProp', DeclarationVisibility.Protected, 'number') - .addProperty('pubProp', DeclarationVisibility.Public, 'string'); - (await ctrl.commit()).should.be.true; - - document.lineAt(46).text.should.equal(` public pubProp: string;`); - document.lineAt(47).text.should.equal(` protected newProp: number;`); - }); - - it('should add a property in between properties', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.addProperty('newProp', DeclarationVisibility.Protected, 'number'); - (await ctrl.commit()).should.be.true; - - document.lineAt(23).text.should.equal(` protected bar: string;`); - document.lineAt(24).text.should.equal(` protected newProp: number;`); - }); - - it('should add multiple properties in between properties', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.addProperty('protProp', DeclarationVisibility.Protected, 'number') - .addProperty('pubProp', DeclarationVisibility.Public, 'number') - .addProperty('privProp', DeclarationVisibility.Private, 'number'); - (await ctrl.commit()).should.be.true; - - document.lineAt(22).text.should.equal(` public foo: string;`); - document.lineAt(23).text.should.equal(` public pubProp: number;`); - document.lineAt(24).text.should.equal(` protected bar: string;`); - document.lineAt(25).text.should.equal(` protected protProp: number;`); - document.lineAt(26).text.should.equal(` private baz: string;`); - document.lineAt(27).text.should.equal(` private privProp: number;`); - }); - - it('should remove multiple properties from a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.removeProperty('foo').removeProperty('baz'); - (await ctrl.commit()).should.be.true; - - document.lineAt(21).text.should.equal(`class ManagedClassWithProperties {`); - document.lineAt(22).text.should.equal(` protected bar: string;`); - document.lineAt(23).text.should.equal(`}`); - }); - - it('should remove multiple properties to reach an empty class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.removeProperty('foo') - .removeProperty('bar') - .removeProperty('baz'); - (await ctrl.commit()).should.be.true; - - document.lineAt(21).text.should.equal(`class ManagedClassWithProperties {`); - document.lineAt(22).text.should.equal(`}`); - }); - - it('should remove one and add one property', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.removeProperty('foo') - .addProperty('fooReplace', DeclarationVisibility.Public, 'type'); - (await ctrl.commit()).should.be.true; - - document.lineAt(22).text.should.equal(` public fooReplace: type;`); - }); - - it('should add a method to a class with methods', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.addMethod( - 'newMethod', - DeclarationVisibility.Private, - 'type', - [ - new ParameterDeclaration('foo', undefined), - new ParameterDeclaration('bar', 'baz'), - ], - ); - (await ctrl.commit()).should.be.true; - - document.lineAt(20).text.should.equal(` private newMethod(foo, bar: baz): type {`); - document.lineAt(21).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(22).text.should.equal(` }`); - }); - - it('should add a method to a class without methods', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithProperties'); - - ctrl.addMethod( - 'newMethod', - DeclarationVisibility.Private, - 'type', - [ - new ParameterDeclaration('foo', undefined), - new ParameterDeclaration('bar', 'baz'), - ], - ); - (await ctrl.commit()).should.be.true; - - document.lineAt(26).text.should.equal(` private newMethod(foo, bar: baz): type {`); - document.lineAt(27).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(28).text.should.equal(` }`); - }); - - it('should remove a method from a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.removeMethod('whatever'); - (await ctrl.commit()).should.be.true; - - document.lineAt(12).text.should.equal(' private ohyea(foo: string, bar: number): ManagedClass {'); - }); - - it('should add multiple methods to a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.addMethod( - 'newMethod', - DeclarationVisibility.Private, - 'type', - [ - new ParameterDeclaration('foo', undefined), - new ParameterDeclaration('bar', 'baz'), - ]) - .addMethod('protMethod', DeclarationVisibility.Protected, 'type'); - (await ctrl.commit()).should.be.true; - - document.lineAt(16).text.should.equal(` protected protMethod(): type {`); - document.lineAt(17).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(18).text.should.equal(` }`); - - document.lineAt(24).text.should.equal(` private newMethod(foo, bar: baz): type {`); - document.lineAt(25).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(26).text.should.equal(` }`); - }); - - it('should remove multiple methods from a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassWithMethods'); - - ctrl.removeMethod('whatever').removeMethod('method').removeMethod('ohyea'); - (await ctrl.commit()).should.be.true; - - document.lineAt(9).text.should.equal('class ManagedClassWithMethods {'); - document.lineAt(10).text.should.equal('}'); - }); - - it('should add a property and a method to a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassFull'); - - ctrl.addProperty('newProperty', DeclarationVisibility.Public, 'FOOBAR') - .addMethod('newMethod', DeclarationVisibility.Public); - (await ctrl.commit()).should.be.true; - - document.lineAt(29).text.should.equal(' public newProperty: FOOBAR;'); - - document.lineAt(37).text.should.equal(` public newMethod() {`); - document.lineAt(38).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(39).text.should.equal(` }`); - }); - - it('should remove a property and a method from a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassFull'); - - ctrl.removeProperty('bar') - .removeMethod('whatever'); - (await ctrl.commit()).should.be.true; - - document.lineAt(29).text.should.not.equal(' protected bar: string;'); - - document.lineAt(38).text.should.not.equal(` protected whatever(): string {`); - }); - - it('should add multiple properties and methods to a class', async () => { - const ctrl = await ClassManager.create(document, 'ManagedClassFull'); - - ctrl.addProperty('newProperty', DeclarationVisibility.Public, 'FOOBAR') - .addMethod('newMethod', DeclarationVisibility.Public) - .addProperty('newProperty2', DeclarationVisibility.Public, 'FOOBAR') - .addMethod('newMethod2', DeclarationVisibility.Public); - (await ctrl.commit()).should.be.true; - - document.lineAt(29).text.should.equal(' public newProperty: FOOBAR;'); - document.lineAt(30).text.should.equal(' public newProperty2: FOOBAR;'); - - document.lineAt(38).text.should.equal(` public newMethod() {`); - document.lineAt(39).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(40).text.should.equal(` }`); - - document.lineAt(42).text.should.equal(` public newMethod2() {`); - document.lineAt(43).text.should.equal(` throw new Error('Not implemented yet.');`); - document.lineAt(44).text.should.equal(` }`); - }); - - }); - -}); diff --git a/test/etc/workspace_1/code-completion/classes.ts b/test/etc/workspace_1/code-completion/classes.ts new file mode 100644 index 0000000..f4cae18 --- /dev/null +++ b/test/etc/workspace_1/code-completion/classes.ts @@ -0,0 +1,4 @@ +export class CodeCompletionClass1 { } +export class CodeCompletionClass2 { } +export interface CodeCompletionInterface { } +export default class { } diff --git a/test/etc/workspace_1/code-completion/completions.ts b/test/etc/workspace_1/code-completion/completions.ts new file mode 100644 index 0000000..1cad62d --- /dev/null +++ b/test/etc/workspace_1/code-completion/completions.ts @@ -0,0 +1,10 @@ +CodeCompletionCla +CodeCompletionInter +classe +"CodeCompletionCla" +Foobar.CodeCompletionCla +// CodeCompletionCla +import CodeCompletionCla + +class YayClass { } +YayCl diff --git a/test/etc/workspace_1/main.ts b/test/etc/workspace_1/main.ts index b6800e5..e69de29 100644 --- a/test/etc/workspace_1/main.ts +++ b/test/etc/workspace_1/main.ts @@ -1,11 +0,0 @@ -import { Foo } from './server/indices/foobar'; -import { Loggee } from './utilities/Logger'; -import winstonLogger, { Logger } from './utilities/Logger'; - -import iocSymbols from './ioc-symbols'; - -function foo() { - console.log(winstonLogger, Logger, Loggee, iocSymbols); -} - -Foo diff --git a/test/tests/code-completion/__snapshots__/code-completion.test.ts.snap b/test/tests/code-completion/__snapshots__/code-completion.test.ts.snap new file mode 100644 index 0000000..ecaeb7c --- /dev/null +++ b/test/tests/code-completion/__snapshots__/code-completion.test.ts.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CodeCompletion provideCompletionItems() should not provide a completion for the own file 1`] = `Array []`; + +exports[`CodeCompletion provideCompletionItems() should provide a completion list 1`] = ` +Array [ + Object { + "detail": "/code-completion/classes", + "documentation": undefined, + "filterText": undefined, + "insertText": undefined, + "kind": "Class", + "label": "CodeCompletionClass1", + "sortText": undefined, + "textEdit": undefined, + }, + Object { + "detail": "/code-completion/classes", + "documentation": undefined, + "filterText": undefined, + "insertText": undefined, + "kind": "Class", + "label": "CodeCompletionClass2", + "sortText": undefined, + "textEdit": undefined, + }, +] +`; + +exports[`CodeCompletion provideCompletionItems() should provide a completion list bottom sorted 1`] = ` +Array [ + Object { + "detail": "/code-completion/classes", + "documentation": undefined, + "filterText": undefined, + "insertText": undefined, + "kind": "Class", + "label": "CodeCompletionClass1", + "sortText": "9999-CodeCompletionClass1", + "textEdit": undefined, + }, + Object { + "detail": "/code-completion/classes", + "documentation": undefined, + "filterText": undefined, + "insertText": undefined, + "kind": "Class", + "label": "CodeCompletionClass2", + "sortText": "9999-CodeCompletionClass2", + "textEdit": undefined, + }, +] +`; + +exports[`CodeCompletion provideCompletionItems() should provide a completion list for default imports 1`] = ` +Array [ + Object { + "detail": "/code-completion/classes", + "documentation": undefined, + "filterText": undefined, + "insertText": undefined, + "kind": "File", + "label": "classes", + "sortText": undefined, + "textEdit": undefined, + }, +] +`; + +exports[`CodeCompletion provideCompletionItems() should provide a completion list for interfaces 1`] = ` +Array [ + Object { + "detail": "/code-completion/classes", + "documentation": undefined, + "filterText": undefined, + "insertText": undefined, + "kind": "Interface", + "label": "CodeCompletionInterface", + "sortText": undefined, + "textEdit": undefined, + }, +] +`; diff --git a/test/tests/code-completion/code-completion.test.ts b/test/tests/code-completion/code-completion.test.ts new file mode 100644 index 0000000..38c7875 --- /dev/null +++ b/test/tests/code-completion/code-completion.test.ts @@ -0,0 +1,124 @@ +import { join } from 'path'; +import { stub } from 'sinon'; +import { CancellationTokenSource, Position, TextDocument, Uri, window, workspace } from 'vscode'; + +import { CodeCompletion } from '../../../src/code-completion'; +import Configuration from '../../../src/configuration'; +import DeclarationManager from '../../../src/declarations/declaration-manager'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { expect, waitForIndexReady } from '../setup'; + +describe('CodeCompletion', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const token = new CancellationTokenSource().token; + const file = Uri.file(join(rootPath, 'code-completion', 'completions.ts')); + let document: TextDocument; + let extension: CodeCompletion; + let declarations: DeclarationManager; + let config: Configuration; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + + declarations = ioc.get(iocSymbols.declarationManager); + config = ioc.get(iocSymbols.configuration); + extension = new CodeCompletion( + ioc.get(iocSymbols.extensionContext), + ioc.get(iocSymbols.logger), + config, + ioc.get(iocSymbols.importManager), + declarations, + ioc.get(iocSymbols.parser), + ); + + await waitForIndexReady(declarations.getIndexForFile(document.uri)!); + }); + + describe('provideCompletionItems()', () => { + + it('should provide a completion list', async () => { + const result = await extension.provideCompletionItems(document, new Position(0, 17), token); + expect(result).to.matchSnapshot(); + }); + + it('should provide a completion list for interfaces', async () => { + const result = await extension.provideCompletionItems(document, new Position(1, 17), token); + expect(result).to.matchSnapshot(); + }); + + it('should provide a completion list for default imports', async () => { + const result = await extension.provideCompletionItems(document, new Position(2, 6), token); + expect(result).to.matchSnapshot(); + }); + + it('should not provide a completion list for non ready indices', async () => { + const mock = stub(declarations, 'getIndexForFile').callsFake(() => ({ indexReady: false })); + try { + const result = await extension.provideCompletionItems(document, new Position(0, 0), token); + expect(result).to.be.null; + } finally { + mock.restore(); + } + }); + + it('should not provide a completion list for undefined workspaces', async () => { + const mock = stub(workspace, 'getWorkspaceFolder').callsFake(() => undefined); + try { + const result = await extension.provideCompletionItems(document, new Position(0, 0), token); + expect(result).to.be.null; + } finally { + mock.restore(); + } + }); + + it('should not provide a completion list for undefined indices', async () => { + const mock = stub(declarations, 'getIndexForFile').callsFake(() => undefined); + try { + const result = await extension.provideCompletionItems(document, new Position(0, 0), token); + expect(result).to.be.null; + } finally { + mock.restore(); + } + }); + + it('should not provide a completion list for typing in a string', async () => { + const result = await extension.provideCompletionItems(document, new Position(3, 18), token); + expect(result).to.be.null; + }); + + it('should not provide a completion list for typing after a "."', async () => { + const result = await extension.provideCompletionItems(document, new Position(4, 24), token); + expect(result).to.be.null; + }); + + it('should not provide a completion list for typing in a comment', async () => { + const result = await extension.provideCompletionItems(document, new Position(5, 20), token); + expect(result).to.be.null; + }); + + it('should not provide a completion list for typing in an import', async () => { + const result = await extension.provideCompletionItems(document, new Position(6, 24), token); + expect(result).to.be.null; + }); + + it('should not provide a completion for the own file', async () => { + const result = await extension.provideCompletionItems(document, new Position(9, 5), token); + expect(result).to.matchSnapshot(); + }); + + it('should provide a completion list bottom sorted', async () => { + const mock = stub(config.codeCompletion, 'completionSortMode').callsFake(() => 'bottom'); + try { + const result = await extension.provideCompletionItems(document, new Position(0, 17), token); + expect(result).to.matchSnapshot(); + } finally { + mock.restore(); + } + }); + + }); + +}); diff --git a/test/tests/setup.ts b/test/tests/setup.ts index 7e1c3b3..e39e4d6 100644 --- a/test/tests/setup.ts +++ b/test/tests/setup.ts @@ -2,6 +2,7 @@ import { expect as chaiExpect, use } from 'chai'; import { EOL } from 'os'; import { join, parse } from 'path'; import sinonChai = require('sinon-chai'); +import { DeclarationIndex } from 'typescript-parser'; import { TextDocument } from 'vscode'; const chaiJestSnapshot = require('chai-jest-snapshot'); @@ -42,3 +43,21 @@ export function getDocumentText(document: TextDocument, lineFrom: number, lineTo } return lines.join(EOL) + EOL; } + +export function waitForIndexReady(index: DeclarationIndex): Promise { + return new Promise((resolve) => { + if (index.indexReady) { + resolve(); + } + + const interval = setInterval( + () => { + if (index.indexReady) { + clearInterval(interval); + resolve(); + } + }, + 50, + ); + }); +} diff --git a/tsconfig.json b/tsconfig.json index d7d2d63..b432373 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,6 @@ "./test/**/*" ], "exclude": [ - "./src/_old", - "./test/_old", "./test/etc" ] }