From 9f927fb039120c6239e355c94e23b6a1c8c27403 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 6 Sep 2018 12:50:23 +0000 Subject: [PATCH 1/2] chore(deps): update prettier --- package-lock.json | 17 ++++++++++------- package.json | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index a3ae034dc..ef00962e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -378,9 +378,9 @@ } }, "@sourcegraph/prettierrc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@sourcegraph/prettierrc/-/prettierrc-2.1.1.tgz", - "integrity": "sha512-p02LPFLOhr0JRsBwtCqNC+9AoSAKjNsW96zdfPjkn4lA+3H/0nHBtjUkoSPTuVh8FXZ56sAB2JkhH9RIZ5YiuA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@sourcegraph/prettierrc/-/prettierrc-2.2.0.tgz", + "integrity": "sha512-kRdHxdAppxYnN7qAQjNTyuG05pjYHFtEUquZauXVXBeaGB4sye3uSkb8wgi34jeaUHG/gWp2f5hQgCCBMizjjA==", "dev": true }, "@sourcegraph/tsconfig": { @@ -529,6 +529,7 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -3610,6 +3611,7 @@ "version": "0.1.4", "bundled": true, "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -4766,7 +4768,8 @@ "longest": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "loose-envify": { "version": "1.3.1", @@ -6649,9 +6652,9 @@ "dev": true }, "prettier": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.12.1.tgz", - "integrity": "sha1-wa0g6APndJ+vkFpAnSNn4Gu+cyU=", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.2.tgz", + "integrity": "sha512-McHPg0n1pIke+A/4VcaS2en+pTNjy4xF+Uuq86u/5dyDO59/TtFZtQ708QIRkEZ3qwKz3GVkVa6mpxK/CpB8Rg==", "dev": true }, "process-nextick-args": { diff --git a/package.json b/package.json index 7f6644392..f740250f0 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "vscode-languageserver-types": "^3.0.3" }, "devDependencies": { - "@sourcegraph/prettierrc": "^2.0.0", + "@sourcegraph/prettierrc": "^2.2.0", "@sourcegraph/tsconfig": "^3.0.0", "@sourcegraph/tslint-config": "^11.0.1", "@types/chai": "4.0.6", @@ -83,7 +83,7 @@ "husky": "^0.14.0", "mocha": "^5.0.0", "nyc": "^11.0.2", - "prettier": "1.12.1", + "prettier": "1.14.2", "rimraf": "^2.6.1", "semantic-release": "^15.1.8", "sinon": "^5.0.0", From 1fca4b80c4a83c585013e3e78e443c81fe0a447d Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 6 Sep 2018 16:13:49 +0200 Subject: [PATCH 2/2] style: run prettier --- package-lock.json | 5 +- src/lang-handler.ts | 14 +- src/test/typescript-service-helpers.ts | 33 +- src/typescript-service.ts | 803 +++++++++++++------------ 4 files changed, 454 insertions(+), 401 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef00962e3..726218780 100644 --- a/package-lock.json +++ b/package-lock.json @@ -529,7 +529,6 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, - "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -3611,7 +3610,6 @@ "version": "0.1.4", "bundled": true, "dev": true, - "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -4768,8 +4766,7 @@ "longest": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "loose-envify": { "version": "1.3.1", diff --git a/src/lang-handler.ts b/src/lang-handler.ts index c4a00c244..0f1d7922f 100644 --- a/src/lang-handler.ts +++ b/src/lang-handler.ts @@ -107,13 +107,15 @@ export class RemoteLanguageClient { .filter(msg => isResponseMessage(msg) && msg.id === id) .take(1) // Emit result or error - .map((msg: ResponseMessage): any => { - receivedResponse = true - if (msg.error) { - throw Object.assign(new Error(msg.error.message), msg.error) + .map( + (msg: ResponseMessage): any => { + receivedResponse = true + if (msg.error) { + throw Object.assign(new Error(msg.error.message), msg.error) + } + return msg.result } - return msg.result - }) + ) // Forward events to subscriber .subscribe(subscriber) // Handler for unsubscribe() diff --git a/src/test/typescript-service-helpers.ts b/src/test/typescript-service-helpers.ts index 3377b3342..097e0c834 100644 --- a/src/test/typescript-service-helpers.ts +++ b/src/test/typescript-service-helpers.ts @@ -66,23 +66,24 @@ export const initializeTypeScriptService = ( async function(this: TestContext & IBeforeAndAfterContext): Promise { // Stub client this.client = sinon.createStubInstance(RemoteLanguageClient) - this.client.textDocumentXcontent.callsFake((params: TextDocumentContentParams): Observable< - TextDocumentItem - > => { - if (!files.has(params.textDocument.uri)) { - return Observable.throw(new Error(`Text document ${params.textDocument.uri} does not exist`)) + this.client.textDocumentXcontent.callsFake( + (params: TextDocumentContentParams): Observable => { + if (!files.has(params.textDocument.uri)) { + return Observable.throw(new Error(`Text document ${params.textDocument.uri} does not exist`)) + } + return Observable.of({ + uri: params.textDocument.uri, + text: files.get(params.textDocument.uri)!, + version: 1, + languageId: '', + }) } - return Observable.of({ - uri: params.textDocument.uri, - text: files.get(params.textDocument.uri)!, - version: 1, - languageId: '', - }) - }) - this.client.workspaceXfiles.callsFake((params: WorkspaceFilesParams): Observable => - observableFromIterable(files.keys()) - .map(uri => ({ uri })) - .toArray() + ) + this.client.workspaceXfiles.callsFake( + (params: WorkspaceFilesParams): Observable => + observableFromIterable(files.keys()) + .map(uri => ({ uri })) + .toArray() ) this.client.xcacheGet.callsFake(() => Observable.of(null)) this.client.workspaceApplyEdit.callsFake(() => Observable.of({ applied: true })) diff --git a/src/typescript-service.ts b/src/typescript-service.ts index 38a14267a..5b1f055e9 100644 --- a/src/typescript-service.ts +++ b/src/typescript-service.ts @@ -413,24 +413,28 @@ export class TypeScriptService { ? configuration.getService().getTypeDefinitionAtPosition(fileName, offset) : configuration.getService().getDefinitionAtPosition(fileName, offset) - return Observable.from(definitions || []).map((definition): Location => { - const sourceFile = this._getSourceFile(configuration, definition.fileName, span) - if (!sourceFile) { - throw new Error('expected source file "' + definition.fileName + '" to exist in configuration') - } - const start = ts.getLineAndCharacterOfPosition(sourceFile, definition.textSpan.start) - const end = ts.getLineAndCharacterOfPosition( - sourceFile, - definition.textSpan.start + definition.textSpan.length - ) - return { - uri: locationUri(definition.fileName), - range: { - start, - end, - }, + return Observable.from(definitions || []).map( + (definition): Location => { + const sourceFile = this._getSourceFile(configuration, definition.fileName, span) + if (!sourceFile) { + throw new Error( + 'expected source file "' + definition.fileName + '" to exist in configuration' + ) + } + const start = ts.getLineAndCharacterOfPosition(sourceFile, definition.textSpan.start) + const end = ts.getLineAndCharacterOfPosition( + sourceFile, + definition.textSpan.start + definition.textSpan.length + ) + return { + uri: locationUri(definition.fileName), + range: { + start, + end, + }, + } } - }) + ) }) } @@ -484,35 +488,44 @@ export class TypeScriptService { // Query TypeScript for references return Observable.from( configuration.getService().getDefinitionAtPosition(fileName, offset) || [] - ).mergeMap((definition: ts.DefinitionInfo): Observable => { - const definitionUri = locationUri(definition.fileName) - // Get the PackageDescriptor - return this._getPackageDescriptor(definitionUri) - .defaultIfEmpty(undefined) - .map((packageDescriptor: PackageDescriptor | undefined): SymbolLocationInformation => { - const sourceFile = this._getSourceFile(configuration, definition.fileName, span) - if (!sourceFile) { - throw new Error(`Expected source file ${definition.fileName} to exist in configuration`) - } - const symbol = definitionInfoToSymbolDescriptor(definition, this.root) - if (packageDescriptor) { - symbol.package = packageDescriptor - } - return { - symbol, - location: { - uri: definitionUri, - range: { - start: ts.getLineAndCharacterOfPosition(sourceFile, definition.textSpan.start), - end: ts.getLineAndCharacterOfPosition( - sourceFile, - definition.textSpan.start + definition.textSpan.length - ), - }, - }, - } - }) - }) + ).mergeMap( + (definition: ts.DefinitionInfo): Observable => { + const definitionUri = locationUri(definition.fileName) + // Get the PackageDescriptor + return this._getPackageDescriptor(definitionUri) + .defaultIfEmpty(undefined) + .map( + (packageDescriptor: PackageDescriptor | undefined): SymbolLocationInformation => { + const sourceFile = this._getSourceFile(configuration, definition.fileName, span) + if (!sourceFile) { + throw new Error( + `Expected source file ${definition.fileName} to exist in configuration` + ) + } + const symbol = definitionInfoToSymbolDescriptor(definition, this.root) + if (packageDescriptor) { + symbol.package = packageDescriptor + } + return { + symbol, + location: { + uri: definitionUri, + range: { + start: ts.getLineAndCharacterOfPosition( + sourceFile, + definition.textSpan.start + ), + end: ts.getLineAndCharacterOfPosition( + sourceFile, + definition.textSpan.start + definition.textSpan.length + ), + }, + }, + } + } + ) + } + ) }) } @@ -542,24 +555,28 @@ export class TypeScriptService { }) // Fetch the package.json of the dependency return this.updater.ensure(packageJsonUri, span).concat( - Observable.defer((): Observable => { - const packageJson: PackageJson = JSON.parse(this.inMemoryFileSystem.getContent(packageJsonUri)) - const { name, version } = packageJson - if (!name) { - return Observable.empty() - } - // Used by the LSP proxy to shortcut database lookup of repo URL for PackageDescriptor - let repoURL: string | undefined - if (name.startsWith('@types/')) { - // if the dependency package is an @types/ package, point the repo to DefinitelyTyped - repoURL = 'https://github.com/DefinitelyTyped/DefinitelyTyped' - } else { - // else use repository field from package.json - repoURL = - typeof packageJson.repository === 'object' ? packageJson.repository.url : undefined + Observable.defer( + (): Observable => { + const packageJson: PackageJson = JSON.parse( + this.inMemoryFileSystem.getContent(packageJsonUri) + ) + const { name, version } = packageJson + if (!name) { + return Observable.empty() + } + // Used by the LSP proxy to shortcut database lookup of repo URL for PackageDescriptor + let repoURL: string | undefined + if (name.startsWith('@types/')) { + // if the dependency package is an @types/ package, point the repo to DefinitelyTyped + repoURL = 'https://github.com/DefinitelyTyped/DefinitelyTyped' + } else { + // else use repository field from package.json + repoURL = + typeof packageJson.repository === 'object' ? packageJson.repository.url : undefined + } + return Observable.of({ name, version, repoURL }) } - return Observable.of({ name, version, repoURL }) - }) + ) ) } else { // The symbol is defined in the root package of the workspace, not in a dependency @@ -606,72 +623,74 @@ export class TypeScriptService { return this.projectManager .ensureReferencedFiles(uri, undefined, undefined, span) .toArray() - .map((): Hover => { - const fileName: string = uri2path(uri) - const configuration = this.projectManager.getConfiguration(fileName) - configuration.ensureBasicFiles(span) + .map( + (): Hover => { + const fileName: string = uri2path(uri) + const configuration = this.projectManager.getConfiguration(fileName) + configuration.ensureBasicFiles(span) - const sourceFile = this._getSourceFile(configuration, fileName, span) - if (!sourceFile) { - throw new Error(`Unknown text document ${uri}`) - } - const offset: number = ts.getPositionOfLineAndCharacter( - sourceFile, - params.position.line, - params.position.character - ) - const info = configuration.getService().getQuickInfoAtPosition(fileName, offset) - if (!info) { - return { contents: [] } - } - const contents: (MarkedString | string)[] = [] - // Add declaration without the kind - const declaration = ts.displayPartsToString(info.displayParts).replace(/^\(.+?\)\s+/, '') - contents.push({ language: 'typescript', value: declaration }) - // Add kind with modifiers, e.g. "method (private, ststic)", "class (exported)" - if (info.kind) { - let kind = '**' + info.kind + '**' - const modifiers = info.kindModifiers - .split(',') - // Filter out some quirks like "constructor (exported)" - .filter( - mod => - mod && - (mod !== ts.ScriptElementKindModifier.exportedModifier || - info.kind !== ts.ScriptElementKind.constructorImplementationElement) - ) - // Make proper adjectives - .map(mod => { - switch (mod) { - case ts.ScriptElementKindModifier.ambientModifier: - return 'ambient' - case ts.ScriptElementKindModifier.exportedModifier: - return 'exported' - default: - return mod - } - }) - if (modifiers.length > 0) { - kind += ' _(' + modifiers.join(', ') + ')_' + const sourceFile = this._getSourceFile(configuration, fileName, span) + if (!sourceFile) { + throw new Error(`Unknown text document ${uri}`) + } + const offset: number = ts.getPositionOfLineAndCharacter( + sourceFile, + params.position.line, + params.position.character + ) + const info = configuration.getService().getQuickInfoAtPosition(fileName, offset) + if (!info) { + return { contents: [] } + } + const contents: (MarkedString | string)[] = [] + // Add declaration without the kind + const declaration = ts.displayPartsToString(info.displayParts).replace(/^\(.+?\)\s+/, '') + contents.push({ language: 'typescript', value: declaration }) + // Add kind with modifiers, e.g. "method (private, ststic)", "class (exported)" + if (info.kind) { + let kind = '**' + info.kind + '**' + const modifiers = info.kindModifiers + .split(',') + // Filter out some quirks like "constructor (exported)" + .filter( + mod => + mod && + (mod !== ts.ScriptElementKindModifier.exportedModifier || + info.kind !== ts.ScriptElementKind.constructorImplementationElement) + ) + // Make proper adjectives + .map(mod => { + switch (mod) { + case ts.ScriptElementKindModifier.ambientModifier: + return 'ambient' + case ts.ScriptElementKindModifier.exportedModifier: + return 'exported' + default: + return mod + } + }) + if (modifiers.length > 0) { + kind += ' _(' + modifiers.join(', ') + ')_' + } + contents.push(kind) + } + // Add documentation + const documentation = ts.displayPartsToString(info.documentation) + if (documentation) { + contents.push(documentation) + } + const start = ts.getLineAndCharacterOfPosition(sourceFile, info.textSpan.start) + const end = ts.getLineAndCharacterOfPosition(sourceFile, info.textSpan.start + info.textSpan.length) + + return { + contents, + range: { + start, + end, + }, } - contents.push(kind) - } - // Add documentation - const documentation = ts.displayPartsToString(info.documentation) - if (documentation) { - contents.push(documentation) - } - const start = ts.getLineAndCharacterOfPosition(sourceFile, info.textSpan.start) - const end = ts.getLineAndCharacterOfPosition(sourceFile, info.textSpan.start + info.textSpan.length) - - return { - contents, - range: { - start, - end, - }, } - }) + ) } /** @@ -725,25 +744,27 @@ export class TypeScriptService { // Filter references in node_modules !reference.fileName.includes('/node_modules/') ) - .map((reference): Location => { - const sourceFile = program.getSourceFile(reference.fileName) - if (!sourceFile) { - throw new Error(`Source file ${reference.fileName} does not exist`) - } - // Convert offset to line/character position - const start = ts.getLineAndCharacterOfPosition(sourceFile, reference.textSpan.start) - const end = ts.getLineAndCharacterOfPosition( - sourceFile, - reference.textSpan.start + reference.textSpan.length - ) - return { - uri: path2uri(reference.fileName), - range: { - start, - end, - }, + .map( + (reference): Location => { + const sourceFile = program.getSourceFile(reference.fileName) + if (!sourceFile) { + throw new Error(`Source file ${reference.fileName} does not exist`) + } + // Convert offset to line/character position + const start = ts.getLineAndCharacterOfPosition(sourceFile, reference.textSpan.start) + const end = ts.getLineAndCharacterOfPosition( + sourceFile, + reference.textSpan.start + reference.textSpan.length + ) + return { + uri: path2uri(reference.fileName), + range: { + start, + end, + }, + } } - }) + ) }) ) .map((location: Location): Operation => ({ op: 'add', path: '/-', value: location })) @@ -769,87 +790,91 @@ export class TypeScriptService { const scores: number[] = [] let observable = this.isDefinitelyTyped - .mergeMap((isDefinitelyTyped: boolean): Observable<[number, SymbolInformation]> => { - // Use special logic for DefinitelyTyped - // Search only in the correct subdirectory for the given PackageDescriptor - if (isDefinitelyTyped) { - // Error if not passed a SymbolDescriptor query with an `@types` PackageDescriptor - if ( - !params.symbol || - !params.symbol.package || - !params.symbol.package.name || - !params.symbol.package.name.startsWith('@types/') - ) { - return Observable.throw( - new Error( - 'workspace/symbol on DefinitelyTyped is only supported with a SymbolDescriptor query with an @types PackageDescriptor' + .mergeMap( + (isDefinitelyTyped: boolean): Observable<[number, SymbolInformation]> => { + // Use special logic for DefinitelyTyped + // Search only in the correct subdirectory for the given PackageDescriptor + if (isDefinitelyTyped) { + // Error if not passed a SymbolDescriptor query with an `@types` PackageDescriptor + if ( + !params.symbol || + !params.symbol.package || + !params.symbol.package.name || + !params.symbol.package.name.startsWith('@types/') + ) { + return Observable.throw( + new Error( + 'workspace/symbol on DefinitelyTyped is only supported with a SymbolDescriptor query with an @types PackageDescriptor' + ) ) - ) - } + } - // Fetch all files in the package subdirectory - // All packages are in the types/ subdirectory - const normRootUri = this.rootUri.endsWith('/') ? this.rootUri : this.rootUri + '/' - const packageRootUri = normRootUri + params.symbol.package.name.substr(1) + '/' - - return this.updater - .ensureStructure(span) - .concat(Observable.defer(() => observableFromIterable(this.inMemoryFileSystem.uris()))) - .filter(uri => uri.startsWith(packageRootUri)) - .mergeMap(uri => this.updater.ensure(uri, span)) - .concat( - Observable.defer(() => { - span.log({ event: 'fetched package files' }) - const config = this.projectManager.getParentConfiguration(packageRootUri, 'ts') - if (!config) { - throw new Error(`Could not find tsconfig for ${packageRootUri}`) - } - // Don't match PackageDescriptor on symbols - return this._getSymbolsInConfig(config, omit(params.symbol!, 'package'), span) - }) - ) - } - // Regular workspace symbol search - // Search all symbols in own code, but not in dependencies - return ( - this.projectManager - .ensureOwnFiles(span) - .concat( - Observable.defer(() => { - if (params.symbol && params.symbol.package && params.symbol.package.name) { - // If SymbolDescriptor query with PackageDescriptor, search for package.jsons with matching package name - return ( - observableFromIterable(this.packageManager.packageJsonUris()) - .filter( - packageJsonUri => - (JSON.parse( - this.inMemoryFileSystem.getContent(packageJsonUri) - ) as PackageJson).name === params.symbol!.package!.name - ) - // Find their parent and child tsconfigs - .mergeMap(packageJsonUri => - Observable.merge( - castArray( - this.projectManager.getParentConfiguration(packageJsonUri) || [] - ), - // Search child directories starting at the directory of the package.json - observableFromIterable( - this.projectManager.getChildConfigurations( - url.resolve(packageJsonUri, '.') + // Fetch all files in the package subdirectory + // All packages are in the types/ subdirectory + const normRootUri = this.rootUri.endsWith('/') ? this.rootUri : this.rootUri + '/' + const packageRootUri = normRootUri + params.symbol.package.name.substr(1) + '/' + + return this.updater + .ensureStructure(span) + .concat(Observable.defer(() => observableFromIterable(this.inMemoryFileSystem.uris()))) + .filter(uri => uri.startsWith(packageRootUri)) + .mergeMap(uri => this.updater.ensure(uri, span)) + .concat( + Observable.defer(() => { + span.log({ event: 'fetched package files' }) + const config = this.projectManager.getParentConfiguration(packageRootUri, 'ts') + if (!config) { + throw new Error(`Could not find tsconfig for ${packageRootUri}`) + } + // Don't match PackageDescriptor on symbols + return this._getSymbolsInConfig(config, omit(params.symbol!, 'package'), span) + }) + ) + } + // Regular workspace symbol search + // Search all symbols in own code, but not in dependencies + return ( + this.projectManager + .ensureOwnFiles(span) + .concat( + Observable.defer(() => { + if (params.symbol && params.symbol.package && params.symbol.package.name) { + // If SymbolDescriptor query with PackageDescriptor, search for package.jsons with matching package name + return ( + observableFromIterable(this.packageManager.packageJsonUris()) + .filter( + packageJsonUri => + (JSON.parse( + this.inMemoryFileSystem.getContent(packageJsonUri) + ) as PackageJson).name === params.symbol!.package!.name + ) + // Find their parent and child tsconfigs + .mergeMap(packageJsonUri => + Observable.merge( + castArray( + this.projectManager.getParentConfiguration( + packageJsonUri + ) || [] + ), + // Search child directories starting at the directory of the package.json + observableFromIterable( + this.projectManager.getChildConfigurations( + url.resolve(packageJsonUri, '.') + ) ) ) ) - ) - ) - } - // Else search all tsconfigs in the workspace - return observableFromIterable(this.projectManager.configurations()) - }) - ) - // If PackageDescriptor is given, only search project with the matching package name - .mergeMap(config => this._getSymbolsInConfig(config, params.query || params.symbol, span)) - ) - }) + ) + } + // Else search all tsconfigs in the workspace + return observableFromIterable(this.projectManager.configurations()) + }) + ) + // If PackageDescriptor is given, only search project with the matching package name + .mergeMap(config => this._getSymbolsInConfig(config, params.query || params.symbol, span)) + ) + } + ) // Filter duplicate symbols // There may be few configurations that contain the same file(s) // or files from different configurations may refer to the same file(s) @@ -1003,16 +1028,18 @@ export class TypeScriptService { return symbol }) }) - .map((symbol: SymbolDescriptor): ReferenceInformation => ({ - symbol, - reference: { - uri: locationUri(source.fileName), - range: { - start: ts.getLineAndCharacterOfPosition(source, node.pos), - end: ts.getLineAndCharacterOfPosition(source, node.end), + .map( + (symbol: SymbolDescriptor): ReferenceInformation => ({ + symbol, + reference: { + uri: locationUri(source.fileName), + range: { + start: ts.getLineAndCharacterOfPosition(source, node.pos), + end: ts.getLineAndCharacterOfPosition(source, node.end), + }, }, - }, - })) + }) + ) } catch (err) { // Continue with next node on error // Workaround for https://github.com/Microsoft/TypeScript/issues/15219 @@ -1053,72 +1080,82 @@ export class TypeScriptService { */ public workspaceXpackages(params = {}, span = new Span()): Observable { return this.isDefinitelyTyped - .mergeMap((isDefinitelyTyped: boolean): Observable => { - // In DefinitelyTyped, report all @types/ packages - if (isDefinitelyTyped) { - const typesUri = url.resolve(this.rootUri, 'types/') + .mergeMap( + (isDefinitelyTyped: boolean): Observable => { + // In DefinitelyTyped, report all @types/ packages + if (isDefinitelyTyped) { + const typesUri = url.resolve(this.rootUri, 'types/') + return ( + observableFromIterable(this.inMemoryFileSystem.uris()) + // Find all types/ subdirectories + .filter(uri => uri.startsWith(typesUri)) + // Get the directory names + .map( + (uri): PackageInformation => ({ + package: { + name: + '@types/' + + decodeURIComponent(uri.substr(typesUri.length).split('/')[0]), + // TODO report a version by looking at subfolders like v6 + }, + // TODO parse /// comments in .d.ts files for collecting dependencies between @types packages + dependencies: [], + }) + ) + ) + } + // For other workspaces, search all package.json files return ( - observableFromIterable(this.inMemoryFileSystem.uris()) - // Find all types/ subdirectories - .filter(uri => uri.startsWith(typesUri)) - // Get the directory names - .map((uri): PackageInformation => ({ - package: { - name: '@types/' + decodeURIComponent(uri.substr(typesUri.length).split('/')[0]), - // TODO report a version by looking at subfolders like v6 - }, - // TODO parse /// comments in .d.ts files for collecting dependencies between @types packages - dependencies: [], - })) + this.projectManager + .ensureModuleStructure(span) + // Iterate all files + .concat(Observable.defer(() => observableFromIterable(this.inMemoryFileSystem.uris()))) + // Filter own package.jsons + .filter(uri => uri.includes('/package.json') && !uri.includes('/node_modules/')) + // Map to contents of package.jsons + .mergeMap(uri => this.packageManager.getPackageJson(uri)) + // Map each package.json to a PackageInformation + .mergeMap(packageJson => { + if (!packageJson.name) { + return [] + } + const packageDescriptor: PackageDescriptor = { + name: packageJson.name, + version: packageJson.version, + repoURL: + (typeof packageJson.repository === 'object' && packageJson.repository.url) || + undefined, + } + // Collect all dependencies for this package.json + return ( + Observable.from(DEPENDENCY_KEYS) + .filter(key => !!packageJson[key]) + // Get [name, version] pairs + .mergeMap(key => toPairs(packageJson[key])) + // Map to DependencyReferences + .map( + ([name, version]): DependencyReference => ({ + attributes: { + name, + version, + }, + hints: { + dependeePackageName: packageJson.name, + }, + }) + ) + .toArray() + .map( + (dependencies): PackageInformation => ({ + package: packageDescriptor, + dependencies, + }) + ) + ) + }) ) } - // For other workspaces, search all package.json files - return ( - this.projectManager - .ensureModuleStructure(span) - // Iterate all files - .concat(Observable.defer(() => observableFromIterable(this.inMemoryFileSystem.uris()))) - // Filter own package.jsons - .filter(uri => uri.includes('/package.json') && !uri.includes('/node_modules/')) - // Map to contents of package.jsons - .mergeMap(uri => this.packageManager.getPackageJson(uri)) - // Map each package.json to a PackageInformation - .mergeMap(packageJson => { - if (!packageJson.name) { - return [] - } - const packageDescriptor: PackageDescriptor = { - name: packageJson.name, - version: packageJson.version, - repoURL: - (typeof packageJson.repository === 'object' && packageJson.repository.url) || - undefined, - } - // Collect all dependencies for this package.json - return ( - Observable.from(DEPENDENCY_KEYS) - .filter(key => !!packageJson[key]) - // Get [name, version] pairs - .mergeMap(key => toPairs(packageJson[key])) - // Map to DependencyReferences - .map(([name, version]): DependencyReference => ({ - attributes: { - name, - version, - }, - hints: { - dependeePackageName: packageJson.name, - }, - })) - .toArray() - .map((dependencies): PackageInformation => ({ - package: packageDescriptor, - dependencies, - })) - ) - }) - ) - }) + ) .map((packageInfo): Operation => ({ op: 'add', path: '/-', value: packageInfo })) .startWith({ op: 'add', path: '', value: [] }) } @@ -1146,15 +1183,17 @@ export class TypeScriptService { .filter(key => !!packageJson[key]) // Get [name, version] pairs .mergeMap(key => toPairs(packageJson[key])) - .map(([name, version]): DependencyReference => ({ - attributes: { - name, - version, - }, - hints: { - dependeePackageName: packageJson.name, - }, - })) + .map( + ([name, version]): DependencyReference => ({ + attributes: { + name, + version, + }, + hints: { + dependeePackageName: packageJson.name, + }, + }) + ) ) .map((dependency): Operation => ({ op: 'add', path: '/-', value: dependency })) .startWith({ op: 'add', path: '', value: [] }) @@ -1292,49 +1331,55 @@ export class TypeScriptService { return this.projectManager .ensureReferencedFiles(uri, undefined, undefined, span) .toArray() - .map((): SignatureHelp => { - const filePath = uri2path(uri) - const configuration = this.projectManager.getConfiguration(filePath) - configuration.ensureBasicFiles(span) + .map( + (): SignatureHelp => { + const filePath = uri2path(uri) + const configuration = this.projectManager.getConfiguration(filePath) + configuration.ensureBasicFiles(span) - const sourceFile = this._getSourceFile(configuration, filePath, span) - if (!sourceFile) { - throw new Error(`expected source file ${filePath} to exist in configuration`) - } - const offset: number = ts.getPositionOfLineAndCharacter( - sourceFile, - params.position.line, - params.position.character - ) + const sourceFile = this._getSourceFile(configuration, filePath, span) + if (!sourceFile) { + throw new Error(`expected source file ${filePath} to exist in configuration`) + } + const offset: number = ts.getPositionOfLineAndCharacter( + sourceFile, + params.position.line, + params.position.character + ) - const signatures: ts.SignatureHelpItems | undefined = configuration - .getService() - .getSignatureHelpItems(filePath, offset, undefined) - if (!signatures) { - return { signatures: [], activeParameter: 0, activeSignature: 0 } - } + const signatures: + | ts.SignatureHelpItems + | undefined = configuration.getService().getSignatureHelpItems(filePath, offset, undefined) + if (!signatures) { + return { signatures: [], activeParameter: 0, activeSignature: 0 } + } + + const signatureInformations = signatures.items.map( + (item): SignatureInformation => { + const prefix = ts.displayPartsToString(item.prefixDisplayParts) + const params = item.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(', ') + const suffix = ts.displayPartsToString(item.suffixDisplayParts) + const parameters = item.parameters.map( + (p): ParameterInformation => ({ + label: ts.displayPartsToString(p.displayParts), + documentation: ts.displayPartsToString(p.documentation), + }) + ) + return { + label: prefix + params + suffix, + documentation: ts.displayPartsToString(item.documentation), + parameters, + } + } + ) - const signatureInformations = signatures.items.map((item): SignatureInformation => { - const prefix = ts.displayPartsToString(item.prefixDisplayParts) - const params = item.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(', ') - const suffix = ts.displayPartsToString(item.suffixDisplayParts) - const parameters = item.parameters.map((p): ParameterInformation => ({ - label: ts.displayPartsToString(p.displayParts), - documentation: ts.displayPartsToString(p.documentation), - })) return { - label: prefix + params + suffix, - documentation: ts.displayPartsToString(item.documentation), - parameters, + signatures: signatureInformations, + activeSignature: signatures.selectedItemIndex, + activeParameter: signatures.argumentIndex, } - }) - - return { - signatures: signatureInformations, - activeSignature: signatures.selectedItemIndex, - activeParameter: signatures.argumentIndex, } - }) + ) .map(signatureHelp => ({ op: 'add', path: '', value: signatureHelp } as Operation)) } @@ -1385,15 +1430,17 @@ export class TypeScriptService { .getCodeFixesAtPosition(filePath, start, end, errorCodes, this.settings.format || {}, {}) || [] ) }) - .map((action: ts.CodeAction): Operation => ({ - op: 'add', - path: '/-', - value: { - title: action.description, - command: 'codeFix', - arguments: action.changes, - } as Command, - })) + .map( + (action: ts.CodeAction): Operation => ({ + op: 'add', + path: '/-', + value: { + title: action.description, + command: 'codeFix', + arguments: action.changes, + } as Command, + }) + ) .startWith({ op: 'add', path: '', value: [] } as Operation) } @@ -1445,13 +1492,15 @@ export class TypeScriptService { throw new Error(`Expected source file ${change.fileName} to exist in configuration`) } const uri = path2uri(change.fileName) - changes[uri] = change.textChanges.map(({ span, newText }): TextEdit => ({ - range: { - start: ts.getLineAndCharacterOfPosition(sourceFile, span.start), - end: ts.getLineAndCharacterOfPosition(sourceFile, span.start + span.length), - }, - newText, - })) + changes[uri] = change.textChanges.map( + ({ span, newText }): TextEdit => ({ + range: { + start: ts.getLineAndCharacterOfPosition(sourceFile, span.start), + end: ts.getLineAndCharacterOfPosition(sourceFile, span.start + span.length), + }, + newText, + }) + ) } return this.client.workspaceApplyEdit({ edit: { changes } }, span) @@ -1497,31 +1546,35 @@ export class TypeScriptService { return Observable.from( configuration.getService().findRenameLocations(filePath, position, false, true) || [] - ).map((location: ts.RenameLocation): [string, TextEdit] => { - const sourceFile = this._getSourceFile(configuration, location.fileName, span) - if (!sourceFile) { - throw new Error(`expected source file ${location.fileName} to exist in configuration`) + ).map( + (location: ts.RenameLocation): [string, TextEdit] => { + const sourceFile = this._getSourceFile(configuration, location.fileName, span) + if (!sourceFile) { + throw new Error(`expected source file ${location.fileName} to exist in configuration`) + } + const editUri = path2uri(location.fileName) + const start = ts.getLineAndCharacterOfPosition(sourceFile, location.textSpan.start) + const end = ts.getLineAndCharacterOfPosition( + sourceFile, + location.textSpan.start + location.textSpan.length + ) + const edit: TextEdit = { range: { start, end }, newText: params.newName } + return [editUri, edit] } - const editUri = path2uri(location.fileName) - const start = ts.getLineAndCharacterOfPosition(sourceFile, location.textSpan.start) - const end = ts.getLineAndCharacterOfPosition( - sourceFile, - location.textSpan.start + location.textSpan.length - ) - const edit: TextEdit = { range: { start, end }, newText: params.newName } - return [editUri, edit] - }) + ) }) ) - .map(([uri, edit]): Operation => { - // if file has no edit yet, initialize array - if (!editUris.has(uri)) { - editUris.add(uri) - return { op: 'add', path: JSONPTR`/changes/${uri}`, value: [edit] } + .map( + ([uri, edit]): Operation => { + // if file has no edit yet, initialize array + if (!editUris.has(uri)) { + editUris.add(uri) + return { op: 'add', path: JSONPTR`/changes/${uri}`, value: [edit] } + } + // else append to array + return { op: 'add', path: JSONPTR`/changes/${uri}/-`, value: edit } } - // else append to array - return { op: 'add', path: JSONPTR`/changes/${uri}/-`, value: edit } - }) + ) .startWith({ op: 'add', path: '', value: { changes: {} } as WorkspaceEdit } as Operation) }