From 793e1e8d2b820e550c1b561f8a28c8b2365afbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 10 Oct 2017 11:19:19 +0200 Subject: [PATCH 01/40] adding mapper --- package.json | 2 +- src/extension/IoC.ts | 4 ++++ src/extension/IoCSymbols.ts | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7df45c6..3f1a285 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "version": "0.0.0-development", "publisher": "rbbit", "engines": { - "vscode": "^1.13.0", + "vscode": "^1.17.0", "node": ">=8.0.0", "npm": ">=5.3.0" }, diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 095da96..8e819a6 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -4,6 +4,7 @@ import { DeclarationIndex, TypescriptCodeGenerator, TypescriptParser } from 'typ import { ExtensionContext, workspace } from 'vscode'; import { ExtensionConfig } from '../common/config'; +import { DeclarationIndexMapper } from '../common/helpers/DeclarationIndexMapper'; import { Logger } from '../common/utilities'; import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; import { BaseExtension } from './extensions/BaseExtension'; @@ -19,6 +20,7 @@ import { VscodeExtensionConfig } from './VscodeExtensionConfig'; const container = new IoCContainer(); +// DEPRECATED container.bind(iocSymbols.rootPath).toConstantValue(workspace.rootPath || ''); container.bind(TypeScriptHero).to(TypeScriptHero).inSingletonScope(); container.bind(iocSymbols.configuration).to(VscodeExtensionConfig).inSingletonScope(); @@ -30,6 +32,8 @@ container }) .inSingletonScope(); +container.bind(iocSymbols.declarationIndexMapper).to(DeclarationIndexMapper).inSingletonScope(); + container .bind(iocSymbols.typescriptParser) .toDynamicValue(() => { diff --git a/src/extension/IoCSymbols.ts b/src/extension/IoCSymbols.ts index 193dcec..a193354 100644 --- a/src/extension/IoCSymbols.ts +++ b/src/extension/IoCSymbols.ts @@ -9,6 +9,7 @@ export const iocSymbols = { generatorFactory: Symbol('generatorFactory'), codeActionCreators: Symbol('codeActionCreators'), declarationIndex: Symbol('declarationIndex'), + declarationIndexMapper: Symbol('declarationIndexMapper'), typescriptParser: Symbol('typescriptParser'), rootPath: Symbol('rootPath'), }; From 4e63e1e0855df6b67aace6037d3b644d2dc8dc62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 10 Oct 2017 15:46:26 +0200 Subject: [PATCH 02/40] move helpers, move mapper --- config/tsconfig.base.json | 3 +- src/common/helpers/DeclarationIndexHelpers.ts | 82 ++++++++++++++++++- src/extension/IoC.ts | 5 +- 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/config/tsconfig.base.json b/config/tsconfig.base.json index efe393c..8940570 100644 --- a/config/tsconfig.base.json +++ b/config/tsconfig.base.json @@ -4,7 +4,8 @@ "target": "es6", "outDir": "../out", "lib": [ - "es6" + "es6", + "es2017" ], "rootDir": "..", "emitDecoratorMetadata": true, diff --git a/src/common/helpers/DeclarationIndexHelpers.ts b/src/common/helpers/DeclarationIndexHelpers.ts index f131565..bc159e2 100644 --- a/src/common/helpers/DeclarationIndexHelpers.ts +++ b/src/common/helpers/DeclarationIndexHelpers.ts @@ -1,5 +1,9 @@ +import { existsSync } from 'fs'; import { join, normalize, parse, relative } from 'path'; import { DeclarationInfo, ExternalModuleImport, Import, NamedImport, NamespaceImport } from 'typescript-parser'; +import { RelativePattern, Uri, workspace, WorkspaceFolder } from 'vscode'; + +import { ExtensionConfig } from '../config'; /** * Calculates a list of declarationInfos filtered by the already imported ones in the given document. @@ -32,7 +36,7 @@ export function getDeclarationsFilteredByImports( // declarations = declarations // .filter(o => (!(o.declaration instanceof DefaultDeclaration) || importedLib !== o.from)); // } - // } + // } // TODO } else if (tsImport instanceof NamespaceImport || tsImport instanceof ExternalModuleImport) { declarations = declarations.filter(o => o.from !== tsImport.libraryName); } @@ -88,3 +92,79 @@ export function getRelativeLibraryName(library: string, actualFilePath: string, } return relativePath.replace(/\\/g, '/'); } + +/** + * TODO + * + * @export + * @param {ExtensionConfig} config + * @param {WorkspaceFolder} workspaceFolder + * @returns {Promise} + */ +export async function findFiles(config: ExtensionConfig, workspaceFolder: WorkspaceFolder): Promise { + const searches: PromiseLike[] = [ + workspace.findFiles( + new RelativePattern(workspaceFolder, `{${config.resolver.resolverModeFileGlobs.join(',')}}`), + new RelativePattern(workspaceFolder, '{**/node_modules/**,**/typings/**}'), + ), + ]; + + // TODO: check the package json and index javascript file in node_modules (?) + + let globs: string[] = []; + let ignores = ['**/typings/**']; + const excludePatterns = config.resolver.ignorePatterns; // convert to resource config + const rootPath = workspaceFolder.uri.path; + + if (rootPath && existsSync(join(rootPath, 'package.json'))) { + const packageJson = require(join(rootPath, 'package.json')); + if (packageJson['dependencies']) { + globs = globs.concat( + Object.keys(packageJson['dependencies']).filter(o => excludePatterns.indexOf(o) < 0) + .map(o => `**/node_modules/${o}/**/*.d.ts`), + ); + ignores = ignores.concat( + Object.keys(packageJson['dependencies']).filter(o => excludePatterns.indexOf(o) < 0) + .map(o => `**/node_modules/${o}/node_modules/**`), + ); + } + if (packageJson['devDependencies']) { + globs = globs.concat( + Object.keys(packageJson['devDependencies']).filter(o => excludePatterns.indexOf(o) < 0) + .map(o => `**/node_modules/${o}/**/*.d.ts`), + ); + ignores = ignores.concat( + Object.keys(packageJson['devDependencies']).filter(o => excludePatterns.indexOf(o) < 0) + .map(o => `**/node_modules/${o}/node_modules/**`), + ); + } + } else { + globs.push('**/node_modules/**/*.d.ts'); + } + + searches.push( + workspace.findFiles( + new RelativePattern(workspaceFolder, `{${globs.join(',')}}`), + new RelativePattern(workspaceFolder, `{${ignores.join(',')}}`), + ), + ); + + searches.push( + workspace.findFiles( + new RelativePattern(workspaceFolder, '**/typings/**/*.d.ts'), + new RelativePattern(workspaceFolder, '**/node_modules/**'), + ), + ); + + let uris = await Promise.all(searches); + + uris = uris.map((o, idx) => idx === 0 ? + o.filter( + f => f.fsPath + .replace(rootPath || '', '') + .split(/\\|\//) + .every(p => excludePatterns.indexOf(p) < 0)) : + o, + ); + return uris.reduce((all, cur) => all.concat(cur), []).map(o => o.fsPath); +} diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 8e819a6..abbbdb4 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -4,7 +4,6 @@ import { DeclarationIndex, TypescriptCodeGenerator, TypescriptParser } from 'typ import { ExtensionContext, workspace } from 'vscode'; import { ExtensionConfig } from '../common/config'; -import { DeclarationIndexMapper } from '../common/helpers/DeclarationIndexMapper'; import { Logger } from '../common/utilities'; import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; import { BaseExtension } from './extensions/BaseExtension'; @@ -24,6 +23,7 @@ const container = new IoCContainer(); container.bind(iocSymbols.rootPath).toConstantValue(workspace.rootPath || ''); container.bind(TypeScriptHero).to(TypeScriptHero).inSingletonScope(); container.bind(iocSymbols.configuration).to(VscodeExtensionConfig).inSingletonScope(); +// DEPRECATED container .bind(iocSymbols.declarationIndex) .toDynamicValue((context: interfaces.Context) => { @@ -32,8 +32,6 @@ container }) .inSingletonScope(); -container.bind(iocSymbols.declarationIndexMapper).to(DeclarationIndexMapper).inSingletonScope(); - container .bind(iocSymbols.typescriptParser) .toDynamicValue(() => { @@ -56,6 +54,7 @@ container.bind(iocSymbols.extensions).to(CodeCompletionExtension) container.bind(iocSymbols.extensions).to(DocumentSymbolStructureExtension).inSingletonScope(); container.bind(iocSymbols.extensions).to(CodeActionExtension).inSingletonScope(); container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExtension).inSingletonScope(); +container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExtension).inSingletonScope(); // Logging container From 753615c94ab609e785d3c9a774b7b2dc3ca1bf67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 10 Oct 2017 15:46:33 +0200 Subject: [PATCH 03/40] 1st ver of mapper --- .../DeclarationIndexMapperExtension.ts | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/extension/extensions/DeclarationIndexMapperExtension.ts diff --git a/src/extension/extensions/DeclarationIndexMapperExtension.ts b/src/extension/extensions/DeclarationIndexMapperExtension.ts new file mode 100644 index 0000000..0d66fb6 --- /dev/null +++ b/src/extension/extensions/DeclarationIndexMapperExtension.ts @@ -0,0 +1,110 @@ +import { inject, injectable } from 'inversify'; +import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; +import { + ExtensionContext, + FileSystemWatcher, + RelativePattern, + workspace, + WorkspaceFolder, + WorkspaceFoldersChangeEvent, +} from 'vscode'; + +import { ExtensionConfig } from '../../common/config'; +import { findFiles } from '../../common/helpers'; +import { Logger, LoggerFactory } from '../../common/utilities'; +import { iocSymbols } from '../../extension/IoCSymbols'; +import { BaseExtension } from './BaseExtension'; + +// const parser = context.container.get(iocSymbols.typescriptParser); +// return new DeclarationIndex(parser, context.container.get(iocSymbols.rootPath)); + +/* +1. pro rootpath 1 index +2. build index +3. add workspace changed thingy pro index +spöter: +4. luege öbs im gliche folder isch zum imports etc resolve +*/ + +interface WorkspaceIndex { + index: DeclarationIndex; + folder: WorkspaceFolder; + watcher: FileSystemWatcher; +} + +@injectable() +export class DeclarationIndexMapperExtension extends BaseExtension { + protected context: ExtensionContext; + private logger: Logger; + private indizes: { [uri: string]: WorkspaceIndex } = {}; + + constructor( + @inject(iocSymbols.extensionContext) context: ExtensionContext, + @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, + @inject(iocSymbols.configuration) private config: ExtensionConfig, + ) { + super(context); + this.logger = loggerFactory('DeclarationIndexMapper'); + } + + public initialize(): void { + this.context.subscriptions.push(workspace.onDidChangeWorkspaceFolders(e => this.workspaceChanged(e))); + this.logger.info( + `Fired up index mapper, got ${(workspace.workspaceFolders || []).length} workspaces.`, + workspace.workspaceFolders, + ); + for (const folder of (workspace.workspaceFolders || []).filter(workspace => workspace.uri.scheme === 'file')) { + this.initializeIndex(folder); + } + this.logger.info('Initialized'); + } + + public dispose(): void { + for (const index of Object.values(this.indizes)) { + index.watcher.dispose(); + index.index.reset(); + } + this.indizes = {}; + } + + public getIndexForFile(fileUri: string): DeclarationIndex { + return '' as any; + } + + private workspaceChanged(event: WorkspaceFoldersChangeEvent): void { + this.logger.info('Workspaces changed.', event); + for (const add of event.added) { + if (this.indizes[add.uri.path]) { + this.logger.warning(`The workspace with the path ${add.uri.path} already exists. Skipping.`); + continue; + } + this.initializeIndex(add); + } + + for (const remove of event.removed) { + this.indizes[remove.uri.path].index.reset(); + this.indizes[remove.uri.path].watcher.dispose(); + delete this.indizes[remove.uri.path]; + } + } + + private async initializeIndex(folder: WorkspaceFolder): Promise { + const index = new DeclarationIndex(this.parser, folder.uri.path); + const files = await findFiles(this.config, folder); + const watcher = workspace.createFileSystemWatcher( + new RelativePattern( + folder, + `{${this.config.resolver.resolverModeFileGlobs.join(',')},**/package.json,**/typings.json}`, + ), + ); + // watcher.onDidChange() + await index.buildIndex(files); + this.indizes[folder.uri.path] = { + index, + folder, + watcher, + }; + this.logger.info(`Finished building index for workspace "${folder.name}".`); + } +} From 7bce399c91eaffb14c383722d43e03c1d2048f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 11 Oct 2017 11:07:44 +0200 Subject: [PATCH 04/40] adding declaration index --- .../DeclarationIndexMapperExtension.ts | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/extension/extensions/DeclarationIndexMapperExtension.ts b/src/extension/extensions/DeclarationIndexMapperExtension.ts index 0d66fb6..3b0af4f 100644 --- a/src/extension/extensions/DeclarationIndexMapperExtension.ts +++ b/src/extension/extensions/DeclarationIndexMapperExtension.ts @@ -1,9 +1,10 @@ import { inject, injectable } from 'inversify'; -import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; +import { DeclarationIndex, FileChanges, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, FileSystemWatcher, RelativePattern, + Uri, workspace, WorkspaceFolder, WorkspaceFoldersChangeEvent, @@ -68,8 +69,13 @@ export class DeclarationIndexMapperExtension extends BaseExtension { this.indizes = {}; } - public getIndexForFile(fileUri: string): DeclarationIndex { - return '' as any; + public getIndexForFile(fileUri: Uri): DeclarationIndex | undefined { + const workspaceFolder = workspace.getWorkspaceFolder(fileUri); + if (!workspaceFolder || !this.indizes[workspaceFolder.uri.path]) { + return; + } + + return this.indizes[workspaceFolder.uri.path].index; } private workspaceChanged(event: WorkspaceFoldersChangeEvent): void { @@ -98,7 +104,40 @@ export class DeclarationIndexMapperExtension extends BaseExtension { `{${this.config.resolver.resolverModeFileGlobs.join(',')},**/package.json,**/typings.json}`, ), ); - // watcher.onDidChange() + + 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) { + this.logger.info(`Refreshing index for workspace ${folder.name}.`); + await index.reindexForChanges(events); + this.logger.info(`Finished indexing 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)); + await index.buildIndex(files); this.indizes[folder.uri.path] = { index, From bb4a4e64c826f20a1bf348b7122af26bf4815312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 11 Oct 2017 13:29:38 +0200 Subject: [PATCH 05/40] moved Declaration Index --- src/extension/IoC.ts | 4 +- ...Extension.ts => DeclarationIndexMapper.ts} | 15 +- .../extensions/ImportResolveExtension.ts | 212 +++++------------- 3 files changed, 70 insertions(+), 161 deletions(-) rename src/extension/extensions/{DeclarationIndexMapperExtension.ts => DeclarationIndexMapper.ts} (92%) diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index abbbdb4..19bdf23 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -9,6 +9,7 @@ import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCr import { BaseExtension } from './extensions/BaseExtension'; import { CodeActionExtension } from './extensions/CodeActionExtension'; import { CodeCompletionExtension } from './extensions/CodeCompletionExtension'; +import { DeclarationIndexMapper } from './extensions/DeclarationIndexMapper'; import { DocumentSymbolStructureExtension } from './extensions/DocumentSymbolStructureExtension'; import { ImportResolveExtension } from './extensions/ImportResolveExtension'; import { OrganizeImportsOnSaveExtension } from './extensions/OrganizeImportsOnSaveExtension'; @@ -32,6 +33,8 @@ container }) .inSingletonScope(); +container.bind(iocSymbols.declarationIndexMapper).to(DeclarationIndexMapper).inSingletonScope(); + container .bind(iocSymbols.typescriptParser) .toDynamicValue(() => { @@ -54,7 +57,6 @@ container.bind(iocSymbols.extensions).to(CodeCompletionExtension) container.bind(iocSymbols.extensions).to(DocumentSymbolStructureExtension).inSingletonScope(); container.bind(iocSymbols.extensions).to(CodeActionExtension).inSingletonScope(); container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExtension).inSingletonScope(); -container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExtension).inSingletonScope(); // Logging container diff --git a/src/extension/extensions/DeclarationIndexMapperExtension.ts b/src/extension/extensions/DeclarationIndexMapper.ts similarity index 92% rename from src/extension/extensions/DeclarationIndexMapperExtension.ts rename to src/extension/extensions/DeclarationIndexMapper.ts index 3b0af4f..6e572a7 100644 --- a/src/extension/extensions/DeclarationIndexMapperExtension.ts +++ b/src/extension/extensions/DeclarationIndexMapper.ts @@ -1,4 +1,4 @@ -import { inject, injectable } from 'inversify'; +import { inject, injectable, postConstruct } from 'inversify'; import { DeclarationIndex, FileChanges, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, @@ -14,7 +14,6 @@ import { ExtensionConfig } from '../../common/config'; import { findFiles } from '../../common/helpers'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../../extension/IoCSymbols'; -import { BaseExtension } from './BaseExtension'; // const parser = context.container.get(iocSymbols.typescriptParser); // return new DeclarationIndex(parser, context.container.get(iocSymbols.rootPath)); @@ -34,21 +33,20 @@ interface WorkspaceIndex { } @injectable() -export class DeclarationIndexMapperExtension extends BaseExtension { - protected context: ExtensionContext; +export class DeclarationIndexMapper { private logger: Logger; private indizes: { [uri: string]: WorkspaceIndex } = {}; constructor( - @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.extensionContext) private context: ExtensionContext, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.configuration) private config: ExtensionConfig, ) { - super(context); this.logger = loggerFactory('DeclarationIndexMapper'); } + @postConstruct() public initialize(): void { this.context.subscriptions.push(workspace.onDidChangeWorkspaceFolders(e => this.workspaceChanged(e))); this.logger.info( @@ -61,12 +59,15 @@ export class DeclarationIndexMapperExtension extends BaseExtension { this.logger.info('Initialized'); } - public dispose(): void { + public rebuildAll(): void { 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); + } } public getIndexForFile(fileUri: Uri): DeclarationIndex | undefined { diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index abff4db..87e2b04 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -1,18 +1,8 @@ import { existsSync } from 'fs'; import { inject, injectable } from 'inversify'; import { join } from 'path'; -import { DeclarationIndex, DeclarationInfo, FileChanges, TypescriptParser } from 'typescript-parser'; -import { - commands, - ExtensionContext, - FileSystemWatcher, - ProgressLocation, - StatusBarAlignment, - StatusBarItem, - Uri, - window, - workspace, -} from 'vscode'; +import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; +import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, Uri, window, workspace } from 'vscode'; import { ExtensionConfig } from '../../common/config'; import { ResolverMode } from '../../common/enums'; @@ -22,13 +12,14 @@ import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers'; import { BaseExtension } from './BaseExtension'; +import { DeclarationIndexMapper } from './DeclarationIndexMapper'; type DeclarationsForImportOptions = { cursorSymbol: string, documentSource: string, documentPath: string }; type MissingDeclarationsForFileOptions = { documentSource: string, documentPath: string }; /** * Compares the ignorepatterns (if they have the same elements ignored). - * + * * @param {string[]} local * @param {string[]} config * @returns {boolean} @@ -52,7 +43,7 @@ function compareIgnorePatterns(local: string[], config: string[]): boolean { /** * Search for typescript / typescript react files in the workspace and return the path to them. * This is needed for the initial load of the index. - * + * * @export * @param {ExtensionConfig} config * @returns {Promise} @@ -118,13 +109,13 @@ export async function findFiles(config: ExtensionConfig, rootPath: string): Prom } const resolverOk = 'TSH Resolver $(check)'; -const resolverSyncing = 'TSH Resolver $(sync)'; -const resolverErr = 'TSH Resolver $(flame)'; +// 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} @@ -134,7 +125,6 @@ export class ImportResolveExtension extends BaseExtension { private logger: Logger; private statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 4); private ignorePatterns: string[]; - private fileWatcher: FileSystemWatcher; private actualMode: ResolverMode; constructor( @@ -142,7 +132,7 @@ export class ImportResolveExtension extends BaseExtension { @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, @inject(iocSymbols.configuration) private config: ExtensionConfig, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.declarationIndex) private index: DeclarationIndex, + @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, @inject(iocSymbols.rootPath) private rootPath: string, ) { super(context); @@ -151,19 +141,14 @@ export class ImportResolveExtension extends BaseExtension { /** * Initialized the extension. Registers the commands and other disposables to the context. - * + * * @memberof ImportResolveExtension */ public initialize(): void { this.actualMode = this.config.resolver.resolverMode; this.ignorePatterns = this.config.resolver.ignorePatterns; - this.fileWatcher = workspace.createFileSystemWatcher( - `{${this.config.resolver.resolverModeFileGlobs.join(',')},**/package.json,**/typings.json}`, - ); - this.context.subscriptions.push(this.statusBarItem); - this.context.subscriptions.push(this.fileWatcher); this.statusBarItem.text = resolverOk; this.statusBarItem.tooltip = @@ -188,137 +173,43 @@ export class ImportResolveExtension extends BaseExtension { build = true; } if (build) { - this.buildIndex(); + this.indices.rebuildAll(); } })); - 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( - () => { - if (events) { - this.rebuildForFileChanges(events); - events = undefined; - } - }, - 500, - ); - }; - - this.fileWatcher.onDidCreate(uri => fileWatcherEvent('created', uri)); - this.fileWatcher.onDidChange(uri => fileWatcherEvent('updated', uri)); - this.fileWatcher.onDidDelete(uri => fileWatcherEvent('deleted', uri)); - - this.buildIndex(); - this.logger.info('Initialized'); } /** * Disposes the extension. - * + * * @memberof ImportResolveExtension */ public dispose(): void { this.logger.info('Disposed'); } - /** - * Instructs the index to build an index for the found files (actually searches for all files in the - * current workspace). - * - * @private - * @returns {Promise} - * - * @memberof ImportResolveExtension - */ - private async buildIndex(): Promise { - await this.abstractIndexFunction('Create index.', async () => { - const files = await findFiles(this.config, this.rootPath); - this.logger.info(`Calculating index for ${files.length} files.`); - await this.index.buildIndex(files); - }); - } - - /** - * Instructs the index to rebuild the partial index for the changed files. - * - * @private - * @param {FileChanges} changes - * @returns {Promise} - * @memberof ImportResolveExtension - */ - private async rebuildForFileChanges(changes: FileChanges): Promise { - this.abstractIndexFunction('Reindex changes.', async () => { - await this.index.reindexForChanges(changes); - }); - } - - /** - * Abstracts the build and rebuild functions to be just one call withProgress. - * - * @private - * @param {string} title - * @param {() => Promise} func - * @returns {Promise} - * @memberof ImportResolveExtension - */ - private async abstractIndexFunction(title: string, func: () => Promise): Promise { - await window.withProgress( - { - title, - location: ProgressLocation.Window, - }, - async (progress) => { - this.logger.info('(Re-)Calculating index.'); - progress.report({ message: '(Re-)Calculating index.' }); - this.statusBarItem.text = resolverSyncing; - - try { - await func(); - this.logger.info('(Re-)Calculate finished.'); - progress.report({ message: '(Re-)Calculate finished.' }); - this.statusBarItem.text = resolverOk; - } catch (e) { - this.logger.error('There was an error during the index (re)calculation.', e); - progress.report({ message: 'There was an error during the index (re)calculation.' }); - this.statusBarItem.text = resolverErr; - } - }, - ); - } - /** * Add an import from the whole list. Calls the vscode gui, where the user can * select a symbol to import. - * + * * @private * @returns {Promise} - * + * * @memberof ResolveExtension */ private async addImport(): Promise { - if (!this.index.indexReady) { + if (!window.activeTextEditor) { + return; + } + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); + if (!index || !index.indexReady) { this.showCacheWarning(); return; } try { const selectedItem = await window.showQuickPick( - this.index.declarationInfos.map(o => new ResolveQuickPickItem(o)), + index.declarationInfos.map(o => new ResolveQuickPickItem(o)), { placeHolder: 'Add import to document:' }, ); if (selectedItem) { @@ -334,17 +225,18 @@ export class ImportResolveExtension extends BaseExtension { /** * Add an import from the whole list. Calls the vscode gui, where the user can * select a symbol to import. - * + * * @private * @returns {Promise} - * + * * @memberof ImportResolveExtension */ private async addImportUnderCursor(): Promise { if (!window.activeTextEditor) { return; } - if (!this.index.indexReady) { + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); + if (!index || !index.indexReady) { this.showCacheWarning(); return; } @@ -384,17 +276,18 @@ export class ImportResolveExtension extends BaseExtension { /** * 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; } - if (!this.index.indexReady) { + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); + if (!index || !index.indexReady) { this.showCacheWarning(); return; } @@ -417,10 +310,10 @@ export class ImportResolveExtension extends BaseExtension { /** * Organizes the imports of the actual document. Sorts and formats them correctly. - * + * * @private * @returns {Promise} - * + * * @memberof ImportResolveExtension */ private async organizeImports(): Promise { @@ -438,11 +331,11 @@ export class ImportResolveExtension extends BaseExtension { /** * Effectifely adds an import quick pick item to a document - * + * * @private * @param {DeclarationInfo} declaration * @returns {Promise} - * + * * @memberof ImportResolveExtension */ private async addImportToDocument(declaration: DeclarationInfo): Promise { @@ -455,10 +348,10 @@ export class ImportResolveExtension extends BaseExtension { /** * Returns the string under the cursor. - * + * * @private * @returns {string} - * + * * @memberof ImportResolveExtension */ private getSymbolUnderCursor(): string { @@ -474,9 +367,9 @@ export class ImportResolveExtension extends BaseExtension { /** * Shows a user warning if the resolve index is not ready yet. - * + * * @private - * + * * @memberof ImportResolveExtension */ private showCacheWarning(): void { @@ -486,22 +379,28 @@ export class ImportResolveExtension extends BaseExtension { /** * Calculates the possible imports for a given document source with a filter for the given symbol. * Returns a list of declaration infos that may be used for select picker or something. - * + * * @private * @param {DeclarationsForImportOptions} {cursorSymbol, documentSource, documentPath} * @returns {(Promise)} - * + * * @memberof ImportResolveExtension */ private async getDeclarationsForImport( { cursorSymbol, documentSource, documentPath }: DeclarationsForImportOptions, ): Promise { this.logger.info(`Calculate possible imports for document with filter "${cursorSymbol}"`); - + if (!window.activeTextEditor) { + return []; + } + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); + if (!index || !index.indexReady) { + return []; + } const parsedSource = await this.parser.parseSource(documentSource); const activeDocumentDeclarations = parsedSource.declarations.map(o => o.name); const declarations = getDeclarationsFilteredByImports( - this.index.declarationInfos, + index.declarationInfos, documentPath, parsedSource.imports, this.rootPath, @@ -516,21 +415,28 @@ export class ImportResolveExtension extends BaseExtension { /** * 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)[]> { - // TODO + if (!window.activeTextEditor) { + return []; + } + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); + if (!index || !index.indexReady) { + return []; + } + const parsedDocument = await this.parser.parseSource(documentSource); const missingDeclarations: (DeclarationInfo)[] = []; const declarations = getDeclarationsFilteredByImports( - this.index.declarationInfos, + index.declarationInfos, documentPath, parsedDocument.imports, this.rootPath, @@ -553,7 +459,7 @@ export class ImportResolveExtension extends BaseExtension { /** * Registers the commands for this extension. - * + * * @private * @memberof ImportResolveExtension */ @@ -576,7 +482,7 @@ export class ImportResolveExtension extends BaseExtension { commands.registerTextEditorCommand('typescriptHero.resolve.organizeImports', () => this.organizeImports()), ); this.context.subscriptions.push( - commands.registerCommand('typescriptHero.resolve.rebuildCache', () => this.buildIndex()), + commands.registerCommand('typescriptHero.resolve.rebuildCache', () => this.indices.rebuildAll()), ); } } From 5fc578022acd9f6fd3fd9180487d12d2c4cd59c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 12 Oct 2017 08:49:51 +0200 Subject: [PATCH 06/40] change code actions --- .../MissingImplementationInClassCreator.ts | 32 ++++++++----------- .../code-actions/MissingImportCreator.ts | 28 ++++++++-------- .../extensions/CodeActionExtension.ts | 23 ++++++------- .../extensions/DeclarationIndexMapper.ts | 16 +++------- 4 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/extension/code-actions/MissingImplementationInClassCreator.ts b/src/extension/code-actions/MissingImplementationInClassCreator.ts index f0e1a3b..b5c8ae1 100644 --- a/src/extension/code-actions/MissingImplementationInClassCreator.ts +++ b/src/extension/code-actions/MissingImplementationInClassCreator.ts @@ -1,21 +1,16 @@ import { inject, injectable } from 'inversify'; -import { - ClassLikeDeclaration, - DeclarationIndex, - GenericDeclaration, - NamedImport, - TypescriptParser, -} from 'typescript-parser'; +import { ClassLikeDeclaration, GenericDeclaration, NamedImport, TypescriptParser } from 'typescript-parser'; import { Command, Diagnostic, TextDocument } from 'vscode'; import { getAbsolutLibraryName } from '../../common/helpers'; +import { DeclarationIndexMapper } from '../extensions/DeclarationIndexMapper'; import { iocSymbols } from '../IoCSymbols'; import { ImplementPolymorphElements, NoopCodeAction } from './CodeAction'; import { CodeActionCreator } from './CodeActionCreator'; /** * Action creator that handles missing implementations in a class. - * + * * @export * @class MissingImplementationInClassCreator * @extends {CodeActionCreator} @@ -24,7 +19,7 @@ import { CodeActionCreator } from './CodeActionCreator'; export class MissingImplementationInClassCreator extends CodeActionCreator { constructor( @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.declarationIndex) private index: DeclarationIndex, + @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, @inject(iocSymbols.rootPath) private rootPath: string, ) { super(); @@ -32,10 +27,10 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { /** * Determines if the given diagnostic can be handled by this creator. - * - * @param {Diagnostic} diagnostic - * @returns {boolean} - * + * + * @param {Diagnostic} diagnostic + * @returns {boolean} + * * @memberof MissingImplementationInClassCreator */ public canHandleDiagnostic(diagnostic: Diagnostic): boolean { @@ -45,19 +40,20 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { /** * 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} - * + * @returns {Promise} + * * @memberof MissingImplementationInClassCreator */ public async handleDiagnostic(document: TextDocument, commands: Command[], diagnostic: Diagnostic): Promise { const match = /class ['"](.*)['"] incorrectly implements.*['"](.*)['"]\./ig.exec(diagnostic.message) || /non-abstract class ['"](.*)['"].*implement inherited.*from class ['"](.*)['"]\./ig.exec(diagnostic.message); - if (!match) { + const index = this.indices.getIndexForFile(document.uri); + if (!match || !index) { return commands; } @@ -76,7 +72,7 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { o => o instanceof NamedImport && o.specifiers.some(s => s.specifier === specifier), ); const declaration = (parsedDocument.declarations.find(o => o.name === specifier) || - (this.index.declarationInfos.find( + (index.declarationInfos.find( o => o.declaration.name === specifier && o.from === getAbsolutLibraryName(alreadyImported!.libraryName, document.fileName, this.rootPath), ) || { declaration: undefined }).declaration) as (ClassLikeDeclaration & GenericDeclaration) | undefined; diff --git a/src/extension/code-actions/MissingImportCreator.ts b/src/extension/code-actions/MissingImportCreator.ts index 9f490e2..1724d80 100644 --- a/src/extension/code-actions/MissingImportCreator.ts +++ b/src/extension/code-actions/MissingImportCreator.ts @@ -1,14 +1,14 @@ import { inject, injectable } from 'inversify'; -import { DeclarationIndex } from 'typescript-parser'; import { Command, Diagnostic, TextDocument } from 'vscode'; +import { DeclarationIndexMapper } from '../extensions/DeclarationIndexMapper'; import { iocSymbols } from '../IoCSymbols'; import { AddImportCodeAction, AddMissingImportsCodeAction, NoopCodeAction } from './CodeAction'; import { CodeActionCreator } from './CodeActionCreator'; /** * Action creator that handles missing imports in files. - * + * * @export * @class MissingImportCreator * @extends {CodeActionCreator} @@ -16,17 +16,17 @@ import { CodeActionCreator } from './CodeActionCreator'; @injectable() export class MissingImportCreator extends CodeActionCreator { constructor( - @inject(iocSymbols.declarationIndex) private index: DeclarationIndex, + @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { super(); } /** * Determines if the given diagnostic can be handled by this creator. - * - * @param {Diagnostic} diagnostic - * @returns {boolean} - * + * + * @param {Diagnostic} diagnostic + * @returns {boolean} + * * @memberof MissingImportCreator */ public canHandleDiagnostic(diagnostic: Diagnostic): boolean { @@ -35,21 +35,23 @@ export class MissingImportCreator extends CodeActionCreator { /** * 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} - * + * @returns {Promise} + * * @memberof MissingImportCreator */ public async handleDiagnostic(document: TextDocument, commands: Command[], diagnostic: Diagnostic): Promise { const match = /cannot find name ['"](.*)['"]/ig.exec(diagnostic.message); - if (!match) { + const index = this.indices.getIndexForFile(document.uri); + + if (!match || !index) { return commands; } - const infos = this.index.declarationInfos.filter(o => o.declaration.name === match[1]); + const infos = index.declarationInfos.filter(o => o.declaration.name === match[1]); if (infos.length > 0) { for (const info of infos) { commands.push(this.createCommand( @@ -65,7 +67,7 @@ export class MissingImportCreator extends CodeActionCreator { ) { commands.push(this.createCommand( 'Add all missing imports if possible.', - new AddMissingImportsCodeAction(document, this.index), + new AddMissingImportsCodeAction(document, index), )); } } else { diff --git a/src/extension/extensions/CodeActionExtension.ts b/src/extension/extensions/CodeActionExtension.ts index 94580f2..e393bd0 100644 --- a/src/extension/extensions/CodeActionExtension.ts +++ b/src/extension/extensions/CodeActionExtension.ts @@ -1,5 +1,4 @@ import { inject, injectable, multiInject } from 'inversify'; -import { DeclarationIndex } from 'typescript-parser'; import { CancellationToken, CodeActionContext, @@ -18,12 +17,13 @@ import { CodeAction } from '../code-actions/CodeAction'; import { CodeActionCreator } from '../code-actions/CodeActionCreator'; import { iocSymbols } from '../IoCSymbols'; import { BaseExtension } from './BaseExtension'; +import { DeclarationIndexMapper } from './DeclarationIndexMapper'; /** * 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 + * 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} @@ -36,7 +36,7 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, @multiInject(iocSymbols.codeActionCreators) private actionCreators: CodeActionCreator[], - @inject(iocSymbols.declarationIndex) private index: DeclarationIndex, + @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { super(context); this.logger = loggerFactory('CodeActionExtension'); @@ -44,7 +44,7 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv /** * Initialized the extension. Registers the commands and other disposables to the context. - * + * * @memberof ImportResolveExtension */ public initialize(): void { @@ -60,7 +60,7 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv /** * Disposes the extension. - * + * * @memberof ImportResolveExtension */ public dispose(): void { @@ -69,13 +69,13 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv /** * 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( @@ -84,7 +84,8 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv context: CodeActionContext, _token: CancellationToken, ): Promise { - if (!this.index.indexReady) { + const index = this.indices.getIndexForFile(document.uri); + if (!index || !index.indexReady) { return []; } @@ -102,11 +103,11 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv /** * 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 { diff --git a/src/extension/extensions/DeclarationIndexMapper.ts b/src/extension/extensions/DeclarationIndexMapper.ts index 6e572a7..6d271c8 100644 --- a/src/extension/extensions/DeclarationIndexMapper.ts +++ b/src/extension/extensions/DeclarationIndexMapper.ts @@ -15,23 +15,17 @@ import { findFiles } from '../../common/helpers'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../../extension/IoCSymbols'; -// const parser = context.container.get(iocSymbols.typescriptParser); -// return new DeclarationIndex(parser, context.container.get(iocSymbols.rootPath)); - -/* -1. pro rootpath 1 index -2. build index -3. add workspace changed thingy pro index -spöter: -4. luege öbs im gliche folder isch zum imports etc resolve -*/ - interface WorkspaceIndex { index: DeclarationIndex; folder: WorkspaceFolder; watcher: FileSystemWatcher; } +// TODO documentation +// TODO change settings to scoped settings +// TODO move did change configuration to all indices +// TODO error handling of each index + @injectable() export class DeclarationIndexMapper { private logger: Logger; From b07c730fef9904dbea553adcd7c2d9cf43c2e05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 12 Oct 2017 08:52:26 +0200 Subject: [PATCH 07/40] change code completion --- .../extensions/CodeCompletionExtension.ts | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/extension/extensions/CodeCompletionExtension.ts b/src/extension/extensions/CodeCompletionExtension.ts index f5eff50..66d46cd 100644 --- a/src/extension/extensions/CodeCompletionExtension.ts +++ b/src/extension/extensions/CodeCompletionExtension.ts @@ -1,15 +1,15 @@ import { inject, injectable } from 'inversify'; -import { DeclarationIndex, DeclarationInfo, TypescriptParser } from 'typescript-parser'; +import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; import { CancellationToken, commands, CompletionItem, CompletionItemProvider, + Disposable, ExtensionContext, languages, Position, TextDocument, - Disposable, workspace, } from 'vscode'; @@ -20,10 +20,11 @@ import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers/ImportManager'; import { getItemKind } from '../utilities/utilityFunctions'; import { BaseExtension } from './BaseExtension'; +import { DeclarationIndexMapper } from './DeclarationIndexMapper'; /** * Extension that provides code completion for typescript files. Uses the calculated index to provide information. - * + * * @export * @class CodeCompletionExtension * @extends {BaseExtension} @@ -38,7 +39,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.declarationIndex) private index: DeclarationIndex, + @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, @inject(iocSymbols.rootPath) private rootPath: string, @inject(iocSymbols.configuration) private config: ExtensionConfig, ) { @@ -48,7 +49,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion /** * Initialized the extension. Registers the commands and other disposables to the context. - * + * * @memberof CodeCompletionExtension */ public initialize(): void { @@ -82,7 +83,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion /** * Disposes the extension. - * + * * @memberof CodeCompletionExtension */ public dispose(): void { @@ -94,12 +95,12 @@ export class CodeCompletionExtension extends BaseExtension implements Completion /** * Provides completion items for a given position in the given document. - * - * @param {TextDocument} document - * @param {Position} position - * @param {CancellationToken} token - * @returns {Promise<(CompletionItem[] | null)>} - * + * + * @param {TextDocument} document + * @param {Position} position + * @param {CancellationToken} token + * @returns {Promise<(CompletionItem[] | null)>} + * * @memberof CodeCompletionExtension */ public async provideCompletionItems( @@ -107,7 +108,8 @@ export class CodeCompletionExtension extends BaseExtension implements Completion position: Position, token: CancellationToken, ): Promise { - if (!this.index.indexReady) { + const index = this.indices.getIndexForFile(document.uri); + if (!index || !index.indexReady) { return null; } @@ -123,7 +125,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion if (!searchWord || token.isCancellationRequested || - !this.index.indexReady || + !index.indexReady || (lineText.substring(0, position.character).match(/["'`]/g) || []).length % 2 === 1 || lineText.match(/^\s*(\/\/|\/\*\*|\*\/|\*)/g) || lineText.startsWith('import ') || @@ -135,7 +137,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion const parsed = await this.parser.parseSource(document.getText()); const declarations = getDeclarationsFilteredByImports( - this.index.declarationInfos, + index.declarationInfos, document.fileName, parsed.imports, this.rootPath, @@ -166,11 +168,11 @@ export class CodeCompletionExtension extends BaseExtension implements Completion /** * 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} + * @param {TextDocument} document + * @param {DeclarationInfo} declaration + * @returns {Promise} * @memberof CodeCompletionExtension */ private async executeIntellisenseItem(document: TextDocument, declaration: DeclarationInfo): Promise { From 22931536f70e84efc2c8652512f29c39e1b303e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 12 Oct 2017 08:59:08 +0200 Subject: [PATCH 08/40] moved mapper --- src/extension/IoC.ts | 2 +- .../code-actions/MissingImplementationInClassCreator.ts | 2 +- src/extension/code-actions/MissingImportCreator.ts | 2 +- src/extension/extensions/CodeActionExtension.ts | 2 +- src/extension/extensions/CodeCompletionExtension.ts | 2 +- src/extension/extensions/ImportResolveExtension.ts | 2 +- .../{extensions => utilities}/DeclarationIndexMapper.ts | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename src/extension/{extensions => utilities}/DeclarationIndexMapper.ts (100%) diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 19bdf23..7c13c1b 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -9,12 +9,12 @@ import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCr import { BaseExtension } from './extensions/BaseExtension'; import { CodeActionExtension } from './extensions/CodeActionExtension'; import { CodeCompletionExtension } from './extensions/CodeCompletionExtension'; -import { DeclarationIndexMapper } from './extensions/DeclarationIndexMapper'; 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 { VscodeLogger } from './utilities/VscodeLogger'; import { VscodeExtensionConfig } from './VscodeExtensionConfig'; diff --git a/src/extension/code-actions/MissingImplementationInClassCreator.ts b/src/extension/code-actions/MissingImplementationInClassCreator.ts index b5c8ae1..16a1ad3 100644 --- a/src/extension/code-actions/MissingImplementationInClassCreator.ts +++ b/src/extension/code-actions/MissingImplementationInClassCreator.ts @@ -3,8 +3,8 @@ import { ClassLikeDeclaration, GenericDeclaration, NamedImport, TypescriptParser import { Command, Diagnostic, TextDocument } from 'vscode'; import { getAbsolutLibraryName } from '../../common/helpers'; -import { DeclarationIndexMapper } from '../extensions/DeclarationIndexMapper'; import { iocSymbols } from '../IoCSymbols'; +import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; import { ImplementPolymorphElements, NoopCodeAction } from './CodeAction'; import { CodeActionCreator } from './CodeActionCreator'; diff --git a/src/extension/code-actions/MissingImportCreator.ts b/src/extension/code-actions/MissingImportCreator.ts index 1724d80..bcdc634 100644 --- a/src/extension/code-actions/MissingImportCreator.ts +++ b/src/extension/code-actions/MissingImportCreator.ts @@ -1,8 +1,8 @@ import { inject, injectable } from 'inversify'; import { Command, Diagnostic, TextDocument } from 'vscode'; -import { DeclarationIndexMapper } from '../extensions/DeclarationIndexMapper'; import { iocSymbols } from '../IoCSymbols'; +import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; import { AddImportCodeAction, AddMissingImportsCodeAction, NoopCodeAction } from './CodeAction'; import { CodeActionCreator } from './CodeActionCreator'; diff --git a/src/extension/extensions/CodeActionExtension.ts b/src/extension/extensions/CodeActionExtension.ts index e393bd0..2634847 100644 --- a/src/extension/extensions/CodeActionExtension.ts +++ b/src/extension/extensions/CodeActionExtension.ts @@ -16,8 +16,8 @@ import { Logger, LoggerFactory } from '../../common/utilities'; import { CodeAction } from '../code-actions/CodeAction'; import { CodeActionCreator } from '../code-actions/CodeActionCreator'; import { iocSymbols } from '../IoCSymbols'; +import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; import { BaseExtension } from './BaseExtension'; -import { DeclarationIndexMapper } from './DeclarationIndexMapper'; /** * Provider instance that is responsible for the "light bulb" feature. diff --git a/src/extension/extensions/CodeCompletionExtension.ts b/src/extension/extensions/CodeCompletionExtension.ts index 66d46cd..36a6e9a 100644 --- a/src/extension/extensions/CodeCompletionExtension.ts +++ b/src/extension/extensions/CodeCompletionExtension.ts @@ -18,9 +18,9 @@ import { getDeclarationsFilteredByImports } from '../../common/helpers'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers/ImportManager'; +import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; import { getItemKind } from '../utilities/utilityFunctions'; import { BaseExtension } from './BaseExtension'; -import { DeclarationIndexMapper } from './DeclarationIndexMapper'; /** * Extension that provides code completion for typescript files. Uses the calculated index to provide information. diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index 87e2b04..48fea7b 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -11,8 +11,8 @@ import { ResolveQuickPickItem } from '../../common/quick-pick-items'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers'; +import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; import { BaseExtension } from './BaseExtension'; -import { DeclarationIndexMapper } from './DeclarationIndexMapper'; type DeclarationsForImportOptions = { cursorSymbol: string, documentSource: string, documentPath: string }; type MissingDeclarationsForFileOptions = { documentSource: string, documentPath: string }; diff --git a/src/extension/extensions/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts similarity index 100% rename from src/extension/extensions/DeclarationIndexMapper.ts rename to src/extension/utilities/DeclarationIndexMapper.ts From f305b49754df2ee5b6e25010d497583d997f5e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 12 Oct 2017 09:02:33 +0200 Subject: [PATCH 09/40] style --- src/extension/utilities/VscodeLogger.ts | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/extension/utilities/VscodeLogger.ts b/src/extension/utilities/VscodeLogger.ts index a804538..907d96a 100644 --- a/src/extension/utilities/VscodeLogger.ts +++ b/src/extension/utilities/VscodeLogger.ts @@ -5,7 +5,7 @@ import { ExtensionContext, OutputChannel, window } from 'vscode'; /** * Central logger instance of the extension. - * + * * @export * @class VscodeLogger */ @@ -21,10 +21,10 @@ export class VscodeLogger implements Logger { /** * Logs an error message. Provided data is logged out after the message. - * + * * @param {string} message * @param {*} [data] - * + * * @memberof VscodeLogger */ public error(message: string, data?: any): void { @@ -38,10 +38,10 @@ export class VscodeLogger implements Logger { /** * Logs a warning message. Provided data is logged out after the message. - * + * * @param {string} message * @param {*} [data] - * + * * @memberof VscodeLogger */ public warning(message: string, data?: any): void { @@ -55,10 +55,10 @@ export class VscodeLogger implements Logger { /** * Logs an info message. Provided data is logged out after the message. - * + * * @param {string} message * @param {*} [data] - * + * * @memberof VscodeLogger */ public info(message: string, data?: any): void { @@ -73,13 +73,13 @@ export class VscodeLogger implements Logger { /** * Internal method to actually do the logging. Checks if the output should be done and logs * the data into the output channel and the console (if debugging). - * + * * @private * @param {LogLevel} level * @param {string} severity * @param {string} message * @param {*} [data] - * + * * @memberof VscodeLogger */ private log(level: LogLevel, severity: string, message: string, data?: any): void { @@ -101,10 +101,10 @@ export class VscodeLogger implements Logger { /** * Returns a propper formatted date for logging. - * + * * @private * @returns {string} - * + * * @memberof Logger */ private getDate(): string { @@ -127,10 +127,10 @@ export class VscodeLogger implements Logger { /** * Maps the configuration string to a propper enum value of LogLevel. - * + * * @private * @returns {LogLevel} - * + * * @memberof VscodeLogger */ private getLogLevel(): LogLevel { From 2317f7f011ee70ca063da416a94b021909c1bdb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 12 Oct 2017 09:45:02 +0200 Subject: [PATCH 10/40] change settings scope --- package.json | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 3f1a285..946c8a9 100644 --- a/package.json +++ b/package.json @@ -199,25 +199,29 @@ "All" ], "default": "Warnings", - "description": "Defines the log output level in the output window." + "description": "Defines the log output level in the output window.", + "scope": "window" }, - "typescriptHero.completionSortMode": { + "typescriptHero.codeCompletion.completionSortMode": { "enum": [ "default", "bottom" ], "default": "default", - "description": "Import completion sort order" + "description": "Defines the sortmode of the code completion in intellisense (bottom means sorted to bottom).", + "scope": "resource" }, "typescriptHero.resolver.insertSpaceBeforeAndAfterImportBraces": { "type": "boolean", "default": true, - "description": "Defines if there should be a space inside the curly braces of an import statement." + "description": "Defines if there should be a space inside the curly braces of an import statement.", + "scope": "resource" }, "typescriptHero.resolver.insertSemicolons": { "type": "boolean", "default": true, - "description": "Defines if there should be a semicolon at the end of a statement." + "description": "Defines if there should be a semicolon at the end of a statement.", + "scope": "resource" }, "typescriptHero.resolver.stringQuoteStyle": { "enum": [ @@ -225,7 +229,8 @@ "\"" ], "default": "'", - "description": "Defines if single or double quotes should be used." + "description": "Defines if single or double quotes should be used.", + "scope": "resource" }, "typescriptHero.resolver.ignorePatterns": { "type": "array", @@ -238,24 +243,28 @@ "out", "dist" ], - "description": "Defines partial pathes that are ignored during indexing (e.g. 'node_modules' would exclude all modules)." + "description": "Defines partial pathes that are ignored during indexing (e.g. 'node_modules' would exclude all modules).", + "scope": "resource" }, "typescriptHero.resolver.multiLineWrapThreshold": { "type": "number", "minimum": 1, "multipleOf": 1, "default": 125, - "description": "Defines the threshold when an import should be wrapped into a multiline import." + "description": "Defines the threshold when an import should be wrapped into a multiline import.", + "scope": "resource" }, "typescriptHero.resolver.multiLineTrailingComma": { "type": "boolean", "default": true, - "description": "Defined if multi line imports contain the last trailing comma." + "description": "Defined if multi line imports contain the last trailing comma.", + "scope": "resource" }, "typescriptHero.resolver.disableImportsSorting": { "type": "boolean", "default": false, - "description": "Defines if sorting is disable during organize imports." + "description": "Defines if sorting is disable during organize imports.", + "scope": "resource" }, "typescriptHero.resolver.disableImportRemovalOnOrganize": { "type": "boolean", @@ -265,7 +274,8 @@ "typescriptHero.resolver.organizeOnSave": { "type": "boolean", "default": false, - "description": "Defines if the imports should be organized on save." + "description": "Defines if the imports should be organized on save.", + "scope": "resource" }, "typescriptHero.resolver.ignoreImportsForOrganize": { "type": "array", @@ -276,7 +286,8 @@ "default": [ "react" ], - "description": "Defines imports (libraries, so the 'from' part), which are not removed during 'organize imports'." + "description": "Defines imports (libraries, so the 'from' part), which are not removed during 'organize imports'.", + "scope": "resource" }, "typescriptHero.resolver.importGroups": { "type": "array", @@ -345,7 +356,8 @@ "Modules", "Workspace" ], - "description": "Defines the groups of the imports ordering. Multiple groups possible, see readme for instructions." + "description": "Defines the groups of the imports ordering. Multiple groups possible, see readme for instructions.", + "scope": "resource" }, "typescriptHero.resolver.resolverMode": { "enum": [ @@ -353,18 +365,21 @@ "ES6", "Both" ], - "default": "TypeScript", - "description": "Defines the mode of the symbol resolver (i.e. if JavaScript files should be indexed as well (experimental)." + "default": "Both", + "description": "Defines the mode of the symbol resolver. (Note that JavaScript mode only indexes workspace files)", + "scope": "resource" }, "typescriptHero.resolver.promptForSpecifiers": { "type": "boolean", "default": true, - "description": "Defines if typescript hero should ask the user for default specifiers or duplicate specifier aliases." + "description": "Defines if typescript hero should ask the user for default specifiers or duplicate specifier aliases.", + "scope": "resource" }, "typescriptHero.codeOutline.enabled": { "type": "boolean", "default": true, - "description": "Defines if the code outline feature (and window) are enabled or not." + "description": "Defines if the code outline feature (and window) are enabled or not.", + "scope": "resource" } } } From 8a5e1174ba8b7a17779494a3d919f9648af261f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 07:43:38 +0200 Subject: [PATCH 11/40] change scope of settings --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 946c8a9..7f06ee9 100644 --- a/package.json +++ b/package.json @@ -373,13 +373,13 @@ "type": "boolean", "default": true, "description": "Defines if typescript hero should ask the user for default specifiers or duplicate specifier aliases.", - "scope": "resource" + "scope": "window" }, "typescriptHero.codeOutline.enabled": { "type": "boolean", "default": true, "description": "Defines if the code outline feature (and window) are enabled or not.", - "scope": "resource" + "scope": "window" } } } From db174f72a6b72845b5d5e23818e0228477249587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 07:49:59 +0200 Subject: [PATCH 12/40] change the config interface --- src/common/config/CodeOutlineConfig.ts | 16 ++++++++++++++-- src/common/config/ExtensionConfig.ts | 22 +++++++++++++++++----- src/common/config/ResolverConfig.ts | 11 +++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/common/config/CodeOutlineConfig.ts b/src/common/config/CodeOutlineConfig.ts index 0ae656f..9878589 100644 --- a/src/common/config/CodeOutlineConfig.ts +++ b/src/common/config/CodeOutlineConfig.ts @@ -1,13 +1,25 @@ +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 | undefined)} + * @memberof CodeOutlineConfig + */ + resource: Uri | undefined; + /** * Defined if the code outline feature is enabled or not. - * + * * @type {boolean} * @memberof CodeOutlineConfig */ diff --git a/src/common/config/ExtensionConfig.ts b/src/common/config/ExtensionConfig.ts index a090178..ebe6222 100644 --- a/src/common/config/ExtensionConfig.ts +++ b/src/common/config/ExtensionConfig.ts @@ -1,17 +1,29 @@ +import { Uri } from 'vscode'; + 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 | undefined)} + * @memberof ExtensionConfig + */ + resource: Uri | undefined; + /** * The actual log level. - * + * * @readonly * @type {string} * @memberof ExtensionConfig @@ -20,7 +32,7 @@ export interface ExtensionConfig { /** * Configuration object for the resolver extension. - * + * * @readonly * @type {ResolverConfig} * @memberof ExtensionConfig @@ -29,7 +41,7 @@ export interface ExtensionConfig { /** * Configuration object for the code outline extension. - * + * * @readonly * @type {CodeOutlineConfig} * @memberof ExtensionConfig @@ -40,7 +52,7 @@ export interface ExtensionConfig { * Completion sorting mode: * default: Use default VSCode sorting mode * bottom: Push to bottom - * + * * @readonly * @type {'default'|'bottom'} * @memberof ExtensionConfig diff --git a/src/common/config/ResolverConfig.ts b/src/common/config/ResolverConfig.ts index 85ff6d1..6f99f48 100644 --- a/src/common/config/ResolverConfig.ts +++ b/src/common/config/ResolverConfig.ts @@ -1,4 +1,5 @@ import { TypescriptGenerationOptions } from 'typescript-parser'; +import { Uri } from 'vscode'; import { ImportGroup } from '../../extension/import-grouping'; import { ResolverMode } from '../enums'; @@ -9,6 +10,16 @@ import { ResolverMode } from '../enums'; * @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 | undefined)} + * @memberof ResolverConfig + */ + resource: Uri | undefined; + /** * Defines, if there should be a space between the brace and the import specifiers. * {Symbol} vs { Symbol } From b2113315eb4a095faf8d19ae54be7fe9a80b568d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 08:02:33 +0200 Subject: [PATCH 13/40] adding new configs --- src/common/config/CodeCompletionConfig.ts | 27 +++++++++++++++++++++++ src/common/config/ExtensionConfig.ts | 13 +++++------ src/common/config/ResolverConfig.ts | 4 ++-- src/common/config/index.ts | 1 + src/common/factories/index.ts | 3 +++ 5 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 src/common/config/CodeCompletionConfig.ts diff --git a/src/common/config/CodeCompletionConfig.ts b/src/common/config/CodeCompletionConfig.ts new file mode 100644 index 0000000..b99efaa --- /dev/null +++ b/src/common/config/CodeCompletionConfig.ts @@ -0,0 +1,27 @@ +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). + * + * @type {('default' | 'bottom')} + * @memberof CodeCompletionConfig + */ + completionSortMode: 'default' | 'bottom'; +} diff --git a/src/common/config/ExtensionConfig.ts b/src/common/config/ExtensionConfig.ts index ebe6222..9d54ed5 100644 --- a/src/common/config/ExtensionConfig.ts +++ b/src/common/config/ExtensionConfig.ts @@ -1,5 +1,6 @@ import { Uri } from 'vscode'; +import { CodeCompletionConfig } from './CodeCompletionConfig'; import { CodeOutlineConfig } from './CodeOutlineConfig'; import { ResolverConfig } from './ResolverConfig'; @@ -16,10 +17,10 @@ export interface ExtensionConfig { * Is needed to determine the actual config values for multi root environments. * * @readonly - * @type {(Uri | undefined)} + * @type {Uri} * @memberof ExtensionConfig */ - resource: Uri | undefined; + resource?: Uri; /** * The actual log level. @@ -49,13 +50,11 @@ export interface ExtensionConfig { codeOutline: CodeOutlineConfig; /** - * Completion sorting mode: - * default: Use default VSCode sorting mode - * bottom: Push to bottom + * Configuration object for the code completion extension. * * @readonly - * @type {'default'|'bottom'} + * @type {CodeCompletionConfig} * @memberof ExtensionConfig */ - completionSortMode: 'default' | 'bottom'; + codeCompletion: CodeCompletionConfig; } diff --git a/src/common/config/ResolverConfig.ts b/src/common/config/ResolverConfig.ts index 6f99f48..0457f80 100644 --- a/src/common/config/ResolverConfig.ts +++ b/src/common/config/ResolverConfig.ts @@ -15,10 +15,10 @@ export interface ResolverConfig { * Is needed to determine the actual config values for multi root environments. * * @readonly - * @type {(Uri | undefined)} + * @type {Uri} * @memberof ResolverConfig */ - resource: Uri | undefined; + resource?: Uri; /** * Defines, if there should be a space between the brace and the import specifiers. diff --git a/src/common/config/index.ts b/src/common/config/index.ts index 4a95f94..04b8fa7 100644 --- a/src/common/config/index.ts +++ b/src/common/config/index.ts @@ -1,3 +1,4 @@ export * from './ExtensionConfig'; export * from './ResolverConfig'; export * from './CodeOutlineConfig'; +export * from './CodeCompletionConfig'; diff --git a/src/common/factories/index.ts b/src/common/factories/index.ts index 53b7469..92ec79e 100644 --- a/src/common/factories/index.ts +++ b/src/common/factories/index.ts @@ -1,6 +1,9 @@ +import { VscodeExtensionConfig } from '../../extension/config/VscodeExtensionConfig'; import { TypescriptCodeGenerator } from 'typescript-parser'; /** * IOC Factory for the {TypescriptCodeGenerator}. */ export type TypescriptCodeGeneratorFactory = () => TypescriptCodeGenerator; + +export type VscodeConfigFactory = () => VscodeExtensionConfig; From fb6572f5287b9d0886c1119d9fe0823d285bfcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 08:16:22 +0200 Subject: [PATCH 14/40] add new config structure --- .../config/VscodeCodeCompletionConfig.ts | 30 ++ .../config/VscodeCodeOutlineConfig.ts | 30 ++ src/extension/config/VscodeExtensionConfig.ts | 74 +++++ src/extension/config/VscodeResolverConfig.ts | 286 ++++++++++++++++++ 4 files changed, 420 insertions(+) create mode 100644 src/extension/config/VscodeCodeCompletionConfig.ts create mode 100644 src/extension/config/VscodeCodeOutlineConfig.ts create mode 100644 src/extension/config/VscodeExtensionConfig.ts create mode 100644 src/extension/config/VscodeResolverConfig.ts diff --git a/src/extension/config/VscodeCodeCompletionConfig.ts b/src/extension/config/VscodeCodeCompletionConfig.ts new file mode 100644 index 0000000..634532e --- /dev/null +++ b/src/extension/config/VscodeCodeCompletionConfig.ts @@ -0,0 +1,30 @@ +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/extension/config/VscodeCodeOutlineConfig.ts b/src/extension/config/VscodeCodeOutlineConfig.ts new file mode 100644 index 0000000..4d1db04 --- /dev/null +++ b/src/extension/config/VscodeCodeOutlineConfig.ts @@ -0,0 +1,30 @@ +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/extension/config/VscodeExtensionConfig.ts b/src/extension/config/VscodeExtensionConfig.ts new file mode 100644 index 0000000..a71efa2 --- /dev/null +++ b/src/extension/config/VscodeExtensionConfig.ts @@ -0,0 +1,74 @@ +import { injectable } from 'inversify'; +import { Uri, workspace, WorkspaceConfiguration } from 'vscode'; + +import { CodeCompletionConfig, CodeOutlineConfig, ExtensionConfig, ResolverConfig } from '../../common/config'; +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 { + private resolverConfig: ResolverConfig = new VscodeResolverConfig(); + private codeOutlineConfig: CodeOutlineConfig = new VscodeCodeOutlineConfig(); + private codeCompletionConfig: CodeCompletionConfig = '' as any; + + private get workspaceSection(): WorkspaceConfiguration { + return workspace.getConfiguration(sectionKey, this.resource); + } + + /** + * The actual log level. + * + * @readonly + * @type {string} + * @memberof VscodeExtensionConfig + */ + public get verbosity(): string { + return this.workspaceSection.get('verbosity', 'Warning'); + } + + /** + * 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) { } +} + + diff --git a/src/extension/config/VscodeResolverConfig.ts b/src/extension/config/VscodeResolverConfig.ts new file mode 100644 index 0000000..9e08717 --- /dev/null +++ b/src/extension/config/VscodeResolverConfig.ts @@ -0,0 +1,286 @@ +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 (e.g. build, out, node_modules). + * If those parts are found after the workspace path is striped away, the file is ignored. + * + * @readonly + * @type {string[]} + * @memberof VscodeResolverConfig + */ + public get ignorePatterns(): string[] { + return this.workspaceSection.get( + 'ignorePatterns', + [ + 'build', + 'out', + 'dist', + ], + ); + } + + /** + * 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 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) { } +} From b746d9ccdf7ae872a3d40f9b5054d68950ee7c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 08:18:49 +0200 Subject: [PATCH 15/40] adding factory and ctor for configs --- src/common/config/CodeOutlineConfig.ts | 4 ++-- src/common/factories/index.ts | 6 ++++-- src/extension/config/VscodeExtensionConfig.ts | 13 +++++++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/common/config/CodeOutlineConfig.ts b/src/common/config/CodeOutlineConfig.ts index 9878589..e6c5aee 100644 --- a/src/common/config/CodeOutlineConfig.ts +++ b/src/common/config/CodeOutlineConfig.ts @@ -12,10 +12,10 @@ export interface CodeOutlineConfig { * Is needed to determine the actual config values for multi root environments. * * @readonly - * @type {(Uri | undefined)} + * @type {Uri} * @memberof CodeOutlineConfig */ - resource: Uri | undefined; + resource?: Uri; /** * Defined if the code outline feature is enabled or not. diff --git a/src/common/factories/index.ts b/src/common/factories/index.ts index 92ec79e..ef704d9 100644 --- a/src/common/factories/index.ts +++ b/src/common/factories/index.ts @@ -1,9 +1,11 @@ -import { VscodeExtensionConfig } from '../../extension/config/VscodeExtensionConfig'; import { TypescriptCodeGenerator } from 'typescript-parser'; +import { Uri } from 'vscode'; + +import { VscodeExtensionConfig } from '../../extension/config/VscodeExtensionConfig'; /** * IOC Factory for the {TypescriptCodeGenerator}. */ export type TypescriptCodeGeneratorFactory = () => TypescriptCodeGenerator; -export type VscodeConfigFactory = () => VscodeExtensionConfig; +export type VscodeConfigFactory = (resource?: Uri) => VscodeExtensionConfig; diff --git a/src/extension/config/VscodeExtensionConfig.ts b/src/extension/config/VscodeExtensionConfig.ts index a71efa2..c4b461f 100644 --- a/src/extension/config/VscodeExtensionConfig.ts +++ b/src/extension/config/VscodeExtensionConfig.ts @@ -2,6 +2,7 @@ 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'; @@ -16,9 +17,9 @@ const sectionKey = 'typescriptHero'; */ @injectable() export class VscodeExtensionConfig implements ExtensionConfig { - private resolverConfig: ResolverConfig = new VscodeResolverConfig(); - private codeOutlineConfig: CodeOutlineConfig = new VscodeCodeOutlineConfig(); - private codeCompletionConfig: CodeCompletionConfig = '' as any; + private resolverConfig: ResolverConfig; + private codeOutlineConfig: CodeOutlineConfig; + private codeCompletionConfig: CodeCompletionConfig; private get workspaceSection(): WorkspaceConfiguration { return workspace.getConfiguration(sectionKey, this.resource); @@ -68,7 +69,11 @@ export class VscodeExtensionConfig implements ExtensionConfig { return this.codeCompletionConfig; } - constructor(public readonly resource?: Uri) { } + constructor(public readonly resource?: Uri) { + this.codeCompletionConfig = new VscodeCodeCompletionConfig(resource); + this.codeOutlineConfig = new VscodeCodeOutlineConfig(resource); + this.resolverConfig = new VscodeResolverConfig(resource); + } } From 5e64378fa5800f10240cf5024af28ea5d3db513c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 08:22:53 +0200 Subject: [PATCH 16/40] add config factory --- src/extension/IoC.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 7c13c1b..dd2c2b2 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -1,11 +1,12 @@ import { Container as IoCContainer, interfaces } from 'inversify'; import inversifyInjectDecorators from 'inversify-inject-decorators'; -import { DeclarationIndex, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { ExtensionContext, workspace } from 'vscode'; +import { TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; +import { ExtensionContext, Uri } from 'vscode'; import { ExtensionConfig } from '../common/config'; import { Logger } from '../common/utilities'; 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'; @@ -20,18 +21,7 @@ import { VscodeExtensionConfig } from './VscodeExtensionConfig'; const container = new IoCContainer(); -// DEPRECATED -container.bind(iocSymbols.rootPath).toConstantValue(workspace.rootPath || ''); container.bind(TypeScriptHero).to(TypeScriptHero).inSingletonScope(); -container.bind(iocSymbols.configuration).to(VscodeExtensionConfig).inSingletonScope(); -// DEPRECATED -container - .bind(iocSymbols.declarationIndex) - .toDynamicValue((context: interfaces.Context) => { - const parser = context.container.get(iocSymbols.typescriptParser); - return new DeclarationIndex(parser, context.container.get(iocSymbols.rootPath)); - }) - .inSingletonScope(); container.bind(iocSymbols.declarationIndexMapper).to(DeclarationIndexMapper).inSingletonScope(); @@ -51,6 +41,10 @@ container }; }); +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(); From 97c769a93feaf5a66767b97201b8a3ffc7cffa54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 17 Oct 2017 16:48:46 +0200 Subject: [PATCH 17/40] remove old config --- src/extension/IoC.ts | 8 +- src/extension/VscodeExtensionConfig.ts | 373 ------------------------- 2 files changed, 4 insertions(+), 377 deletions(-) delete mode 100644 src/extension/VscodeExtensionConfig.ts diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index dd2c2b2..e8aad84 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -4,6 +4,7 @@ import { TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, Uri } from 'vscode'; import { ExtensionConfig } from '../common/config'; +import { VscodeConfigFactory } from '../common/factories'; import { Logger } from '../common/utilities'; import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; import { VscodeExtensionConfig } from './config/VscodeExtensionConfig'; @@ -17,7 +18,6 @@ import { iocSymbols } from './IoCSymbols'; import { TypeScriptHero } from './TypeScriptHero'; import { DeclarationIndexMapper } from './utilities/DeclarationIndexMapper'; import { VscodeLogger } from './utilities/VscodeLogger'; -import { VscodeExtensionConfig } from './VscodeExtensionConfig'; const container = new IoCContainer(); @@ -35,9 +35,9 @@ container container .bind>(iocSymbols.generatorFactory) .toFactory((context: interfaces.Context) => { - return () => { - const config = context.container.get(iocSymbols.configuration); - return new TypescriptCodeGenerator(config.resolver.generationOptions); + return (resource?: Uri) => { + const configFactory = context.container.get(iocSymbols.configuration); + return new TypescriptCodeGenerator(configFactory(resource).resolver.generationOptions); }; }); diff --git a/src/extension/VscodeExtensionConfig.ts b/src/extension/VscodeExtensionConfig.ts deleted file mode 100644 index 23ac1dc..0000000 --- a/src/extension/VscodeExtensionConfig.ts +++ /dev/null @@ -1,373 +0,0 @@ -import { injectable } from 'inversify'; -import { TypescriptGenerationOptions } from 'typescript-parser'; -import { workspace, WorkspaceConfiguration } from 'vscode'; - -import { ExtensionConfig, ResolverConfig } from '../common/config'; -import { CodeOutlineConfig } from '../common/config/CodeOutlineConfig'; -import { ResolverMode } from '../common/enums'; -import { ImportGroup, ImportGroupSetting, ImportGroupSettingParser, RemainImportGroup } from './import-grouping'; - -const sectionKey = 'typescriptHero'; - -/** - * Configuration class for TypeScript Hero - * Contains all exposed config endpoints. - * - * @export - * @class VscodeExtensionConfig - */ -@injectable() -export class VscodeExtensionConfig implements ExtensionConfig { - private resolverConfig: ResolverConfig = new VscodeResolverConfig(); - private codeOutlineConfig: CodeOutlineConfig = new VscodeCodeOutlineConfig(); - - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey); - } - - /** - * The actual log level. - * - * @readonly - * @type {string} - * @memberof VscodeExtensionConfig - */ - public get verbosity(): string { - return this.workspaceSection.get('verbosity') || 'Warning'; - } - - /** - * 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; - } - - /** - * Completion sort mode - * - * @readonly - * @type {'default'|'bottom'} - * @memberof VscodeExtensionConfig - */ - public get completionSortMode(): 'default' | 'bottom' { - return this.workspaceSection.get<'default' | 'bottom'>('completionSortMode') || 'default'; - } -} - -/** - * Configuration class for the resolver extension. - * - * @class VscodeResolverConfig - */ -class VscodeResolverConfig implements ResolverConfig { - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey); - } - - /** - * 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 { - const value = this.workspaceSection.get('resolver.insertSpaceBeforeAndAfterImportBraces'); - return value !== undefined ? value : 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 { - const value = this.workspaceSection.get('resolver.insertSemicolons'); - return value !== undefined ? value : true; - } - - /** - * Defines the quote style (' or "). - * - * @readonly - * @type {string} - * @memberof VscodeResolverConfig - */ - public get stringQuoteStyle(): string { - return this.workspaceSection.get('resolver.stringQuoteStyle') || `'`; - } - - /** - * Array of string that are excluded from indexing (e.g. build, out, node_modules). - * If those parts are found after the workspace path is striped away, the file is ignored. - * - * @readonly - * @type {string[]} - * @memberof VscodeResolverConfig - */ - public get ignorePatterns(): string[] { - return this.workspaceSection.get('resolver.ignorePatterns') || [ - 'build', - 'out', - 'dist', - ]; - } - - /** - * 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('resolver.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 { - const value = this.workspaceSection.get('resolver.multiLineTrailingComma'); - return value !== undefined ? value : true; - } - - /** - * Defines, if sorting is obligatory during organize imports - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - */ - public get disableImportSorting(): boolean { - const value = this.workspaceSection.get('resolver.disableImportsSorting'); - return value !== undefined ? value : false; - } - - /** - * Defines, if removal unsed is obligatory during organize imports - * - * @readonly - * @type {boolean} - * @memberof ResolverConfig - */ - public get disableImportRemovalOnOrganize(): boolean { - const value = this.workspaceSection.get('resolver.disableImportRemovalOnOrganize'); - return value !== undefined ? value : 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('resolver.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('resolver.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 resolver. - * - * @readonly - * @type {ResolverMode} - * @memberof VscodeResolverConfig - */ - public get resolverMode(): ResolverMode { - const mode = this.workspaceSection.get('resolver.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('resolver.organizeOnSave', true); - const editorValue = workspace.getConfiguration().get('editor.formatOnSave', false); - return typescriptHeroValue && editorValue; - } - - /** - * 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('resolver.promptForSpecifiers', false); - } -} - -/** - * Configuration interface for the code outline feature. - * - * @class VscodeCodeOutlineConfig - * @implements {CodeOutlineConfig} - */ -class VscodeCodeOutlineConfig implements CodeOutlineConfig { - private get workspaceSection(): WorkspaceConfiguration { - return workspace.getConfiguration(sectionKey); - } - - /** - * Defined if the code outline feature is enabled or not. - * - * @readonly - * @type {boolean} - * @memberof VscodeCodeOutlineConfig - */ - public get outlineEnabled(): boolean { - const value = this.workspaceSection.get('codeOutline.enabled'); - return value !== undefined ? value : true; - } -} From 1b259436678bdbd68727764dd1e55db8979e2d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 08:49:53 +0200 Subject: [PATCH 18/40] change config in code completion --- .vscode/launch.json | 15 +++++++ src/common/config/ExtensionConfig.ts | 8 ++++ src/common/factories/index.ts | 4 +- src/common/helpers/DeclarationIndexHelpers.ts | 2 +- src/extension/IoC.ts | 9 ++--- src/extension/config/VscodeExtensionConfig.ts | 7 ++++ .../extensions/CodeCompletionExtension.ts | 40 +++++++------------ .../utilities/DeclarationIndexMapper.ts | 18 ++++----- 8 files changed, 59 insertions(+), 44 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 98daa37..829b9d1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -16,6 +16,21 @@ "${workspaceRoot}/out/src/**/*.js" ] }, + { + "name": "Launch Extension Multi-Root", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceRoot}/test/_workspace", + "--extensionDevelopmentPath=${workspaceRoot}" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/out/src/**/*.js" + ] + }, { "name": "Launch Tests", "type": "extensionHost", diff --git a/src/common/config/ExtensionConfig.ts b/src/common/config/ExtensionConfig.ts index 9d54ed5..7111110 100644 --- a/src/common/config/ExtensionConfig.ts +++ b/src/common/config/ExtensionConfig.ts @@ -31,6 +31,14 @@ export interface ExtensionConfig { */ verbosity: string; + /** + * 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. * diff --git a/src/common/factories/index.ts b/src/common/factories/index.ts index ef704d9..3b2f7ee 100644 --- a/src/common/factories/index.ts +++ b/src/common/factories/index.ts @@ -1,11 +1,11 @@ import { TypescriptCodeGenerator } from 'typescript-parser'; import { Uri } from 'vscode'; -import { VscodeExtensionConfig } from '../../extension/config/VscodeExtensionConfig'; +import { ExtensionConfig } from '../config'; /** * IOC Factory for the {TypescriptCodeGenerator}. */ export type TypescriptCodeGeneratorFactory = () => TypescriptCodeGenerator; -export type VscodeConfigFactory = (resource?: Uri) => VscodeExtensionConfig; +export type ConfigFactory = (resource?: Uri) => ExtensionConfig; diff --git a/src/common/helpers/DeclarationIndexHelpers.ts b/src/common/helpers/DeclarationIndexHelpers.ts index bc159e2..d63de24 100644 --- a/src/common/helpers/DeclarationIndexHelpers.ts +++ b/src/common/helpers/DeclarationIndexHelpers.ts @@ -114,7 +114,7 @@ export async function findFiles(config: ExtensionConfig, workspaceFolder: Worksp let globs: string[] = []; let ignores = ['**/typings/**']; const excludePatterns = config.resolver.ignorePatterns; // convert to resource config - const rootPath = workspaceFolder.uri.path; + const rootPath = workspaceFolder.uri.fsPath; if (rootPath && existsSync(join(rootPath, 'package.json'))) { const packageJson = require(join(rootPath, 'package.json')); diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index e8aad84..10d3813 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -4,7 +4,7 @@ import { TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, Uri } from 'vscode'; import { ExtensionConfig } from '../common/config'; -import { VscodeConfigFactory } from '../common/factories'; +import { ConfigFactory } from '../common/factories'; import { Logger } from '../common/utilities'; import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; import { VscodeExtensionConfig } from './config/VscodeExtensionConfig'; @@ -27,16 +27,13 @@ container.bind(iocSymbols.declarationIndexMapper).to(Dec container .bind(iocSymbols.typescriptParser) - .toDynamicValue(() => { - return new TypescriptParser(); - }) - .inSingletonScope(); + .toConstantValue(new TypescriptParser()); container .bind>(iocSymbols.generatorFactory) .toFactory((context: interfaces.Context) => { return (resource?: Uri) => { - const configFactory = context.container.get(iocSymbols.configuration); + const configFactory = context.container.get(iocSymbols.configuration); return new TypescriptCodeGenerator(configFactory(resource).resolver.generationOptions); }; }); diff --git a/src/extension/config/VscodeExtensionConfig.ts b/src/extension/config/VscodeExtensionConfig.ts index c4b461f..35ac546 100644 --- a/src/extension/config/VscodeExtensionConfig.ts +++ b/src/extension/config/VscodeExtensionConfig.ts @@ -17,6 +17,13 @@ const sectionKey = 'typescriptHero'; */ @injectable() export class VscodeExtensionConfig implements ExtensionConfig { + public readonly possibleLanguages: string[] = [ + 'typescript', + 'typescriptreact', + 'javascript', + 'javascriptreact', + ]; + private resolverConfig: ResolverConfig; private codeOutlineConfig: CodeOutlineConfig; private codeCompletionConfig: CodeCompletionConfig; diff --git a/src/extension/extensions/CodeCompletionExtension.ts b/src/extension/extensions/CodeCompletionExtension.ts index 36a6e9a..4a01f6d 100644 --- a/src/extension/extensions/CodeCompletionExtension.ts +++ b/src/extension/extensions/CodeCompletionExtension.ts @@ -5,7 +5,6 @@ import { commands, CompletionItem, CompletionItemProvider, - Disposable, ExtensionContext, languages, Position, @@ -13,7 +12,7 @@ import { workspace, } from 'vscode'; -import { ExtensionConfig } from '../../common/config'; +import { ConfigFactory } from '../../common/factories'; import { getDeclarationsFilteredByImports } from '../../common/helpers'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; @@ -33,15 +32,13 @@ import { BaseExtension } from './BaseExtension'; @injectable() export class CodeCompletionExtension extends BaseExtension implements CompletionItemProvider { private logger: Logger; - private languageRegisters: Disposable[] = []; constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - @inject(iocSymbols.rootPath) private rootPath: string, - @inject(iocSymbols.configuration) private config: ExtensionConfig, + @inject(iocSymbols.configuration) private config: ConfigFactory, ) { super(context); this.logger = loggerFactory('CodeCompletionExtension'); @@ -53,23 +50,10 @@ export class CodeCompletionExtension extends BaseExtension implements Completion * @memberof CodeCompletionExtension */ public initialize(): void { - for (const lang of this.config.resolver.resolverModeLanguages) { - this.languageRegisters.push(languages.registerCompletionItemProvider(lang, this)); + for (const lang of this.config().possibleLanguages) { + this.context.subscriptions.push(languages.registerCompletionItemProvider(lang, this)); } - this.context.subscriptions.push(workspace.onDidChangeConfiguration(() => { - if (this.languageRegisters.length !== this.config.resolver.resolverModeLanguages.length) { - this.logger.info('ResolverMode has changed, registering to new configuration languages'); - for (const register of this.languageRegisters) { - register.dispose(); - } - this.languageRegisters = []; - for (const lang of this.config.resolver.resolverModeLanguages) { - this.languageRegisters.push(languages.registerCompletionItemProvider(lang, this)); - } - } - })); - this.context.subscriptions.push( commands.registerCommand( 'typescriptHero.codeCompletion.executeIntellisenseItem', @@ -87,9 +71,6 @@ export class CodeCompletionExtension extends BaseExtension implements Completion * @memberof CodeCompletionExtension */ public dispose(): void { - for (const register of this.languageRegisters) { - register.dispose(); - } this.logger.info('Disposed'); } @@ -109,7 +90,14 @@ export class CodeCompletionExtension extends BaseExtension implements Completion token: CancellationToken, ): Promise { const index = this.indices.getIndexForFile(document.uri); - if (!index || !index.indexReady) { + 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 + ) { return null; } @@ -140,7 +128,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion index.declarationInfos, document.fileName, parsed.imports, - this.rootPath, + rootFolder.uri.fsPath, ) .filter(o => !parsed.declarations.some(d => d.name === o.declaration.name)) .filter(o => !parsed.usages.some(d => d === o.declaration.name)); @@ -157,7 +145,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion title: 'Execute intellisense insert', command: 'typescriptHero.codeCompletion.executeIntellisenseItem', }; - if (this.config.completionSortMode === 'bottom') { + if (config.codeCompletion.completionSortMode === 'bottom') { item.sortText = `9999-${declaration.declaration.name}`; } items.push(item); diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index 6d271c8..832138f 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -66,32 +66,32 @@ export class DeclarationIndexMapper { public getIndexForFile(fileUri: Uri): DeclarationIndex | undefined { const workspaceFolder = workspace.getWorkspaceFolder(fileUri); - if (!workspaceFolder || !this.indizes[workspaceFolder.uri.path]) { + if (!workspaceFolder || !this.indizes[workspaceFolder.uri.fsPath]) { return; } - return this.indizes[workspaceFolder.uri.path].index; + return this.indizes[workspaceFolder.uri.fsPath].index; } private workspaceChanged(event: WorkspaceFoldersChangeEvent): void { this.logger.info('Workspaces changed.', event); for (const add of event.added) { - if (this.indizes[add.uri.path]) { - this.logger.warning(`The workspace with the path ${add.uri.path} already exists. Skipping.`); + if (this.indizes[add.uri.fsPath]) { + this.logger.warning(`The workspace with the path ${add.uri.fsPath} already exists. Skipping.`); continue; } this.initializeIndex(add); } for (const remove of event.removed) { - this.indizes[remove.uri.path].index.reset(); - this.indizes[remove.uri.path].watcher.dispose(); - delete this.indizes[remove.uri.path]; + this.indizes[remove.uri.fsPath].index.reset(); + this.indizes[remove.uri.fsPath].watcher.dispose(); + delete this.indizes[remove.uri.fsPath]; } } private async initializeIndex(folder: WorkspaceFolder): Promise { - const index = new DeclarationIndex(this.parser, folder.uri.path); + const index = new DeclarationIndex(this.parser, folder.uri.fsPath); const files = await findFiles(this.config, folder); const watcher = workspace.createFileSystemWatcher( new RelativePattern( @@ -134,7 +134,7 @@ export class DeclarationIndexMapper { watcher.onDidDelete(uri => fileWatcherEvent('deleted', uri)); await index.buildIndex(files); - this.indizes[folder.uri.path] = { + this.indizes[folder.uri.fsPath] = { index, folder, watcher, From 87495c0ba5c9a6ea3c43cfab7c93b45b66466ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 08:52:56 +0200 Subject: [PATCH 19/40] change symbol structure extension --- .../DocumentSymbolStructureExtension.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/extension/extensions/DocumentSymbolStructureExtension.ts b/src/extension/extensions/DocumentSymbolStructureExtension.ts index 760b9ad..8332f6d 100644 --- a/src/extension/extensions/DocumentSymbolStructureExtension.ts +++ b/src/extension/extensions/DocumentSymbolStructureExtension.ts @@ -13,7 +13,7 @@ import { workspace, } from 'vscode'; -import { ExtensionConfig } from '../../common/config'; +import { ConfigFactory } from '../../common/factories'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { BaseStructureTreeItem } from '../provider-items/document-structure/BaseStructureTreeItem'; @@ -42,7 +42,7 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, - @inject(iocSymbols.configuration) private config: ExtensionConfig, + @inject(iocSymbols.configuration) private config: ConfigFactory, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, ) { super(context); @@ -85,15 +85,17 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T } public async getChildren(element?: BaseStructureTreeItem): Promise> { - if (!this.config.codeOutline.outlineEnabled) { - return [new DisabledStructureTreeItem()]; - } - if (!window.activeTextEditor) { return []; } - if (!this.config.resolver.resolverModeLanguages.some( + 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()]; From 09a1545243412f19a2d3047a7776f58aed98bac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 09:18:23 +0200 Subject: [PATCH 20/40] adding event for start / finish / err index --- .../extensions/ImportResolveExtension.ts | 93 +++---------------- .../utilities/DeclarationIndexMapper.ts | 46 +++++++-- 2 files changed, 54 insertions(+), 85 deletions(-) diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index 48fea7b..f280bb3 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -1,12 +1,10 @@ -import { existsSync } from 'fs'; +import { ConfigFactory } from '../../common/factories'; import { inject, injectable } from 'inversify'; -import { join } from 'path'; import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; -import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, Uri, window, workspace } from 'vscode'; +import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace } from 'vscode'; import { ExtensionConfig } from '../../common/config'; import { ResolverMode } from '../../common/enums'; -import { getDeclarationsFilteredByImports } from '../../common/helpers'; import { ResolveQuickPickItem } from '../../common/quick-pick-items'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; @@ -40,77 +38,9 @@ function compareIgnorePatterns(local: string[], config: string[]): boolean { return true; } -/** - * Search for typescript / typescript react files in the workspace and return the path to them. - * This is needed for the initial load of the index. - * - * @export - * @param {ExtensionConfig} config - * @returns {Promise} - */ -export async function findFiles(config: ExtensionConfig, rootPath: string): Promise { - const searches: PromiseLike[] = [ - workspace.findFiles( - `{${config.resolver.resolverModeFileGlobs.join(',')}}`, - '{**/node_modules/**,**/typings/**}', - ), - ]; - - // TODO: check the package json and index javascript file in node_modules (?) - - let globs: string[] = []; - let ignores = ['**/typings/**']; - const excludePatterns = config.resolver.ignorePatterns; - - if (rootPath && existsSync(join(rootPath, 'package.json'))) { - const packageJson = require(join(rootPath, 'package.json')); - if (packageJson['dependencies']) { - globs = globs.concat( - Object.keys(packageJson['dependencies']).filter(o => excludePatterns.indexOf(o) < 0) - .map(o => `**/node_modules/${o}/**/*.d.ts`), - ); - ignores = ignores.concat( - Object.keys(packageJson['dependencies']).filter(o => excludePatterns.indexOf(o) < 0) - .map(o => `**/node_modules/${o}/node_modules/**`), - ); - } - if (packageJson['devDependencies']) { - globs = globs.concat( - Object.keys(packageJson['devDependencies']).filter(o => excludePatterns.indexOf(o) < 0) - .map(o => `**/node_modules/${o}/**/*.d.ts`), - ); - ignores = ignores.concat( - Object.keys(packageJson['devDependencies']).filter(o => excludePatterns.indexOf(o) < 0) - .map(o => `**/node_modules/${o}/node_modules/**`), - ); - } - } else { - globs.push('**/node_modules/**/*.d.ts'); - } - searches.push( - workspace.findFiles(`{${globs.join(',')}}`, `{${ignores.join(',')}}`), - ); - - searches.push( - workspace.findFiles('**/typings/**/*.d.ts', '**/node_modules/**'), - ); - - let uris = await Promise.all(searches); - - uris = uris.map((o, idx) => idx === 0 ? - o.filter( - f => f.fsPath - .replace(rootPath || '', '') - .split(/\\|\//) - .every(p => excludePatterns.indexOf(p) < 0)) : - o, - ); - return uris.reduce((all, cur) => all.concat(cur), []).map(o => o.fsPath); -} - const resolverOk = 'TSH Resolver $(check)'; -// const resolverSyncing = 'TSH Resolver $(sync)'; -// const resolverErr = 'TSH Resolver $(flame)'; +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 @@ -130,10 +60,9 @@ export class ImportResolveExtension extends BaseExtension { constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, - @inject(iocSymbols.configuration) private config: ExtensionConfig, + @inject(iocSymbols.configuration) private config: ConfigFactory, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - @inject(iocSymbols.rootPath) private rootPath: string, ) { super(context); this.logger = loggerFactory('ImportResolveExtension'); @@ -151,9 +80,17 @@ export class ImportResolveExtension extends BaseExtension { this.context.subscriptions.push(this.statusBarItem); this.statusBarItem.text = resolverOk; - this.statusBarItem.tooltip = - `Click to manually reindex all files; Actual mode: ${ResolverMode[this.config.resolver.resolverMode]}`; + 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(); diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index 832138f..d44f32a 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -1,6 +1,8 @@ import { inject, injectable, postConstruct } from 'inversify'; import { DeclarationIndex, FileChanges, TypescriptParser } from 'typescript-parser'; import { + Event, + EventEmitter, ExtensionContext, FileSystemWatcher, RelativePattern, @@ -25,9 +27,18 @@ interface WorkspaceIndex { // TODO change settings to scoped settings // TODO move did change configuration to all indices // TODO error handling of each index +// TODO events for indexing part @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 logger: Logger; private indizes: { [uri: string]: WorkspaceIndex } = {}; @@ -37,6 +48,18 @@ export class DeclarationIndexMapper { @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.configuration) private config: ExtensionConfig, ) { + 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); + this.logger = loggerFactory('DeclarationIndexMapper'); } @@ -99,6 +122,13 @@ export class DeclarationIndexMapper { `{${this.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; @@ -133,12 +163,14 @@ export class DeclarationIndexMapper { watcher.onDidChange(uri => fileWatcherEvent('updated', uri)); watcher.onDidDelete(uri => fileWatcherEvent('deleted', uri)); - await index.buildIndex(files); - this.indizes[folder.uri.fsPath] = { - index, - folder, - watcher, - }; - this.logger.info(`Finished building index for workspace "${folder.name}".`); + try { + await index.buildIndex(files); + this.indizes[folder.uri.fsPath] = workspaceIndex; + this.logger.info(`Finished building index for workspace "${folder.name}".`); + this._onFinishIndexing.fire(workspaceIndex); + } catch (error) { + this.logger.error(`Error during build of index for workspace "${folder.name}"`, error); + this._onIndexingError.fire({ error, index: workspaceIndex }); + } } } From c3a437c4d9d0e610438732437843b6cf1e476abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 16:55:01 +0200 Subject: [PATCH 21/40] add new config to other ext --- .../extensions/ImportResolveExtension.ts | 67 ++++--------------- .../OrganizeImportsOnSaveExtension.ts | 7 +- .../utilities/DeclarationIndexMapper.ts | 25 +++++++ 3 files changed, 41 insertions(+), 58 deletions(-) diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index f280bb3..f906dd6 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -1,10 +1,8 @@ -import { ConfigFactory } from '../../common/factories'; import { inject, injectable } from 'inversify'; import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace } from 'vscode'; -import { ExtensionConfig } from '../../common/config'; -import { ResolverMode } from '../../common/enums'; +import { getDeclarationsFilteredByImports } from '../../common/helpers'; import { ResolveQuickPickItem } from '../../common/quick-pick-items'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; @@ -15,29 +13,6 @@ import { BaseExtension } from './BaseExtension'; type DeclarationsForImportOptions = { cursorSymbol: string, documentSource: string, documentPath: string }; type MissingDeclarationsForFileOptions = { documentSource: string, documentPath: string }; -/** - * Compares the ignorepatterns (if they have the same elements ignored). - * - * @param {string[]} local - * @param {string[]} config - * @returns {boolean} - */ -function compareIgnorePatterns(local: string[], config: string[]): boolean { - if (local.length !== config.length) { - return false; - } - const localSorted = local.sort(); - const configSorted = config.sort(); - - for (let x = 0; x < configSorted.length; x += 1) { - if (configSorted[x] !== localSorted[x]) { - return false; - } - } - - return true; -} - const resolverOk = 'TSH Resolver $(check)'; const resolverSyncing = 'TSH Resolver $(sync)'; const resolverErr = 'TSH Resolver $(flame)'; @@ -54,13 +29,10 @@ const resolverErr = 'TSH Resolver $(flame)'; export class ImportResolveExtension extends BaseExtension { private logger: Logger; private statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 4); - private ignorePatterns: string[]; - private actualMode: ResolverMode; constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, - @inject(iocSymbols.configuration) private config: ConfigFactory, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { @@ -74,9 +46,6 @@ export class ImportResolveExtension extends BaseExtension { * @memberof ImportResolveExtension */ public initialize(): void { - this.actualMode = this.config.resolver.resolverMode; - this.ignorePatterns = this.config.resolver.ignorePatterns; - this.context.subscriptions.push(this.statusBarItem); this.statusBarItem.text = resolverOk; @@ -95,25 +64,6 @@ export class ImportResolveExtension extends BaseExtension { this.commandRegistrations(); - this.context.subscriptions.push(workspace.onDidChangeConfiguration(() => { - let build = false; - if (!compareIgnorePatterns(this.ignorePatterns, this.config.resolver.ignorePatterns)) { - this.logger.info('The typescriptHero.resolver.ignorePatterns setting was modified, reload the index.'); - this.ignorePatterns = this.config.resolver.ignorePatterns; - build = true; - } - if (this.actualMode !== this.config.resolver.resolverMode) { - this.logger.info('The typescriptHero.resolver.resolverMode setting was modified, reload the index.'); - this.statusBarItem.tooltip = - `Click to manually reindex all files; Actual mode: ${ResolverMode[this.config.resolver.resolverMode]}`; - this.actualMode = this.config.resolver.resolverMode; - build = true; - } - if (build) { - this.indices.rebuildAll(); - } - })); - this.logger.info('Initialized'); } @@ -330,17 +280,21 @@ export class ImportResolveExtension extends BaseExtension { if (!window.activeTextEditor) { return []; } + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); - if (!index || !index.indexReady) { + const rootFolder = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri); + + if (!index || !index.indexReady || !rootFolder) { return []; } + const parsedSource = await this.parser.parseSource(documentSource); const activeDocumentDeclarations = parsedSource.declarations.map(o => o.name); const declarations = getDeclarationsFilteredByImports( index.declarationInfos, documentPath, parsedSource.imports, - this.rootPath, + rootFolder.uri.fsPath, ).filter(o => o.declaration.name.startsWith(cursorSymbol)); return [ @@ -365,8 +319,11 @@ export class ImportResolveExtension extends BaseExtension { if (!window.activeTextEditor) { return []; } + const index = this.indices.getIndexForFile(window.activeTextEditor.document.uri); - if (!index || !index.indexReady) { + const rootFolder = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri); + + if (!index || !index.indexReady || !rootFolder) { return []; } @@ -376,7 +333,7 @@ export class ImportResolveExtension extends BaseExtension { index.declarationInfos, documentPath, parsedDocument.imports, - this.rootPath, + rootFolder.uri.fsPath, ); for (const usage of parsedDocument.nonLocalUsages) { diff --git a/src/extension/extensions/OrganizeImportsOnSaveExtension.ts b/src/extension/extensions/OrganizeImportsOnSaveExtension.ts index bdf1a54..c13526f 100644 --- a/src/extension/extensions/OrganizeImportsOnSaveExtension.ts +++ b/src/extension/extensions/OrganizeImportsOnSaveExtension.ts @@ -1,7 +1,7 @@ import { inject, injectable } from 'inversify'; import { ExtensionContext, workspace } from 'vscode'; -import { ExtensionConfig } from '../../common/config'; +import { ConfigFactory } from '../../common/factories'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers'; @@ -27,7 +27,7 @@ export class OrganizeImportsOnSaveExtension extends BaseExtension { constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, - @inject(iocSymbols.configuration) private config: ExtensionConfig, + @inject(iocSymbols.configuration) private config: ConfigFactory, ) { super(context); this.logger = loggerFactory('OrganizeImportsOnSaveExtension'); @@ -40,7 +40,8 @@ export class OrganizeImportsOnSaveExtension extends BaseExtension { */ public initialize(): void { this.context.subscriptions.push(workspace.onWillSaveTextDocument((event) => { - if (!this.config.resolver.organizeOnSave) { + const config = this.config(event.document.uri); + if (!config.resolver.organizeOnSave) { this.logger.info('Organize on save is deactivated through config.'); return; } diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index d44f32a..9363446 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -29,6 +29,31 @@ interface WorkspaceIndex { // TODO error handling of each index // TODO events for indexing part +// TODO: update index on change of configs +// this.context.subscriptions.push(workspace.onDidChangeConfiguration(() => { +// if (!window.activeTextEditor) { +// return; +// } +// let build = false; +// const config = this.config(window.activeTextEditor.document.uri); + +// if (!compareIgnorePatterns(this.ignorePatterns, config.resolver.ignorePatterns)) { +// this.logger.info('The typescriptHero.resolver.ignorePatterns setting was modified, reload the index.'); +// this.ignorePatterns = config.resolver.ignorePatterns; +// build = true; +// } +// if (this.actualMode !== config.resolver.resolverMode) { +// this.logger.info('The typescriptHero.resolver.resolverMode setting was modified, reload the index.'); +// this.statusBarItem.tooltip = +// `Click to manually reindex all files; Actual mode: ${ResolverMode[config.resolver.resolverMode]}`; +// this.actualMode = config.resolver.resolverMode; +// build = true; +// } +// if (build) { +// this.indices.rebuildAll(); +// } +// })); + @injectable() export class DeclarationIndexMapper { public readonly onStartIndexing: Event; From e91bb5f7a2e99306d30c1d8bea5e5d31ee62937e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:10:00 +0200 Subject: [PATCH 22/40] update all config related files (without tests) --- src/extension/IoC.ts | 2 +- src/extension/IoCSymbols.ts | 1 - .../MissingImplementationInClassCreator.ts | 9 ++-- src/extension/managers/ClassManager.ts | 53 +++++++++---------- src/extension/managers/ImportManager.ts | 36 +++++++------ .../utilities/DeclarationIndexMapper.ts | 9 ++-- 6 files changed, 56 insertions(+), 54 deletions(-) diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 10d3813..fd4545f 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -55,7 +55,7 @@ container .toFactory((context: interfaces.Context) => { return (prefix?: string) => { const extContext = context.container.get(iocSymbols.extensionContext); - const config = context.container.get(iocSymbols.configuration); + const config = context.container.get(iocSymbols.configuration)(); return new VscodeLogger(extContext, config, prefix); }; diff --git a/src/extension/IoCSymbols.ts b/src/extension/IoCSymbols.ts index a193354..1b80abd 100644 --- a/src/extension/IoCSymbols.ts +++ b/src/extension/IoCSymbols.ts @@ -11,5 +11,4 @@ export const iocSymbols = { declarationIndex: Symbol('declarationIndex'), declarationIndexMapper: Symbol('declarationIndexMapper'), typescriptParser: Symbol('typescriptParser'), - rootPath: Symbol('rootPath'), }; diff --git a/src/extension/code-actions/MissingImplementationInClassCreator.ts b/src/extension/code-actions/MissingImplementationInClassCreator.ts index 16a1ad3..251f058 100644 --- a/src/extension/code-actions/MissingImplementationInClassCreator.ts +++ b/src/extension/code-actions/MissingImplementationInClassCreator.ts @@ -1,6 +1,6 @@ import { inject, injectable } from 'inversify'; import { ClassLikeDeclaration, GenericDeclaration, NamedImport, TypescriptParser } from 'typescript-parser'; -import { Command, Diagnostic, TextDocument } from 'vscode'; +import { Command, Diagnostic, TextDocument, workspace } from 'vscode'; import { getAbsolutLibraryName } from '../../common/helpers'; import { iocSymbols } from '../IoCSymbols'; @@ -20,7 +20,6 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { constructor( @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, - @inject(iocSymbols.rootPath) private rootPath: string, ) { super(); } @@ -53,7 +52,9 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { /non-abstract class ['"](.*)['"].*implement inherited.*from class ['"](.*)['"]\./ig.exec(diagnostic.message); const index = this.indices.getIndexForFile(document.uri); - if (!match || !index) { + const rootFolder = workspace.getWorkspaceFolder(document.uri); + + if (!match || !index || !rootFolder) { return commands; } @@ -74,7 +75,7 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { const declaration = (parsedDocument.declarations.find(o => o.name === specifier) || (index.declarationInfos.find( o => o.declaration.name === specifier && - o.from === getAbsolutLibraryName(alreadyImported!.libraryName, document.fileName, this.rootPath), + 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)) { diff --git a/src/extension/managers/ClassManager.ts b/src/extension/managers/ClassManager.ts index 741faf1..7b77859 100644 --- a/src/extension/managers/ClassManager.ts +++ b/src/extension/managers/ClassManager.ts @@ -11,7 +11,6 @@ import { } from 'typescript-parser'; import { Position, Range, TextDocument, TextEdit, workspace, WorkspaceEdit } from 'vscode'; -import { ExtensionConfig } from '../../common/config'; import { ClassNotFoundError, MethodDuplicated, @@ -29,7 +28,7 @@ type VisibleObject = { visibility?: DeclarationVisibility }; /** * Sortfunction for changeable objects. Does sort the objects by visibility. - * + * * @param {Changeable} o1 * @param {Changeable} o2 * @returns {number} @@ -54,7 +53,7 @@ function sortByVisibility(o1: Changeable, o2: Changeable(iocSymbols.generatorFactory)(); } - private static get config(): ExtensionConfig { - return Container.get(iocSymbols.configuration); - } - private ctor: Changeable; private properties: Changeable[] = []; private methods: Changeable[] = []; @@ -90,12 +85,12 @@ export class ClassManager implements ObjectManager { * 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 { @@ -112,10 +107,10 @@ export class ClassManager implements ObjectManager { /** * 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 { @@ -124,12 +119,12 @@ export class ClassManager implements ObjectManager { /** * 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( @@ -158,10 +153,10 @@ export class ClassManager implements ObjectManager { /** * Remove (aka set isDeleted) a property from the virtual class. - * + * * @param {string} name * @returns {this} - * + * * @memberof ClassManager */ public removeProperty(name: string): this { @@ -181,10 +176,10 @@ export class ClassManager implements ObjectManager { /** * 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 { @@ -193,13 +188,13 @@ export class ClassManager implements ObjectManager { /** * 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( @@ -230,10 +225,10 @@ export class ClassManager implements ObjectManager { /** * Removes a method from the virtual class. - * + * * @param {string} name * @returns {this} - * + * * @memberof ClassManager */ public removeMethod(name: string): this { @@ -257,9 +252,9 @@ export class ClassManager implements ObjectManager { * - Delete properties * - Update changed properties (still TODO) * - Insert new properties - * + * * @returns {Promise} - * + * * @memberof ClassManager */ public async commit(): Promise { @@ -276,11 +271,11 @@ export class ClassManager implements ObjectManager { /** * 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 { @@ -293,10 +288,10 @@ export class ClassManager implements ObjectManager { /** * Calculates TextEdits for properties. - * + * * @private * @returns {TextEdit[]} - * + * * @memberof ClassManager */ private calculatePropertyEdits(): TextEdit[] { @@ -338,10 +333,10 @@ export class ClassManager implements ObjectManager { /** * Calculates TextEdits for methods. - * + * * @private * @returns {TextEdit[]} - * + * * @memberof ClassManager */ private calculateMethodEdits(): TextEdit[] { diff --git a/src/extension/managers/ImportManager.ts b/src/extension/managers/ImportManager.ts index 2bc5f0c..9562ba7 100644 --- a/src/extension/managers/ImportManager.ts +++ b/src/extension/managers/ImportManager.ts @@ -17,6 +17,7 @@ import { import { InputBoxOptions, Range, TextDocument, TextEdit, window, workspace, WorkspaceEdit } from 'vscode'; import { ExtensionConfig } from '../../common/config'; +import { ConfigFactory } from '../../common/factories'; import { getAbsolutLibraryName, getDeclarationsFilteredByImports, @@ -55,23 +56,28 @@ export class ImportManager implements ObjectManager { return Container.get(iocSymbols.typescriptParser); } - private static get config(): ExtensionConfig { - return Container.get(iocSymbols.configuration); + private static get config(): ConfigFactory { + return Container.get(iocSymbols.configuration); } private static get generator(): TypescriptCodeGenerator { return Container.get<() => TypescriptCodeGenerator>(iocSymbols.generatorFactory)(); } - private static get rootPath(): string { - return Container.get(iocSymbols.rootPath); - } - private importGroups: ImportGroup[]; private imports: Import[] = []; private userImportDecisions: { [usage: string]: DeclarationInfo[] }[] = []; private organize: boolean; + private get config(): ExtensionConfig { + return ImportManager.config(this.document.uri); + } + + private get rootPath(): string | undefined { + const rootFolder = workspace.getWorkspaceFolder(this.document.uri); + return rootFolder ? rootFolder.uri.fsPath : undefined; + } + /** * Document resource for this controller. Contains the parsed document. * @@ -113,7 +119,7 @@ export class ImportManager implements ObjectManager { */ public reset(): void { this.imports = this._parsedDocument.imports.map(o => o.clone()); - this.importGroups = ImportManager.config.resolver.importGroups; + this.importGroups = this.config.resolver.importGroups; this.addImportsToGroups(this.imports); } @@ -133,7 +139,7 @@ export class ImportManager implements ObjectManager { o => declarationInfo.from === getAbsolutLibraryName( o.libraryName, this.document.fileName, - ImportManager.rootPath, + this.rootPath, ) && o instanceof NamedImport, ) as NamedImport; @@ -149,7 +155,7 @@ export class ImportManager implements ObjectManager { let imp: Import = new NamedImport(getRelativeLibraryName( declarationInfo.from, this.document.fileName, - ImportManager.rootPath, + this.rootPath, )); if (declarationInfo.declaration instanceof ModuleDeclaration) { @@ -183,7 +189,7 @@ export class ImportManager implements ObjectManager { index.declarationInfos, this.document.fileName, this.imports, - ImportManager.rootPath, + this.rootPath, ); for (const usage of this._parsedDocument.nonLocalUsages) { @@ -213,11 +219,11 @@ export class ImportManager implements ObjectManager { this.organize = true; let keep: Import[] = []; - if (ImportManager.config.resolver.disableImportRemovalOnOrganize) { + if (this.config.resolver.disableImportRemovalOnOrganize) { keep = this.imports; } else { for (const actImport of this.imports) { - if (ImportManager.config.resolver.ignoreImportsForOrganize.indexOf(actImport.libraryName) >= 0) { + if (this.config.resolver.ignoreImportsForOrganize.indexOf(actImport.libraryName) >= 0) { keep.push(actImport); continue; } @@ -241,7 +247,7 @@ export class ImportManager implements ObjectManager { } } - if (!ImportManager.config.resolver.disableImportSorting) { + if (!this.config.resolver.disableImportSorting) { keep = [ ...keep.filter(o => o instanceof StringImport).sort(importSort), ...keep.filter(o => !(o instanceof StringImport)).sort(importSort), @@ -432,7 +438,7 @@ export class ImportManager implements ObjectManager { const specifiers = getSpecifiers(); if ( specifiers.filter(o => o === imp.defaultAlias).length > 1 && - ImportManager.config.resolver.promptForSpecifiers + this.config.resolver.promptForSpecifiers ) { imp.defaultAlias = await this.getDefaultIdentifier(imp.defaultAlias); } @@ -442,7 +448,7 @@ export class ImportManager implements ObjectManager { const specifiers = getSpecifiers(); if ( specifiers.filter(o => o === (spec.alias || spec.specifier)).length > 1 && - ImportManager.config.resolver.promptForSpecifiers + this.config.resolver.promptForSpecifiers ) { spec.alias = await this.getSpecifierAlias(spec.alias || spec.specifier); } diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index 9363446..190065d 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -12,7 +12,7 @@ import { WorkspaceFoldersChangeEvent, } from 'vscode'; -import { ExtensionConfig } from '../../common/config'; +import { ConfigFactory } from '../../common/factories'; import { findFiles } from '../../common/helpers'; import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../../extension/IoCSymbols'; @@ -71,7 +71,7 @@ export class DeclarationIndexMapper { @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, @inject(iocSymbols.extensionContext) private context: ExtensionContext, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, - @inject(iocSymbols.configuration) private config: ExtensionConfig, + @inject(iocSymbols.configuration) private config: ConfigFactory, ) { this._onFinishIndexing = new EventEmitter(); this._onStartIndexing = new EventEmitter(); @@ -140,11 +140,12 @@ export class DeclarationIndexMapper { private async initializeIndex(folder: WorkspaceFolder): Promise { const index = new DeclarationIndex(this.parser, folder.uri.fsPath); - const files = await findFiles(this.config, folder); + const config = this.config(folder.uri); + const files = await findFiles(config, folder); const watcher = workspace.createFileSystemWatcher( new RelativePattern( folder, - `{${this.config.resolver.resolverModeFileGlobs.join(',')},**/package.json,**/typings.json}`, + `{${config.resolver.resolverModeFileGlobs.join(',')},**/package.json,**/typings.json}`, ), ); const workspaceIndex = { From 57fa8c189679e0c2e6773c221c6dfb4becc13492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:13:54 +0200 Subject: [PATCH 23/40] adding multi-root file --- test/multi-root.code-workspace | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/multi-root.code-workspace diff --git a/test/multi-root.code-workspace b/test/multi-root.code-workspace new file mode 100644 index 0000000..0a9d174 --- /dev/null +++ b/test/multi-root.code-workspace @@ -0,0 +1,14 @@ +{ + "folders": [ + { + "path": "_workspace" + }, + { + "path": "_workspace_2" + }, + { + "path": "_workspace/server" + } + ], + "settings": {} +} From f38ca6c6b0464a41a3a1df431ca31f729ba4eea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:14:38 +0200 Subject: [PATCH 24/40] launch config --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 829b9d1..17854e9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,7 +22,7 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": [ - "${workspaceRoot}/test/_workspace", + "${workspaceRoot}/test/multi-root.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}" ], "stopOnEntry": false, From e4e2aa1477c44ac5815470ac6f0b9895e75ce199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:17:56 +0200 Subject: [PATCH 25/40] add default settings for testing --- test/multi-root.code-workspace | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/multi-root.code-workspace b/test/multi-root.code-workspace index 0a9d174..517fdf6 100644 --- a/test/multi-root.code-workspace +++ b/test/multi-root.code-workspace @@ -10,5 +10,11 @@ "path": "_workspace/server" } ], - "settings": {} + "settings": { + "typescriptHero.verbosity": "All", + "typescriptHero.codeOutline.enabled": true, + "typescriptHero.resolver.organizeOnSave": false, + "typescriptHero.resolver.promptForSpecifiers": true, + "editor.formatOnSave": true + } } From cd355290ab809cba84194519713978d3d55dc43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:22:51 +0200 Subject: [PATCH 26/40] adding workspace test files --- test/_workspace_2/file1.ts | 0 test/_workspace_2/file2.ts | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 test/_workspace_2/file1.ts create mode 100644 test/_workspace_2/file2.ts diff --git a/test/_workspace_2/file1.ts b/test/_workspace_2/file1.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/_workspace_2/file2.ts b/test/_workspace_2/file2.ts new file mode 100644 index 0000000..5ef1a5e --- /dev/null +++ b/test/_workspace_2/file2.ts @@ -0,0 +1,3 @@ +export class ClassInFile2 { } + +export default class DefaultClassInFile2 { } From 75aadd0fdf5ebfc5ed15f7bc3f8dcc9b24d51440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:24:47 +0200 Subject: [PATCH 27/40] change base config --- config/tsconfig.base.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/tsconfig.base.json b/config/tsconfig.base.json index 8940570..3287faf 100644 --- a/config/tsconfig.base.json +++ b/config/tsconfig.base.json @@ -21,6 +21,7 @@ "../test/**/*" ], "exclude": [ - "../test/_workspace" + "../test/_workspace", + "../test/_workspace_2" ] } From 847fff4c095e7a21470db586704a15545b05bf3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:27:16 +0200 Subject: [PATCH 28/40] settings / comments --- src/extension/utilities/DeclarationIndexMapper.ts | 5 +---- test/multi-root.code-workspace | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index 190065d..ec11c80 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -24,12 +24,9 @@ interface WorkspaceIndex { } // TODO documentation -// TODO change settings to scoped settings // TODO move did change configuration to all indices -// TODO error handling of each index -// TODO events for indexing part - // TODO: update index on change of configs + // this.context.subscriptions.push(workspace.onDidChangeConfiguration(() => { // if (!window.activeTextEditor) { // return; diff --git a/test/multi-root.code-workspace b/test/multi-root.code-workspace index 517fdf6..7cc4784 100644 --- a/test/multi-root.code-workspace +++ b/test/multi-root.code-workspace @@ -11,7 +11,7 @@ } ], "settings": { - "typescriptHero.verbosity": "All", + "typescriptHero.verbosity": "Warnings", "typescriptHero.codeOutline.enabled": true, "typescriptHero.resolver.organizeOnSave": false, "typescriptHero.resolver.promptForSpecifiers": true, From 1dbe2298cc50662e5355d47e05008b451cdc20a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 18 Oct 2017 17:42:39 +0200 Subject: [PATCH 29/40] move test files --- src/extension/IoCSymbols.ts | 1 - test/_workspace_2/file1.ts | 2 ++ .../common/helpers/ImportHelpers.test.ts | 0 .../extensions/CodeActionExtension.test.ts | 25 +++++++++++-------- .../CodeCompletionExtension.test.ts | 0 .../DocumentSymbolStructureExtension.test.ts | 0 .../extensions/ImportResolveExtension.test.ts | 0 .../OrganizeImportsOnSaveExtension.test.ts | 0 .../ImportGroupSettingParser.test.ts | 0 .../KeywordImportGroup.test.ts | 0 .../import-grouping/RegexImportGroup.test.ts | 0 .../import-grouping/RemainImportGroup.test.ts | 0 .../extension/managers/ClassManager.test.ts | 0 .../extension/managers/ImportManager.test.ts | 0 test/{ => single-workspace-tests}/index.ts | 1 - 15 files changed, 17 insertions(+), 12 deletions(-) rename test/{ => single-workspace-tests}/common/helpers/ImportHelpers.test.ts (100%) rename test/{ => single-workspace-tests}/extension/extensions/CodeActionExtension.test.ts (95%) rename test/{ => single-workspace-tests}/extension/extensions/CodeCompletionExtension.test.ts (100%) rename test/{ => single-workspace-tests}/extension/extensions/DocumentSymbolStructureExtension.test.ts (100%) rename test/{ => single-workspace-tests}/extension/extensions/ImportResolveExtension.test.ts (100%) rename test/{ => single-workspace-tests}/extension/extensions/OrganizeImportsOnSaveExtension.test.ts (100%) rename test/{ => single-workspace-tests}/extension/import-grouping/ImportGroupSettingParser.test.ts (100%) rename test/{ => single-workspace-tests}/extension/import-grouping/KeywordImportGroup.test.ts (100%) rename test/{ => single-workspace-tests}/extension/import-grouping/RegexImportGroup.test.ts (100%) rename test/{ => single-workspace-tests}/extension/import-grouping/RemainImportGroup.test.ts (100%) rename test/{ => single-workspace-tests}/extension/managers/ClassManager.test.ts (100%) rename test/{ => single-workspace-tests}/extension/managers/ImportManager.test.ts (100%) rename test/{ => single-workspace-tests}/index.ts (99%) diff --git a/src/extension/IoCSymbols.ts b/src/extension/IoCSymbols.ts index 1b80abd..5fc8ef5 100644 --- a/src/extension/IoCSymbols.ts +++ b/src/extension/IoCSymbols.ts @@ -8,7 +8,6 @@ export const iocSymbols = { loggerFactory: Symbol('loggerFactory'), generatorFactory: Symbol('generatorFactory'), codeActionCreators: Symbol('codeActionCreators'), - declarationIndex: Symbol('declarationIndex'), declarationIndexMapper: Symbol('declarationIndexMapper'), typescriptParser: Symbol('typescriptParser'), }; diff --git a/test/_workspace_2/file1.ts b/test/_workspace_2/file1.ts index e69de29..8879bf0 100644 --- a/test/_workspace_2/file1.ts +++ b/test/_workspace_2/file1.ts @@ -0,0 +1,2 @@ +import { ClassInFile2 } from './file2'; +ClassInFile2 diff --git a/test/common/helpers/ImportHelpers.test.ts b/test/single-workspace-tests/common/helpers/ImportHelpers.test.ts similarity index 100% rename from test/common/helpers/ImportHelpers.test.ts rename to test/single-workspace-tests/common/helpers/ImportHelpers.test.ts diff --git a/test/extension/extensions/CodeActionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts similarity index 95% rename from test/extension/extensions/CodeActionExtension.test.ts rename to test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts index f9d0acc..cb9aad8 100644 --- a/test/extension/extensions/CodeActionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts @@ -25,16 +25,21 @@ class SpyCodeAction implements CodeAction { } } -const rootPath = Container.get(iocSymbols.rootPath); - describe('CodeActionExtension', () => { let extension: any; + let rootPath: string; before(async () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); const parser = Container.get(iocSymbols.typescriptParser); + let document: TextDocument; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + }); const index = Container.get(iocSymbols.declarationIndex); await index.buildIndex( @@ -187,7 +192,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `non-abstract class 'Foobar' implement inherited from class 'CodeFixImplementAbstract'.`, + `non-abstract class 'Foobar' implement inherited from class 'CodeFixImplementAbstract'.`, }, ], }, @@ -254,7 +259,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: `non-abstract class 'Foobar' ` + - `implement inherited from class 'GenericAbstractClass'.`, + `implement inherited from class 'GenericAbstractClass'.`, }, ], }, @@ -310,7 +315,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: `non-abstract class 'AbstractImplement' ` + - `implement inherited from class 'CodeFixImplementAbstract'.`, + `implement inherited from class 'CodeFixImplementAbstract'.`, }, ], }, @@ -358,8 +363,8 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `non-abstract class 'InternalAbstractImplement' ` + - `implement inherited from class 'InternalAbstract'.`, + `non-abstract class 'InternalAbstractImplement' ` + + `implement inherited from class 'InternalAbstract'.`, }, ], }, @@ -381,7 +386,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `class 'ImplementGenericInterface' incorrectly implements 'GenericInterface'.`, + `class 'ImplementGenericInterface' incorrectly implements 'GenericInterface'.`, }, ], }, @@ -405,8 +410,8 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `non-abstract class 'ImplementGenericAbstract' ` + - `implement inherited from class 'GenericAbstractClass'.`, + `non-abstract class 'ImplementGenericAbstract' ` + + `implement inherited from class 'GenericAbstractClass'.`, }, ], }, diff --git a/test/extension/extensions/CodeCompletionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts similarity index 100% rename from test/extension/extensions/CodeCompletionExtension.test.ts rename to test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts diff --git a/test/extension/extensions/DocumentSymbolStructureExtension.test.ts b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts similarity index 100% rename from test/extension/extensions/DocumentSymbolStructureExtension.test.ts rename to test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts diff --git a/test/extension/extensions/ImportResolveExtension.test.ts b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts similarity index 100% rename from test/extension/extensions/ImportResolveExtension.test.ts rename to test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts diff --git a/test/extension/extensions/OrganizeImportsOnSaveExtension.test.ts b/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts similarity index 100% rename from test/extension/extensions/OrganizeImportsOnSaveExtension.test.ts rename to test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts diff --git a/test/extension/import-grouping/ImportGroupSettingParser.test.ts b/test/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts similarity index 100% rename from test/extension/import-grouping/ImportGroupSettingParser.test.ts rename to test/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts diff --git a/test/extension/import-grouping/KeywordImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts similarity index 100% rename from test/extension/import-grouping/KeywordImportGroup.test.ts rename to test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts diff --git a/test/extension/import-grouping/RegexImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts similarity index 100% rename from test/extension/import-grouping/RegexImportGroup.test.ts rename to test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts diff --git a/test/extension/import-grouping/RemainImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts similarity index 100% rename from test/extension/import-grouping/RemainImportGroup.test.ts rename to test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts diff --git a/test/extension/managers/ClassManager.test.ts b/test/single-workspace-tests/extension/managers/ClassManager.test.ts similarity index 100% rename from test/extension/managers/ClassManager.test.ts rename to test/single-workspace-tests/extension/managers/ClassManager.test.ts diff --git a/test/extension/managers/ImportManager.test.ts b/test/single-workspace-tests/extension/managers/ImportManager.test.ts similarity index 100% rename from test/extension/managers/ImportManager.test.ts rename to test/single-workspace-tests/extension/managers/ImportManager.test.ts diff --git a/test/index.ts b/test/single-workspace-tests/index.ts similarity index 99% rename from test/index.ts rename to test/single-workspace-tests/index.ts index 31f24fd..061d889 100644 --- a/test/index.ts +++ b/test/single-workspace-tests/index.ts @@ -19,7 +19,6 @@ import { iocSymbols } from '../src/extension/IoCSymbols'; // 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; From 716465f9bfcacde810164249082d556c8f287b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Mon, 23 Oct 2017 09:41:50 +0200 Subject: [PATCH 30/40] change vars --- .travis.yml | 10 +++------- package.json | 10 ++++++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index dfe5e6d..2c4c7e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,6 @@ node_js: notifications: email: false -env: - global: - - CODE_TESTS_WORKSPACE=$TRAVIS_BUILD_DIR/test/_workspace - os: - linux @@ -32,8 +28,8 @@ addons: before_install: - if [ $TRAVIS_OS_NAME == "linux" ]; then export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0; - sh -e /etc/init.d/xvfb start; - sleep 3; + sh -e /etc/init.d/xvfb start; + sleep 3; fi - rvm get stable - rvm install 2.4 @@ -42,7 +38,7 @@ before_install: install: - yarn install - + before_script: - greenkeeper-lockfile-update - yarn run build diff --git a/package.json b/package.json index 7f06ee9..9424dea 100644 --- a/package.json +++ b/package.json @@ -80,13 +80,15 @@ "predevelop": "del-cli ./out", "develop": "tsc", "postinstall": "test -f ./node_modules/vscode/bin/install && node ./node_modules/vscode/bin/install || echo 'vscode/bin/install not found'", - "pretest": "del-cli ./out && tsc -p ./config/tsconfig.test.json && yarn run lint", - "test": "node ./node_modules/vscode/bin/test", "lint": "tslint -c tslint.json --project ./config/tsconfig.build.json", + "pretest": "del-cli ./out && tsc -p ./config/tsconfig.test.json && yarn lint", + "test": "yarn test:single-workspace", + "test:single-workspace": "CODE_TESTS_WORKSPACE=./test/_workspace CODE_TESTS_PATH=./out/test/single-workspace-tests node ./node_modules/vscode/bin/test", + "test:multi-workspace": "CODE_TESTS_WORKSPACE=./test/multi-root.code-workspace CODE_TESTS_PATH=./out/test/multi-root-workspace-tests node ./node_modules/vscode/bin/test", "build": "del-cli ./out && tsc -p ./config/tsconfig.build.json", - "package": "yarn run build && del-cli './*.vsix' && vsce package", + "package": "yarn build && del-cli './*.vsix' && vsce package", "semantic-release-pre": "semantic-release pre", - "semantic-release": "yarn run semantic-release-pre && vsce package && vsce publish -p $VSCE_TOKEN && yarn install && semantic-release post" + "semantic-release": "yarn semantic-release-pre && vsce package && vsce publish -p $VSCE_TOKEN && yarn install && semantic-release post" }, "devDependencies": { "@types/chai": "^4.0.4", From 6be37c29553dba5d24c4417bd8d22f32fb1e50a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Mon, 23 Oct 2017 09:43:27 +0200 Subject: [PATCH 31/40] add config for multi root launch --- .vscode/launch.json | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 17854e9..1e50969 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -32,14 +32,30 @@ ] }, { - "name": "Launch Tests", + "name": "Launch Tests (single Workspace)", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", "args": [ "${workspaceRoot}/test/_workspace", "--extensionDevelopmentPath=${workspaceRoot}", - "--extensionTestsPath=${workspaceRoot}/out/test" + "--extensionTestsPath=${workspaceRoot}/out/test/single-workspace-tests" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/out/test/**/*.js" + ] + }, + { + "name": "Launch Tests (multi-root Workspace)", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceRoot}/test/multi-root.code-workspace", + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/multi-root-workspace-tests" ], "stopOnEntry": false, "sourceMaps": true, From 669f920bc63389f58ce020548f79d1e7e7da7511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Tue, 24 Oct 2017 09:07:03 +0200 Subject: [PATCH 32/40] fixing tests (basic) --- .../common/helpers/ImportHelpers.test.ts | 2 +- .../import-grouping/ImportGroupSettingParser.test.ts | 5 +++-- test/single-workspace-tests/index.ts | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/single-workspace-tests/common/helpers/ImportHelpers.test.ts b/test/single-workspace-tests/common/helpers/ImportHelpers.test.ts index 9adafd5..781d69a 100644 --- a/test/single-workspace-tests/common/helpers/ImportHelpers.test.ts +++ b/test/single-workspace-tests/common/helpers/ImportHelpers.test.ts @@ -1,6 +1,6 @@ import * as chai from 'chai'; -import { getImportInsertPosition } from '../../../src/common/helpers'; +import { getImportInsertPosition } from '../../../../src/common/helpers'; chai.should(); diff --git a/test/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts b/test/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts index f5148ee..2f981c3 100644 --- a/test/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/ImportGroupSettingParser.test.ts @@ -1,11 +1,12 @@ +import * as chai from 'chai'; + import { ImportGroupIdentifierInvalidError, ImportGroupKeyword, ImportGroupSettingParser, KeywordImportGroup, RegexImportGroup, -} from '../../../src/extension/import-grouping'; -import * as chai from 'chai'; +} from '../../../../src/extension/import-grouping'; chai.should(); diff --git a/test/single-workspace-tests/index.ts b/test/single-workspace-tests/index.ts index 061d889..9956ef9 100644 --- a/test/single-workspace-tests/index.ts +++ b/test/single-workspace-tests/index.ts @@ -2,8 +2,8 @@ import 'reflect-metadata'; import { ExtensionContext, Memento } from 'vscode'; -import { Container } from '../src/extension/IoC'; -import { iocSymbols } from '../src/extension/IoCSymbols'; +import { Container } from '../../src/extension/IoC'; +import { iocSymbols } from '../../src/extension/IoCSymbols'; // tslint:disable From 404f95c104c8cb32a5adec759c0a14f250e2ba0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 25 Oct 2017 12:03:22 +0200 Subject: [PATCH 33/40] try fix test --- .../extensions/CodeActionExtension.test.ts | 42 +++++++++---------- .../CodeCompletionExtension.test.ts | 12 +++--- .../DocumentSymbolStructureExtension.test.ts | 24 ++++++----- .../extensions/ImportResolveExtension.test.ts | 20 ++++----- .../OrganizeImportsOnSaveExtension.test.ts | 8 ++-- .../KeywordImportGroup.test.ts | 12 +++--- .../import-grouping/RegexImportGroup.test.ts | 12 +++--- .../import-grouping/RemainImportGroup.test.ts | 12 +++--- .../extension/managers/ClassManager.test.ts | 12 +++--- .../extension/managers/ImportManager.test.ts | 12 +++--- 10 files changed, 84 insertions(+), 82 deletions(-) diff --git a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts index cb9aad8..f04b5b0 100644 --- a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts @@ -4,15 +4,17 @@ import * as sinon from 'sinon'; import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, Position, Range, TextDocument, window, workspace } from 'vscode'; -import { LoggerFactory } from '../../../src/common/utilities'; -import { AddImportCodeAction, CodeAction, ImplementPolymorphElements } from '../../../src/extension/code-actions/CodeAction'; +import { ConfigFactory } from '../../../../src/common/factories'; +import { LoggerFactory } from '../../../../src/common/utilities'; +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'; +} 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'; chai.should(); @@ -25,23 +27,19 @@ class SpyCodeAction implements CodeAction { } } -describe('CodeActionExtension', () => { +describe.only('CodeActionExtension', () => { + const rootPath = workspace.workspaceFolders![0].uri.fsPath; let extension: any; - let rootPath: string; before(async () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); const parser = Container.get(iocSymbols.typescriptParser); - let document: TextDocument; - - before(async () => { - document = await workspace.openTextDocument(file); - await window.showTextDocument(document); - }); + const config = Container.get(iocSymbols.configuration); + const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - const index = Container.get(iocSymbols.declarationIndex); + const index = new DeclarationIndex(parser, rootPath); await index.buildIndex( [ join( @@ -63,12 +61,14 @@ describe('CodeActionExtension', () => { ], ); + fakeMapper.getIndexForFile = sinon.spy(() => index); + const creators = [ - new MissingImportCreator(index as any), - new MissingImplementationInClassCreator(parser, index as any, rootPath), + new MissingImportCreator(fakeMapper), + new MissingImplementationInClassCreator(parser, fakeMapper), ]; - extension = new CodeActionExtension(ctx, logger, creators, index as any); + extension = new CodeActionExtension(ctx, logger, creators, fakeMapper); }); describe('executeCodeAction', () => { @@ -385,8 +385,8 @@ describe('CodeActionExtension', () => { { diagnostics: [ { - message: - `class 'ImplementGenericInterface' incorrectly implements 'GenericInterface'.`, + message: `class 'ImplementGenericInterface' incorrectly ` + + `implements 'GenericInterface'.`, }, ], }, diff --git a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts index 8beca1a..8ef77dd 100644 --- a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts @@ -3,17 +3,17 @@ import { join } from 'path'; import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; -import { ExtensionConfig } from '../../../src/common/config'; -import { LoggerFactory } from '../../../src/common/utilities'; -import { CodeCompletionExtension } from '../../../src/extension/extensions/CodeCompletionExtension'; -import { Container } from '../../../src/extension/IoC'; -import { iocSymbols } from '../../../src/extension/IoCSymbols'; +import { ExtensionConfig } from '../../../../src/common/config'; +import { LoggerFactory } from '../../../../src/common/utilities'; +import { CodeCompletionExtension } from '../../../../src/extension/extensions/CodeCompletionExtension'; +import { Container } from '../../../../src/extension/IoC'; +import { iocSymbols } from '../../../../src/extension/IoCSymbols'; const should = chai.should(); -const rootPath = Container.get(iocSymbols.rootPath); describe('CodeCompletionExtension', () => { + const rootPath = Container.get(iocSymbols.rootPath); const token = new vscode.CancellationTokenSource().token; let document: vscode.TextDocument; diff --git a/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts index 817bd95..5426cec 100644 --- a/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts @@ -2,27 +2,29 @@ import { join } from 'path'; import { TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; -import { ExtensionConfig } from '../../../src/common/config'; -import { LoggerFactory } from '../../../src/common/utilities'; -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 { ExtensionConfig } from '../../../../src/common/config'; +import { LoggerFactory } from '../../../../src/common/utilities'; +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'; +} 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'; +} 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'; +} from '../../../../src/extension/provider-items/document-structure/NotParseableStructureTreeItem'; -const rootPath = Container.get(iocSymbols.rootPath); describe('DocumentSymbolStructureExtension', () => { + const rootPath = Container.get(iocSymbols.rootPath); let extension: DocumentSymbolStructureExtension; const file = join( rootPath, diff --git a/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts index d6708c8..29d1bbf 100644 --- a/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts @@ -3,18 +3,18 @@ import { join } from 'path'; import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; -import { ExtensionConfig } from '../../../src/common/config'; -import { LoggerFactory } from '../../../src/common/utilities'; -import { ImportResolveExtension } from '../../../src/extension/extensions/ImportResolveExtension'; -import { Container } from '../../../src/extension/IoC'; -import { iocSymbols } from '../../../src/extension/IoCSymbols'; +import { ExtensionConfig } from '../../../../src/common/config'; +import { LoggerFactory } from '../../../../src/common/utilities'; +import { ImportResolveExtension } from '../../../../src/extension/extensions/ImportResolveExtension'; +import { Container } from '../../../../src/extension/IoC'; +import { iocSymbols } from '../../../../src/extension/IoCSymbols'; chai.should(); -const rootPath = Container.get(iocSymbols.rootPath); describe('TypeScript Mode: ImportResolveExtension', () => { + const rootPath = Container.get(iocSymbols.rootPath); let extension: any; before(async () => { @@ -184,7 +184,7 @@ describe('TypeScript Mode: ImportResolveExtension', () => { }); }); - + describe('organizeImports with exports', () => { const file = join(rootPath, 'extension/extensions/importResolveExtension/organizeImportsWithExports.ts'); @@ -399,7 +399,7 @@ describe('Mixed Mode: ImportResolveExtension', () => { 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', @@ -411,7 +411,7 @@ describe('Mixed Mode: ImportResolveExtension', () => { }); }); - + describe('addImportToDocument in .ts file', () => { const file = join( rootPath, @@ -452,7 +452,7 @@ describe('Mixed Mode: ImportResolveExtension', () => { 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', diff --git a/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts b/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts index 71d138b..fbc256b 100644 --- a/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts @@ -3,16 +3,16 @@ 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'; +import { Container } from '../../../../src/extension/IoC'; +import { iocSymbols } from '../../../../src/extension/IoCSymbols'; +import { ImportManager } from '../../../../src/extension/managers'; chai.should(); -const rootPath = Container.get(iocSymbols.rootPath); describe('OrganizeImportsOnSaveExtension', () => { + const rootPath = Container.get(iocSymbols.rootPath); let document: vscode.TextDocument; let index: DeclarationIndex; diff --git a/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts index b63f8d6..d3876bc 100644 --- a/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts @@ -2,18 +2,18 @@ import * as chai from 'chai'; import { join } from 'path'; import { File, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { ExtensionConfig } from '../../../src/common/config'; -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'; +import { ExtensionConfig } from '../../../../src/common/config'; +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(); -const rootPath = Container.get(iocSymbols.rootPath); describe('KeywordImportGroup', () => { + const rootPath = Container.get(iocSymbols.rootPath); let file: File; let importGroup: KeywordImportGroup; let config: ExtensionConfig; diff --git a/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts index 74b2ed1..d7ce8b5 100644 --- a/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts @@ -2,18 +2,18 @@ import * as chai from 'chai'; import { join } from 'path'; import { File, NamedImport, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { ExtensionConfig } from '../../../src/common/config'; -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'; +import { ExtensionConfig } from '../../../../src/common/config'; +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(); -const rootPath = Container.get(iocSymbols.rootPath); describe('RegexImportGroup', () => { + const rootPath = Container.get(iocSymbols.rootPath); let file: File; let importGroup: RegexImportGroup; let config: ExtensionConfig; diff --git a/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts index 54209a0..43b6065 100644 --- a/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts @@ -2,18 +2,18 @@ import * as chai from 'chai'; import { join } from 'path'; import { File, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; -import { ExtensionConfig } from '../../../src/common/config'; -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'; +import { ExtensionConfig } from '../../../../src/common/config'; +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(); -const rootPath = Container.get(iocSymbols.rootPath); describe('RemainImportGroup', () => { + const rootPath = Container.get(iocSymbols.rootPath); let file: File; let importGroup: RemainImportGroup; let config: ExtensionConfig; diff --git a/test/single-workspace-tests/extension/managers/ClassManager.test.ts b/test/single-workspace-tests/extension/managers/ClassManager.test.ts index c596860..701e45c 100644 --- a/test/single-workspace-tests/extension/managers/ClassManager.test.ts +++ b/test/single-workspace-tests/extension/managers/ClassManager.test.ts @@ -10,19 +10,19 @@ import { } from 'typescript-parser'; import { Position, Range, TextDocument, window, workspace } from 'vscode'; -import { findFiles } from '../../../src/extension/extensions/ImportResolveExtension'; -import { Container } from '../../../src/extension/IoC'; -import { iocSymbols } from '../../../src/extension/IoCSymbols'; -import { ClassManager } from '../../../src/extension/managers/ClassManager'; -import { VscodeExtensionConfig } from '../../../src/extension/VscodeExtensionConfig'; +// import { findFiles } from '../../../../src/extension/extensions/ImportResolveExtension'; +import { Container } from '../../../../src/extension/IoC'; +import { iocSymbols } from '../../../../src/extension/IoCSymbols'; +import { ClassManager } from '../../../../src/extension/managers/ClassManager'; +// import { VscodeExtensionConfig } from '../../../../src/extension/VscodeExtensionConfig'; const should = chai.should(); chai.use(sinonChai); -const rootPath = Container.get(iocSymbols.rootPath); describe('ClassManager', () => { + const rootPath = Container.get(iocSymbols.rootPath); const file = join(rootPath, 'extension/managers/ClassManagerFile.ts'); let document: TextDocument; let documentText: string; diff --git a/test/single-workspace-tests/extension/managers/ImportManager.test.ts b/test/single-workspace-tests/extension/managers/ImportManager.test.ts index 04c1250..f9cc403 100644 --- a/test/single-workspace-tests/extension/managers/ImportManager.test.ts +++ b/test/single-workspace-tests/extension/managers/ImportManager.test.ts @@ -5,11 +5,11 @@ import sinonChai = require('sinon-chai'); import { DeclarationIndex, File, NamedImport } from 'typescript-parser'; import { Position, Range, TextDocument, window, workspace } from 'vscode'; -import { findFiles } from '../../../src/extension/extensions/ImportResolveExtension'; -import { Container } from '../../../src/extension/IoC'; -import { iocSymbols } from '../../../src/extension/IoCSymbols'; -import { ImportManager } from '../../../src/extension/managers'; -import { VscodeExtensionConfig } from '../../../src/extension/VscodeExtensionConfig'; +// import { findFiles } from '../../../../src/extension/extensions/ImportResolveExtension'; +import { Container } from '../../../../src/extension/IoC'; +import { iocSymbols } from '../../../../src/extension/IoCSymbols'; +import { ImportManager } from '../../../../src/extension/managers'; +// import { VscodeExtensionConfig } from '../../../../src/extension/VscodeExtensionConfig'; const should = chai.should(); chai.use(sinonChai); @@ -35,10 +35,10 @@ function restoreInputBox(stub: sinon.SinonStub): void { stub.restore(); } -const rootPath = Container.get(iocSymbols.rootPath); describe('ImportManager', () => { + const rootPath = Container.get(iocSymbols.rootPath); const file = join(rootPath, 'extension/managers/ImportManagerFile.ts'); let document: TextDocument; let documentText: string; From 5ba9a297adefe9d6bc362de28c0d6199a2b254be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 25 Oct 2017 12:52:42 +0200 Subject: [PATCH 34/40] fixing first tests --- .vscode/launch.json | 4 ++-- .../extension/extensions/CodeActionExtension.test.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1e50969..e13e8f7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -39,12 +39,12 @@ "args": [ "${workspaceRoot}/test/_workspace", "--extensionDevelopmentPath=${workspaceRoot}", - "--extensionTestsPath=${workspaceRoot}/out/test/single-workspace-tests" + "--extensionTestsPath=${workspaceRoot}/out/test/single-workspace-tests/" ], "stopOnEntry": false, "sourceMaps": true, "outFiles": [ - "${workspaceRoot}/out/test/**/*.js" + "${workspaceRoot}/out/test/single-workspace-tests/**/*.js" ] }, { diff --git a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts index f04b5b0..e37d686 100644 --- a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts @@ -27,7 +27,7 @@ class SpyCodeAction implements CodeAction { } } -describe.only('CodeActionExtension', () => { +describe('CodeActionExtension', () => { const rootPath = workspace.workspaceFolders![0].uri.fsPath; let extension: any; @@ -96,7 +96,7 @@ describe.only('CodeActionExtension', () => { 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; + spy.calledOnce; }); it('should warn the user if the result is false', async () => { @@ -106,7 +106,7 @@ describe.only('CodeActionExtension', () => { try { await extension.executeCodeAction(new SpyCodeAction(sinon.spy(), false)); - stub.should.be.calledWith('The provided code action could not complete. Please see the logs.'); + stub.calledWith('The provided code action could not complete. Please see the logs.'); } finally { stub.restore(); } @@ -467,7 +467,7 @@ describe.only('CodeActionExtension', () => { cmds.should.have.lengthOf(2); const action = cmds[0]; - action.title.should.equal('Import "Class1" from "/server/indices".'); + action.title.should.equal('Import "Class1" from "/server/indices/MyClass".'); action.arguments[0].should.be.an.instanceof(AddImportCodeAction); }); @@ -492,7 +492,7 @@ describe.only('CodeActionExtension', () => { cmds.should.have.lengthOf(3); let action = cmds[0]; - action.title.should.equal('Import "FancierLibraryClass" from "/server/indices".'); + action.title.should.equal('Import "FancierLibraryClass" from "/server/indices/MyClass".'); action.arguments[0].should.be.an.instanceof(AddImportCodeAction); action = cmds[1]; From 125845333da5a7c440169d020161eefd1f86fa0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 25 Oct 2017 14:24:14 +0200 Subject: [PATCH 35/40] fixing tests --- test/_workspace/.vscode/settings.json | 4 ++- .../extensions/CodeActionExtension.test.ts | 6 ++-- .../CodeCompletionExtension.test.ts | 35 ++++++++++++------- .../DocumentSymbolStructureExtension.test.ts | 7 ++-- .../extensions/ImportResolveExtension.test.ts | 35 +++++++++++++------ .../OrganizeImportsOnSaveExtension.test.ts | 4 +-- .../KeywordImportGroup.test.ts | 6 ++-- .../import-grouping/RegexImportGroup.test.ts | 7 ++-- .../import-grouping/RemainImportGroup.test.ts | 7 ++-- .../extension/managers/ClassManager.test.ts | 13 ++++--- .../extension/managers/ImportManager.test.ts | 21 ++++++----- 11 files changed, 83 insertions(+), 62 deletions(-) diff --git a/test/_workspace/.vscode/settings.json b/test/_workspace/.vscode/settings.json index e1da5dd..c5f10cc 100755 --- a/test/_workspace/.vscode/settings.json +++ b/test/_workspace/.vscode/settings.json @@ -14,5 +14,7 @@ "typescriptHero.codeOutline.enabled": true, "typescriptHero.resolver.organizeOnSave": false, "typescriptHero.resolver.promptForSpecifiers": true, - "editor.formatOnSave": true + "editor.formatOnSave": true, + "typescriptHero.codeCompletion.completionSortMode": "default", + "typescriptHero.resolver.disableImportRemovalOnOrganize": false } diff --git a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts index e37d686..d5f6b59 100644 --- a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts @@ -1,6 +1,7 @@ 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'; @@ -17,6 +18,7 @@ import { iocSymbols } from '../../../../src/extension/IoCSymbols'; import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; chai.should(); +chai.use(sinonChai); class SpyCodeAction implements CodeAction { constructor(private spy: sinon.SinonSpy, private result: boolean) { } @@ -96,7 +98,7 @@ describe('CodeActionExtension', () => { it('should call the execute method of a code action', async () => { const spy = sinon.spy(); await extension.executeCodeAction(new SpyCodeAction(spy, true)); - spy.calledOnce; + spy.should.be.calledOnce; }); it('should warn the user if the result is false', async () => { @@ -106,7 +108,7 @@ describe('CodeActionExtension', () => { try { await extension.executeCodeAction(new SpyCodeAction(sinon.spy(), false)); - stub.calledWith('The provided code action could not complete. Please see the logs.'); + stub.should.be.calledWith('The provided code action could not complete. Please see the logs.'); } finally { stub.restore(); } diff --git a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts index 8ef77dd..861402b 100644 --- a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts @@ -1,24 +1,24 @@ 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 { ExtensionConfig } from '../../../../src/common/config'; +import { ConfigFactory } from '../../../../src/common/factories'; import { LoggerFactory } from '../../../../src/common/utilities'; 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'; const should = chai.should(); - describe('CodeCompletionExtension', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; const token = new vscode.CancellationTokenSource().token; let document: vscode.TextDocument; let extension: CodeCompletionExtension; - let config: ExtensionConfig; before(async () => { const file = join( @@ -31,9 +31,10 @@ describe('CodeCompletionExtension', () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); const parser = Container.get(iocSymbols.typescriptParser); - const index = Container.get(iocSymbols.declarationIndex); - config = Container.get(iocSymbols.configuration); + const config = Container.get(iocSymbols.configuration); + const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); + const index = new DeclarationIndex(parser, rootPath); await index.buildIndex( [ join( @@ -47,7 +48,9 @@ describe('CodeCompletionExtension', () => { ], ); - extension = new CodeCompletionExtension(ctx, logger, parser, index as any, rootPath, config); + fakeMapper.getIndexForFile = sinon.spy(() => index); + + extension = new CodeCompletionExtension(ctx, logger, parser, fakeMapper, config); }); it('shoud resolve to null if typing in a string', async () => { @@ -85,12 +88,20 @@ describe('CodeCompletionExtension', () => { }); it('should use custom sort order when config.completionSortMode is bottom', async () => { - Object.defineProperty(config, 'completionSortMode', { value: 'bottom', writable: true }); - const result = await extension.provideCompletionItems(document, new vscode.Position(6, 5), token); - should.exist(result![0].sortText); - result![0].sortText!.should.equal('9999-MyClass'); + const config = vscode.workspace.getConfiguration( + 'typescriptHero.codeCompletion', + vscode.workspace.workspaceFolders![0].uri, + ); + + config.update('completionSortMode', 'bottom'); - Object.defineProperty(config, 'completionSortMode', { value: 'default' }); + 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 { + config.update('completionSortMode', 'default'); + } }); it('shoud add an insert command text edit if import would be new', async () => { diff --git a/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts index 5426cec..9930532 100644 --- a/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts @@ -2,7 +2,7 @@ import { join } from 'path'; import { TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; -import { ExtensionConfig } from '../../../../src/common/config'; +import { ConfigFactory } from '../../../../src/common/factories'; import { LoggerFactory } from '../../../../src/common/utilities'; import { DocumentSymbolStructureExtension } from '../../../../src/extension/extensions/DocumentSymbolStructureExtension'; import { Container } from '../../../../src/extension/IoC'; @@ -24,7 +24,7 @@ import { describe('DocumentSymbolStructureExtension', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; let extension: DocumentSymbolStructureExtension; const file = join( rootPath, @@ -35,7 +35,7 @@ describe('DocumentSymbolStructureExtension', () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); const parser = Container.get(iocSymbols.typescriptParser); - const config = Container.get(iocSymbols.configuration); + const config = Container.get(iocSymbols.configuration); extension = new DocumentSymbolStructureExtension(ctx, logger, config, parser); }); @@ -57,7 +57,6 @@ describe('DocumentSymbolStructureExtension', () => { }); it('should return a "file not parsable" if it is no ts file', async () => { - const rootPath = Container.get(iocSymbols.rootPath); const file = join( rootPath, 'extension/extensions/documentSymbolStructureExtension/notParsable.txt', diff --git a/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts index 29d1bbf..906ec3e 100644 --- a/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts @@ -1,20 +1,22 @@ 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 { ExtensionConfig } from '../../../../src/common/config'; +import { ConfigFactory } from '../../../../src/common/factories'; import { LoggerFactory } from '../../../../src/common/utilities'; 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'; chai.should(); describe('TypeScript Mode: ImportResolveExtension', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; let extension: any; before(async () => { @@ -28,10 +30,11 @@ describe('TypeScript Mode: ImportResolveExtension', () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); - const config = Container.get(iocSymbols.configuration); + const config = Container.get(iocSymbols.configuration); const parser = Container.get(iocSymbols.typescriptParser); + const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - const index = Container.get(iocSymbols.declarationIndex); + const index = new DeclarationIndex(parser, rootPath); await index.buildIndex( [ join( @@ -53,7 +56,9 @@ describe('TypeScript Mode: ImportResolveExtension', () => { ], ); - extension = new ImportResolveExtension(ctx, logger, config, parser, index, rootPath); + fakeMapper.getIndexForFile = sinon.spy(() => index); + + extension = new ImportResolveExtension(ctx, logger, parser, fakeMapper); }); describe('addImportToDocument', () => { @@ -223,6 +228,7 @@ describe('TypeScript Mode: ImportResolveExtension', () => { describe('JavaScript Mode: ImportResolveExtension', () => { + const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; let extension: any; before(async () => { @@ -236,10 +242,11 @@ describe('JavaScript Mode: ImportResolveExtension', () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); - const config = Container.get(iocSymbols.configuration); + const config = Container.get(iocSymbols.configuration); const parser = Container.get(iocSymbols.typescriptParser); + const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - const index = Container.get(iocSymbols.declarationIndex); + const index = new DeclarationIndex(parser, rootPath); await index.buildIndex( [ join( @@ -257,7 +264,9 @@ describe('JavaScript Mode: ImportResolveExtension', () => { ], ); - extension = new ImportResolveExtension(ctx, logger, config, parser, index, rootPath); + fakeMapper.getIndexForFile = sinon.spy(() => index); + + extension = new ImportResolveExtension(ctx, logger, parser, fakeMapper); }); describe('addImportToDocument', () => { @@ -318,6 +327,7 @@ describe('JavaScript Mode: ImportResolveExtension', () => { describe('Mixed Mode: ImportResolveExtension', () => { + const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; let extension: any; before(async () => { @@ -331,10 +341,11 @@ describe('Mixed Mode: ImportResolveExtension', () => { const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); - const config = Container.get(iocSymbols.configuration); + const config = Container.get(iocSymbols.configuration); const parser = Container.get(iocSymbols.typescriptParser); + const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); - const index = Container.get(iocSymbols.declarationIndex); + const index = new DeclarationIndex(parser, rootPath); await index.buildIndex( [ join( @@ -356,7 +367,9 @@ describe('Mixed Mode: ImportResolveExtension', () => { ], ); - extension = new ImportResolveExtension(ctx, logger, config, parser, index, rootPath); + fakeMapper.getIndexForFile = sinon.spy(() => index); + + extension = new ImportResolveExtension(ctx, logger, parser, fakeMapper); }); describe('addImportToDocument in .js file', () => { diff --git a/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts b/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts index fbc256b..3cda502 100644 --- a/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/OrganizeImportsOnSaveExtension.test.ts @@ -12,7 +12,7 @@ chai.should(); describe('OrganizeImportsOnSaveExtension', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; let document: vscode.TextDocument; let index: DeclarationIndex; @@ -25,7 +25,7 @@ describe('OrganizeImportsOnSaveExtension', () => { await vscode.window.showTextDocument(document); - index = Container.get(iocSymbols.declarationIndex); + index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); await index.buildIndex( [ join( diff --git a/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts index d3876bc..29c82f2 100644 --- a/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/KeywordImportGroup.test.ts @@ -1,8 +1,8 @@ import * as chai from 'chai'; import { join } from 'path'; import { File, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; +import { workspace } from 'vscode'; -import { ExtensionConfig } from '../../../../src/common/config'; import { TypescriptCodeGeneratorFactory } from '../../../../src/common/factories'; import { ImportGroupKeyword, KeywordImportGroup } from '../../../../src/extension/import-grouping'; import { Container } from '../../../../src/extension/IoC'; @@ -13,15 +13,13 @@ chai.should(); describe('KeywordImportGroup', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = workspace.workspaceFolders![0].uri.fsPath; let file: File; let importGroup: KeywordImportGroup; - let config: ExtensionConfig; let generator: TypescriptCodeGenerator; before(async () => { const parser = Container.get(iocSymbols.typescriptParser); - config = Container.get(iocSymbols.configuration); generator = Container.get(iocSymbols.generatorFactory)(); file = await parser.parseFile( join( diff --git a/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts index d7ce8b5..49e88c5 100644 --- a/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/RegexImportGroup.test.ts @@ -1,8 +1,8 @@ import * as chai from 'chai'; import { join } from 'path'; import { File, NamedImport, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; +import { workspace } from 'vscode'; -import { ExtensionConfig } from '../../../../src/common/config'; import { TypescriptCodeGeneratorFactory } from '../../../../src/common/factories'; import { RegexImportGroup } from '../../../../src/extension/import-grouping'; import { Container } from '../../../../src/extension/IoC'; @@ -10,18 +10,15 @@ import { iocSymbols } from '../../../../src/extension/IoCSymbols'; chai.should(); - describe('RegexImportGroup', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = workspace.workspaceFolders![0].uri.fsPath; let file: File; let importGroup: RegexImportGroup; - let config: ExtensionConfig; let generator: TypescriptCodeGenerator; before(async () => { const parser = Container.get(iocSymbols.typescriptParser); - config = Container.get(iocSymbols.configuration); generator = Container.get(iocSymbols.generatorFactory)(); file = await parser.parseFile( join( diff --git a/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts b/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts index 43b6065..647b9e9 100644 --- a/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts +++ b/test/single-workspace-tests/extension/import-grouping/RemainImportGroup.test.ts @@ -1,8 +1,8 @@ import * as chai from 'chai'; import { join } from 'path'; import { File, TypescriptCodeGenerator, TypescriptParser } from 'typescript-parser'; +import { workspace } from 'vscode'; -import { ExtensionConfig } from '../../../../src/common/config'; import { TypescriptCodeGeneratorFactory } from '../../../../src/common/factories'; import { RemainImportGroup } from '../../../../src/extension/import-grouping'; import { Container } from '../../../../src/extension/IoC'; @@ -10,18 +10,15 @@ import { iocSymbols } from '../../../../src/extension/IoCSymbols'; chai.should(); - describe('RemainImportGroup', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = workspace.workspaceFolders![0].uri.fsPath; let file: File; let importGroup: RemainImportGroup; - let config: ExtensionConfig; let generator: TypescriptCodeGenerator; before(async () => { const parser = Container.get(iocSymbols.typescriptParser); - config = Container.get(iocSymbols.configuration); generator = Container.get(iocSymbols.generatorFactory)(); file = await parser.parseFile( join( diff --git a/test/single-workspace-tests/extension/managers/ClassManager.test.ts b/test/single-workspace-tests/extension/managers/ClassManager.test.ts index 701e45c..3abddcd 100644 --- a/test/single-workspace-tests/extension/managers/ClassManager.test.ts +++ b/test/single-workspace-tests/extension/managers/ClassManager.test.ts @@ -10,19 +10,18 @@ import { } from 'typescript-parser'; import { Position, Range, TextDocument, window, workspace } from 'vscode'; -// import { findFiles } from '../../../../src/extension/extensions/ImportResolveExtension'; +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'; -// import { VscodeExtensionConfig } from '../../../../src/extension/VscodeExtensionConfig'; const should = chai.should(); chai.use(sinonChai); - describe('ClassManager', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = workspace.workspaceFolders![0].uri.fsPath; const file = join(rootPath, 'extension/managers/ClassManagerFile.ts'); let document: TextDocument; let documentText: string; @@ -30,10 +29,10 @@ describe('ClassManager', () => { let files: string[]; before(async () => { - const config = new VscodeExtensionConfig(); - files = await findFiles(config, rootPath); + const config = new VscodeExtensionConfig(workspace.workspaceFolders![0].uri); + files = await findFiles(config, workspace.workspaceFolders![0]); - index = Container.get(iocSymbols.declarationIndex); + index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); await index.buildIndex(files); document = await workspace.openTextDocument(file); diff --git a/test/single-workspace-tests/extension/managers/ImportManager.test.ts b/test/single-workspace-tests/extension/managers/ImportManager.test.ts index f9cc403..a7c3bf2 100644 --- a/test/single-workspace-tests/extension/managers/ImportManager.test.ts +++ b/test/single-workspace-tests/extension/managers/ImportManager.test.ts @@ -5,10 +5,13 @@ import sinonChai = require('sinon-chai'); import { DeclarationIndex, File, NamedImport } from 'typescript-parser'; import { Position, Range, TextDocument, window, workspace } from 'vscode'; -// import { findFiles } from '../../../../src/extension/extensions/ImportResolveExtension'; +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'; + +// import { findFiles } from '../../../../src/extension/extensions/ImportResolveExtension'; // import { VscodeExtensionConfig } from '../../../../src/extension/VscodeExtensionConfig'; const should = chai.should(); @@ -35,10 +38,9 @@ function restoreInputBox(stub: sinon.SinonStub): void { stub.restore(); } - describe('ImportManager', () => { - const rootPath = Container.get(iocSymbols.rootPath); + const rootPath = workspace.workspaceFolders![0].uri.fsPath; const file = join(rootPath, 'extension/managers/ImportManagerFile.ts'); let document: TextDocument; let documentText: string; @@ -46,10 +48,10 @@ describe('ImportManager', () => { let files: string[]; before(async () => { - const config = new VscodeExtensionConfig(); - files = await findFiles(config, rootPath); + const config = new VscodeExtensionConfig(workspace.workspaceFolders![0].uri); + files = await findFiles(config, workspace.workspaceFolders![0]); - index = index = Container.get(iocSymbols.declarationIndex); + index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); await index.buildIndex(files); document = await workspace.openTextDocument(file); @@ -886,6 +888,7 @@ describe('ImportManager', () => { 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; @@ -893,10 +896,10 @@ describe('ImportManager with .tsx files', () => { let files: string[]; before(async () => { - const config = new VscodeExtensionConfig(); - files = await findFiles(config, rootPath); + const config = new VscodeExtensionConfig(workspace.workspaceFolders![0].uri); + files = await findFiles(config, workspace.workspaceFolders![0]); - index = index = Container.get(iocSymbols.declarationIndex); + index = new DeclarationIndex(Container.get(iocSymbols.typescriptParser), rootPath); await index.buildIndex(files); document = await workspace.openTextDocument(file); From 0fb64b4cf01bc5ce5d2d7d112df8526250bae333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 25 Oct 2017 14:36:17 +0200 Subject: [PATCH 36/40] fix tests --- src/common/config/CodeCompletionConfig.ts | 1 + .../extensions/CodeCompletionExtension.test.ts | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/common/config/CodeCompletionConfig.ts b/src/common/config/CodeCompletionConfig.ts index b99efaa..617bea6 100644 --- a/src/common/config/CodeCompletionConfig.ts +++ b/src/common/config/CodeCompletionConfig.ts @@ -20,6 +20,7 @@ export interface CodeCompletionConfig { /** * 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 */ diff --git a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts index 861402b..a42c6ed 100644 --- a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts @@ -10,6 +10,7 @@ import { CodeCompletionExtension } from '../../../../src/extension/extensions/Co import { Container } from '../../../../src/extension/IoC'; import { iocSymbols } from '../../../../src/extension/IoCSymbols'; import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; +import { VscodeExtensionConfig } from '../../../../src/extension/config/VscodeExtensionConfig'; const should = chai.should(); @@ -88,19 +89,20 @@ describe('CodeCompletionExtension', () => { }); it('should use custom sort order when config.completionSortMode is bottom', async () => { - const config = vscode.workspace.getConfiguration( - 'typescriptHero.codeCompletion', - vscode.workspace.workspaceFolders![0].uri, - ); + const orig = (extension as any).config; + const config = new VscodeExtensionConfig(); + (config as any).codeCompletionConfig = { + completionSortMode: 'bottom', + }; - config.update('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 { - config.update('completionSortMode', 'default'); + (extension as any).config = orig; } }); From e700fc92382df8e0e63aebf6f7a1b8325857f25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 25 Oct 2017 14:45:22 +0200 Subject: [PATCH 37/40] adding test file for multi root --- .vscode/launch.json | 2 +- package.json | 4 +-- test/_workspace_2/file1.ts | 2 -- test/multi-root-workspace-tests/index.ts | 44 ++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 test/multi-root-workspace-tests/index.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index e13e8f7..09c7f69 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -55,7 +55,7 @@ "args": [ "${workspaceRoot}/test/multi-root.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}", - "--extensionTestsPath=${workspaceRoot}/out/test/multi-root-workspace-tests" + "--extensionTestsPath=${workspaceRoot}/out/test/multi-root-workspace-tests/" ], "stopOnEntry": false, "sourceMaps": true, diff --git a/package.json b/package.json index 9424dea..c87492b 100644 --- a/package.json +++ b/package.json @@ -83,8 +83,8 @@ "lint": "tslint -c tslint.json --project ./config/tsconfig.build.json", "pretest": "del-cli ./out && tsc -p ./config/tsconfig.test.json && yarn lint", "test": "yarn test:single-workspace", - "test:single-workspace": "CODE_TESTS_WORKSPACE=./test/_workspace CODE_TESTS_PATH=./out/test/single-workspace-tests node ./node_modules/vscode/bin/test", - "test:multi-workspace": "CODE_TESTS_WORKSPACE=./test/multi-root.code-workspace CODE_TESTS_PATH=./out/test/multi-root-workspace-tests node ./node_modules/vscode/bin/test", + "test:single-workspace": "CODE_TESTS_WORKSPACE=$(pwd)/test/_workspace CODE_TESTS_PATH=$(pwd)/out/test/single-workspace-tests node ./node_modules/vscode/bin/test", + "test:multi-workspace": "CODE_TESTS_WORKSPACE=$(pwd)/test/multi-root.code-workspace CODE_TESTS_PATH=$(pwd)/out/test/multi-root-workspace-tests node ./node_modules/vscode/bin/test", "build": "del-cli ./out && tsc -p ./config/tsconfig.build.json", "package": "yarn build && del-cli './*.vsix' && vsce package", "semantic-release-pre": "semantic-release pre", diff --git a/test/_workspace_2/file1.ts b/test/_workspace_2/file1.ts index 8879bf0..e69de29 100644 --- a/test/_workspace_2/file1.ts +++ b/test/_workspace_2/file1.ts @@ -1,2 +0,0 @@ -import { ClassInFile2 } from './file2'; -ClassInFile2 diff --git a/test/multi-root-workspace-tests/index.ts b/test/multi-root-workspace-tests/index.ts new file mode 100644 index 0000000..9956ef9 --- /dev/null +++ b/test/multi-root-workspace-tests/index.ts @@ -0,0 +1,44 @@ +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; From 829eb9fdfd7bc63c08cfaea4e3c4102524917757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 25 Oct 2017 18:39:43 +0200 Subject: [PATCH 38/40] add file --- test/multi-root-workspace-tests/MultiRootIndices.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test/multi-root-workspace-tests/MultiRootIndices.test.ts diff --git a/test/multi-root-workspace-tests/MultiRootIndices.test.ts b/test/multi-root-workspace-tests/MultiRootIndices.test.ts new file mode 100644 index 0000000..5d02a97 --- /dev/null +++ b/test/multi-root-workspace-tests/MultiRootIndices.test.ts @@ -0,0 +1,6 @@ + +describe('Multi root indices', () => { + + it('should be tested; will be done as soon as the feature is default enabled.'); + +}); From 1788d76983ee4748a459f884c9990d8294c23d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 26 Oct 2017 07:33:41 +0200 Subject: [PATCH 39/40] docs --- src/common/helpers/DeclarationIndexHelpers.ts | 19 ++++++-------- .../utilities/DeclarationIndexMapper.ts | 25 ------------------- .../extension/managers/ImportManager.test.ts | 3 --- 3 files changed, 8 insertions(+), 39 deletions(-) diff --git a/src/common/helpers/DeclarationIndexHelpers.ts b/src/common/helpers/DeclarationIndexHelpers.ts index d63de24..ed89bad 100644 --- a/src/common/helpers/DeclarationIndexHelpers.ts +++ b/src/common/helpers/DeclarationIndexHelpers.ts @@ -28,15 +28,11 @@ export function getDeclarationsFilteredByImports( const importedLib = getAbsolutLibraryName(tsImport.libraryName, documentPath, rootPath); if (tsImport instanceof NamedImport) { - declarations = declarations - .filter(o => o.from !== importedLib || !(tsImport as NamedImport).specifiers - .some(s => s.specifier === o.declaration.name)); - // if (tsImport.defaultAlias) { - // else if (tsImport instanceof DefaultImport) { - // declarations = declarations - // .filter(o => (!(o.declaration instanceof DefaultDeclaration) || importedLib !== o.from)); - // } - // } // TODO + declarations = declarations.filter( + o => o.from !== importedLib || + !tsImport.specifiers.some(s => s.specifier === o.declaration.name) || + tsImport.defaultAlias !== o.declaration.name, + ); } else if (tsImport instanceof NamespaceImport || tsImport instanceof ExternalModuleImport) { declarations = declarations.filter(o => o.from !== tsImport.libraryName); } @@ -94,7 +90,8 @@ export function getRelativeLibraryName(library: string, actualFilePath: string, } /** - * TODO + * This function searches for files in a specific workspace folder. The files are relative to the given + * workspace folder and the searched type is determined by the configuration of the extension (TS, JS or Both mode). * * @export * @param {ExtensionConfig} config @@ -113,7 +110,7 @@ export async function findFiles(config: ExtensionConfig, workspaceFolder: Worksp let globs: string[] = []; let ignores = ['**/typings/**']; - const excludePatterns = config.resolver.ignorePatterns; // convert to resource config + const excludePatterns = config.resolver.ignorePatterns; const rootPath = workspaceFolder.uri.fsPath; if (rootPath && existsSync(join(rootPath, 'package.json'))) { diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index ec11c80..122f784 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -23,34 +23,9 @@ interface WorkspaceIndex { watcher: FileSystemWatcher; } -// TODO documentation // TODO move did change configuration to all indices // TODO: update index on change of configs -// this.context.subscriptions.push(workspace.onDidChangeConfiguration(() => { -// if (!window.activeTextEditor) { -// return; -// } -// let build = false; -// const config = this.config(window.activeTextEditor.document.uri); - -// if (!compareIgnorePatterns(this.ignorePatterns, config.resolver.ignorePatterns)) { -// this.logger.info('The typescriptHero.resolver.ignorePatterns setting was modified, reload the index.'); -// this.ignorePatterns = config.resolver.ignorePatterns; -// build = true; -// } -// if (this.actualMode !== config.resolver.resolverMode) { -// this.logger.info('The typescriptHero.resolver.resolverMode setting was modified, reload the index.'); -// this.statusBarItem.tooltip = -// `Click to manually reindex all files; Actual mode: ${ResolverMode[config.resolver.resolverMode]}`; -// this.actualMode = config.resolver.resolverMode; -// build = true; -// } -// if (build) { -// this.indices.rebuildAll(); -// } -// })); - @injectable() export class DeclarationIndexMapper { public readonly onStartIndexing: Event; diff --git a/test/single-workspace-tests/extension/managers/ImportManager.test.ts b/test/single-workspace-tests/extension/managers/ImportManager.test.ts index a7c3bf2..749c7f2 100644 --- a/test/single-workspace-tests/extension/managers/ImportManager.test.ts +++ b/test/single-workspace-tests/extension/managers/ImportManager.test.ts @@ -11,9 +11,6 @@ import { Container } from '../../../../src/extension/IoC'; import { iocSymbols } from '../../../../src/extension/IoCSymbols'; import { ImportManager } from '../../../../src/extension/managers'; -// import { findFiles } from '../../../../src/extension/extensions/ImportResolveExtension'; -// import { VscodeExtensionConfig } from '../../../../src/extension/VscodeExtensionConfig'; - const should = chai.should(); chai.use(sinonChai); From b2f230ffab65b1407111962a5b0240f226006e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 26 Oct 2017 07:45:41 +0200 Subject: [PATCH 40/40] ups. --- src/common/helpers/DeclarationIndexHelpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/helpers/DeclarationIndexHelpers.ts b/src/common/helpers/DeclarationIndexHelpers.ts index ed89bad..fd27adc 100644 --- a/src/common/helpers/DeclarationIndexHelpers.ts +++ b/src/common/helpers/DeclarationIndexHelpers.ts @@ -30,8 +30,8 @@ export function getDeclarationsFilteredByImports( if (tsImport instanceof NamedImport) { declarations = declarations.filter( o => o.from !== importedLib || - !tsImport.specifiers.some(s => s.specifier === o.declaration.name) || - tsImport.defaultAlias !== o.declaration.name, + !tsImport.specifiers.some(s => s.specifier === o.declaration.name), + // || tsImport.defaultAlias !== o.declaration.name, ); } else if (tsImport instanceof NamespaceImport || tsImport instanceof ExternalModuleImport) { declarations = declarations.filter(o => o.from !== tsImport.libraryName);