javascript-typescript-langserver
Version: 
Implementation of the Language Server Protocol for JavaScript and TypeScript
1,127 lines (1,126 loc) • 145 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
const fast_json_patch_1 = require("fast-json-patch");
const rxjs_1 = require("rxjs");
const sinon = require("sinon");
const ts = require("typescript");
const vscode_languageserver_1 = require("vscode-languageserver");
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
const lang_handler_1 = require("../lang-handler");
const util_1 = require("../util");
chai.use(chaiAsPromised);
const assert = chai.assert;
const DEFAULT_CAPABILITIES = {
    xcontentProvider: true,
    xfilesProvider: true,
};
/**
 * Returns a function that initializes the test context with a TypeScriptService instance and initializes it (to be used in `beforeEach`)
 *
 * @param createService A factory that creates the TypeScript service. Allows to test subclasses of TypeScriptService
 * @param files A Map from URI to file content of files that should be available in the workspace
 */
exports.initializeTypeScriptService = (createService, rootUri, files, clientCapabilities = DEFAULT_CAPABILITIES) => function () {
    return __awaiter(this, void 0, void 0, function* () {
        // Stub client
        this.client = sinon.createStubInstance(lang_handler_1.RemoteLanguageClient);
        this.client.textDocumentXcontent.callsFake((params) => {
            if (!files.has(params.textDocument.uri)) {
                return rxjs_1.Observable.throw(new Error(`Text document ${params.textDocument.uri} does not exist`));
            }
            return rxjs_1.Observable.of({
                uri: params.textDocument.uri,
                text: files.get(params.textDocument.uri),
                version: 1,
                languageId: '',
            });
        });
        this.client.workspaceXfiles.callsFake((params) => util_1.observableFromIterable(files.keys())
            .map(uri => ({ uri }))
            .toArray());
        this.client.xcacheGet.callsFake(() => rxjs_1.Observable.of(null));
        this.client.workspaceApplyEdit.callsFake(() => rxjs_1.Observable.of({ applied: true }));
        this.service = createService(this.client);
        yield this.service
            .initialize({
            processId: process.pid,
            rootUri,
            capabilities: clientCapabilities || DEFAULT_CAPABILITIES,
            workspaceFolders: [
                {
                    uri: rootUri,
                    name: 'test',
                },
            ],
        })
            .toPromise();
    });
};
/**
 * Shuts the TypeScriptService down (to be used in `afterEach()`)
 */
function shutdownTypeScriptService() {
    return __awaiter(this, void 0, void 0, function* () {
        yield this.service.shutdown().toPromise();
    });
}
exports.shutdownTypeScriptService = shutdownTypeScriptService;
/**
 * Describe a TypeScriptService class
 *
 * @param createService Factory function to create the TypeScriptService instance to describe
 */
function describeTypeScriptService(createService, shutdownService = shutdownTypeScriptService, rootUri) {
    describe('Workspace without project files', () => {
        beforeEach(exports.initializeTypeScriptService(createService, rootUri, new Map([
            [rootUri + 'a.ts', 'const abc = 1; console.log(abc);'],
            [rootUri + 'foo/b.ts', ['/* This is class Foo */', 'export class Foo {}'].join('\n')],
            [rootUri + 'foo/c.ts', 'import {Foo} from "./b";'],
            [rootUri + 'd.ts', ['export interface I {', '  target: string;', '}'].join('\n')],
            [
                rootUri + 'local_callback.ts',
                'function local(): void { function act(handle: () => void): void { handle() } }',
            ],
            [
                rootUri + 'e.ts',
                [
                    'import * as d from "./d";',
                    '',
                    'let i: d.I = { target: "hi" };',
                    'let target = i.target;',
                ].join('\n'),
            ],
            [rootUri + 'foo/f.ts', ['import {Foo} from "./b";', '', 'let foo: Foo = Object({});'].join('\n')],
            [rootUri + 'foo/g.ts', ['class Foo = {}', '', 'let foo: Foo = Object({});'].join('\n')],
        ])));
        afterEach(shutdownService);
        describe('textDocumentDefinition()', () => {
            specify('in same file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentDefinition({
                        textDocument: {
                            uri: rootUri + 'a.ts',
                        },
                        position: {
                            line: 0,
                            character: 29,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            uri: rootUri + 'a.ts',
                            range: {
                                start: {
                                    line: 0,
                                    character: 6,
                                },
                                end: {
                                    line: 0,
                                    character: 9,
                                },
                            },
                        },
                    ]);
                });
            });
            specify('on keyword (non-null)', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentDefinition({
                        textDocument: {
                            uri: rootUri + 'a.ts',
                        },
                        position: {
                            line: 0,
                            character: 0,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, []);
                });
            });
            specify('in other file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentDefinition({
                        textDocument: {
                            uri: rootUri + 'foo/c.ts',
                        },
                        position: {
                            line: 0,
                            character: 9,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            uri: rootUri + 'foo/b.ts',
                            range: {
                                start: {
                                    line: 1,
                                    character: 13,
                                },
                                end: {
                                    line: 1,
                                    character: 16,
                                },
                            },
                        },
                    ]);
                });
            });
        });
        describe('textDocumentTypeDefinition()', () => {
            specify('in other file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentTypeDefinition({
                        textDocument: {
                            uri: rootUri + 'foo/f.ts',
                        },
                        position: {
                            line: 2,
                            character: 5,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            uri: rootUri + 'foo/b.ts',
                            range: {
                                start: {
                                    line: 1,
                                    character: 13,
                                },
                                end: {
                                    line: 1,
                                    character: 16,
                                },
                            },
                        },
                    ]);
                });
            });
            specify('in same file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentTypeDefinition({
                        textDocument: {
                            uri: rootUri + 'foo/g.ts',
                        },
                        position: {
                            line: 2,
                            character: 5,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            uri: rootUri + 'foo/g.ts',
                            range: {
                                start: {
                                    line: 0,
                                    character: 6,
                                },
                                end: {
                                    line: 0,
                                    character: 9,
                                },
                            },
                        },
                    ]);
                });
            });
        });
        describe('textDocumentXdefinition()', () => {
            specify('on interface field reference', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentXdefinition({
                        textDocument: {
                            uri: rootUri + 'e.ts',
                        },
                        position: {
                            line: 3,
                            character: 15,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            location: {
                                uri: rootUri + 'd.ts',
                                range: {
                                    start: {
                                        line: 1,
                                        character: 2,
                                    },
                                    end: {
                                        line: 1,
                                        character: 8,
                                    },
                                },
                            },
                            symbol: {
                                filePath: 'd.ts',
                                containerName: 'd.I',
                                containerKind: '',
                                kind: 'property',
                                name: 'target',
                            },
                        },
                    ]);
                });
            });
            specify('in same file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentXdefinition({
                        textDocument: {
                            uri: rootUri + 'a.ts',
                        },
                        position: {
                            line: 0,
                            character: 29,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            location: {
                                uri: rootUri + 'a.ts',
                                range: {
                                    start: {
                                        line: 0,
                                        character: 6,
                                    },
                                    end: {
                                        line: 0,
                                        character: 9,
                                    },
                                },
                            },
                            symbol: {
                                filePath: 'a.ts',
                                containerName: '"a"',
                                containerKind: 'module',
                                kind: 'const',
                                name: 'abc',
                            },
                        },
                    ]);
                });
            });
        });
        describe('textDocumentHover()', () => {
            specify('in same file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentHover({
                        textDocument: {
                            uri: rootUri + 'a.ts',
                        },
                        position: {
                            line: 0,
                            character: 29,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, {
                        range: {
                            start: {
                                line: 0,
                                character: 27,
                            },
                            end: {
                                line: 0,
                                character: 30,
                            },
                        },
                        contents: [{ language: 'typescript', value: 'const abc: 1' }, '**const**'],
                    });
                });
            });
            specify('local function with callback argument', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentHover({
                        textDocument: {
                            uri: rootUri + 'local_callback.ts',
                        },
                        position: {
                            line: 0,
                            character: 36,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, {
                        range: {
                            start: {
                                line: 0,
                                character: 34,
                            },
                            end: {
                                line: 0,
                                character: 37,
                            },
                        },
                        contents: [
                            { language: 'typescript', value: 'act(handle: () => void): void' },
                            '**local function**',
                        ],
                    });
                });
            });
            specify('in other file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentHover({
                        textDocument: {
                            uri: rootUri + 'foo/c.ts',
                        },
                        position: {
                            line: 0,
                            character: 9,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, {
                        range: {
                            end: {
                                line: 0,
                                character: 11,
                            },
                            start: {
                                line: 0,
                                character: 8,
                            },
                        },
                        contents: [{ language: 'typescript', value: 'class Foo\nimport Foo' }, '**alias**'],
                    });
                });
            });
            specify('over keyword (non-null)', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentHover({
                        textDocument: {
                            uri: rootUri + 'a.ts',
                        },
                        position: {
                            line: 0,
                            character: 0,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, { contents: [] });
                });
            });
            specify('over non-existent file', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    yield Promise.resolve(assert.isRejected(this.service
                        .textDocumentHover({
                        textDocument: {
                            uri: rootUri + 'foo/a.ts',
                        },
                        position: {
                            line: 0,
                            character: 0,
                        },
                    })
                        .toPromise()));
                });
            });
        });
    });
    describe('Workspace with typings directory', () => {
        beforeEach(exports.initializeTypeScriptService(createService, rootUri, new Map([
            [rootUri + 'src/a.ts', "import * as m from 'dep';"],
            [rootUri + 'typings/dep.d.ts', "declare module 'dep' {}"],
            [
                rootUri + 'src/tsconfig.json',
                [
                    '{',
                    '  "compilerOptions": {',
                    '    "target": "ES5",',
                    '    "module": "commonjs",',
                    '    "sourceMap": true,',
                    '    "noImplicitAny": false,',
                    '    "removeComments": false,',
                    '    "preserveConstEnums": true',
                    '  }',
                    '}',
                ].join('\n'),
            ],
            [rootUri + 'src/tsd.d.ts', '/// <reference path="../typings/dep.d.ts" />'],
            [rootUri + 'src/dir/index.ts', 'import * as m from "dep";'],
        ])));
        afterEach(shutdownService);
        describe('textDocumentDefinition()', () => {
            specify('with tsd.d.ts', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .textDocumentDefinition({
                        textDocument: {
                            uri: rootUri + 'src/dir/index.ts',
                        },
                        position: {
                            line: 0,
                            character: 20,
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            uri: rootUri + 'typings/dep.d.ts',
                            range: {
                                start: {
                                    line: 0,
                                    character: 15,
                                },
                                end: {
                                    line: 0,
                                    character: 20,
                                },
                            },
                        },
                    ]);
                });
            });
            describe('on file in project root', () => {
                specify('on import alias', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .textDocumentDefinition({
                            textDocument: {
                                uri: rootUri + 'src/a.ts',
                            },
                            position: {
                                line: 0,
                                character: 12,
                            },
                        })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result, [
                            {
                                uri: rootUri + 'typings/dep.d.ts',
                                range: {
                                    start: {
                                        line: 0,
                                        character: 15,
                                    },
                                    end: {
                                        line: 0,
                                        character: 20,
                                    },
                                },
                            },
                        ]);
                    });
                });
                specify('on module name', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .textDocumentDefinition({
                            textDocument: {
                                uri: rootUri + 'src/a.ts',
                            },
                            position: {
                                line: 0,
                                character: 20,
                            },
                        })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result, [
                            {
                                uri: rootUri + 'typings/dep.d.ts',
                                range: {
                                    start: {
                                        line: 0,
                                        character: 15,
                                    },
                                    end: {
                                        line: 0,
                                        character: 20,
                                    },
                                },
                            },
                        ]);
                    });
                });
            });
        });
    });
    describe('DefinitelyTyped', () => {
        beforeEach(exports.initializeTypeScriptService(createService, rootUri, new Map([
            [
                rootUri + 'package.json',
                JSON.stringify({
                    private: true,
                    name: 'definitely-typed',
                    version: '0.0.1',
                    homepage: 'https://github.com/DefinitelyTyped/DefinitelyTyped',
                    repository: {
                        type: 'git',
                        url: 'git+https://github.com/DefinitelyTyped/DefinitelyTyped.git',
                    },
                    license: 'MIT',
                    bugs: {
                        url: 'https://github.com/DefinitelyTyped/DefinitelyTyped/issues',
                    },
                    engines: {
                        node: '>= 6.9.1',
                    },
                    scripts: {
                        'compile-scripts': 'tsc -p scripts',
                        'new-package': 'node scripts/new-package.js',
                        'not-needed': 'node scripts/not-needed.js',
                        lint: 'node scripts/lint.js',
                        test: 'node node_modules/types-publisher/bin/tester/test.js --run-from-definitely-typed --nProcesses 1',
                    },
                    devDependencies: {
                        'types-publisher': 'Microsoft/types-publisher#production',
                    },
                }, null, 4),
            ],
            [
                rootUri + 'types/resolve/index.d.ts',
                [
                    '/// <reference types="node" />',
                    '',
                    'type resolveCallback = (err: Error, resolved?: string) => void;',
                    'declare function resolve(id: string, cb: resolveCallback): void;',
                    '',
                ].join('\n'),
            ],
            [
                rootUri + 'types/resolve/tsconfig.json',
                JSON.stringify({
                    compilerOptions: {
                        module: 'commonjs',
                        lib: ['es6'],
                        noImplicitAny: true,
                        noImplicitThis: true,
                        strictNullChecks: false,
                        baseUrl: '../',
                        typeRoots: ['../'],
                        types: [],
                        noEmit: true,
                        forceConsistentCasingInFileNames: true,
                    },
                    files: ['index.d.ts'],
                }),
            ],
            [
                rootUri + 'types/notResolve/index.d.ts',
                [
                    '/// <reference types="node" />',
                    '',
                    'type resolveCallback = (err: Error, resolved?: string) => void;',
                    'declare function resolve(id: string, cb: resolveCallback): void;',
                    '',
                ].join('\n'),
            ],
            [
                rootUri + 'types/notResolve/tsconfig.json',
                JSON.stringify({
                    compilerOptions: {
                        module: 'commonjs',
                        lib: ['es6'],
                        noImplicitAny: true,
                        noImplicitThis: true,
                        strictNullChecks: false,
                        baseUrl: '../',
                        typeRoots: ['../'],
                        types: [],
                        noEmit: true,
                        forceConsistentCasingInFileNames: true,
                    },
                    files: ['index.d.ts'],
                }),
            ],
        ])));
        afterEach(shutdownService);
        describe('workspaceSymbol()', () => {
            it('should find a symbol by SymbolDescriptor query with name and package name', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .workspaceSymbol({
                        symbol: { name: 'resolveCallback', package: { name: '@types/resolve' } },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            kind: vscode_languageserver_types_1.SymbolKind.Variable,
                            location: {
                                range: {
                                    end: {
                                        character: 63,
                                        line: 2,
                                    },
                                    start: {
                                        character: 0,
                                        line: 2,
                                    },
                                },
                                uri: rootUri + 'types/resolve/index.d.ts',
                            },
                            name: 'resolveCallback',
                        },
                    ]);
                });
            });
            it('should find a symbol by SymbolDescriptor query with name, containerKind and package name', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .workspaceSymbol({
                        symbol: {
                            name: 'resolveCallback',
                            containerKind: 'module',
                            package: {
                                name: '@types/resolve',
                            },
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result[0], {
                        kind: vscode_languageserver_types_1.SymbolKind.Variable,
                        location: {
                            range: {
                                end: {
                                    character: 63,
                                    line: 2,
                                },
                                start: {
                                    character: 0,
                                    line: 2,
                                },
                            },
                            uri: rootUri + 'types/resolve/index.d.ts',
                        },
                        name: 'resolveCallback',
                    });
                });
            });
        });
    });
    describe('Workspace with root package.json', () => {
        beforeEach(exports.initializeTypeScriptService(createService, rootUri, new Map([
            [rootUri + 'a.ts', 'class a { foo() { const i = 1;} }'],
            [
                rootUri + 'foo/b.ts',
                'class b { bar: number; baz(): number { return this.bar;}}; function qux() {}',
            ],
            [rootUri + 'c.ts', 'import { x } from "dep/dep";'],
            [rootUri + 'package.json', JSON.stringify({ name: 'mypkg' })],
            [rootUri + 'node_modules/dep/dep.ts', 'export var x = 1;'],
            [rootUri + 'node_modules/dep/package.json', JSON.stringify({ name: 'dep' })],
        ])));
        afterEach(shutdownService);
        describe('workspaceSymbol()', () => {
            describe('with SymbolDescriptor query', () => {
                it('should find a symbol by name, kind and package name', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .workspaceSymbol({
                            symbol: {
                                name: 'a',
                                kind: 'class',
                                package: {
                                    name: 'mypkg',
                                },
                            },
                        })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result[0], {
                            kind: vscode_languageserver_types_1.SymbolKind.Class,
                            location: {
                                range: {
                                    end: {
                                        character: 33,
                                        line: 0,
                                    },
                                    start: {
                                        character: 0,
                                        line: 0,
                                    },
                                },
                                uri: rootUri + 'a.ts',
                            },
                            name: 'a',
                        });
                    });
                });
                it('should find a symbol by name, kind, package name and ignore package version', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .workspaceSymbol({
                            symbol: { name: 'a', kind: 'class', package: { name: 'mypkg', version: '203940234' } },
                        })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result[0], {
                            kind: vscode_languageserver_types_1.SymbolKind.Class,
                            location: {
                                range: {
                                    end: {
                                        character: 33,
                                        line: 0,
                                    },
                                    start: {
                                        character: 0,
                                        line: 0,
                                    },
                                },
                                uri: rootUri + 'a.ts',
                            },
                            name: 'a',
                        });
                    });
                });
                it('should find a symbol by name', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .workspaceSymbol({
                            symbol: {
                                name: 'a',
                            },
                        })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result, [
                            {
                                kind: vscode_languageserver_types_1.SymbolKind.Class,
                                location: {
                                    range: {
                                        end: {
                                            character: 33,
                                            line: 0,
                                        },
                                        start: {
                                            character: 0,
                                            line: 0,
                                        },
                                    },
                                    uri: rootUri + 'a.ts',
                                },
                                name: 'a',
                            },
                        ]);
                    });
                });
                it('should return no result if the PackageDescriptor does not match', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .workspaceSymbol({
                            symbol: {
                                name: 'a',
                                kind: 'class',
                                package: {
                                    name: 'not-mypkg',
                                },
                            },
                        })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result, []);
                    });
                });
            });
            describe('with text query', () => {
                it('should find a symbol', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .workspaceSymbol({ query: 'a' })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result, [
                            {
                                kind: vscode_languageserver_types_1.SymbolKind.Class,
                                location: {
                                    range: {
                                        end: {
                                            character: 33,
                                            line: 0,
                                        },
                                        start: {
                                            character: 0,
                                            line: 0,
                                        },
                                    },
                                    uri: rootUri + 'a.ts',
                                },
                                name: 'a',
                            },
                        ]);
                    });
                });
                it('should return all symbols for an empty query excluding dependencies', function () {
                    return __awaiter(this, void 0, void 0, function* () {
                        const result = yield this.service
                            .workspaceSymbol({ query: '' })
                            .reduce(fast_json_patch_1.applyReducer, null)
                            .toPromise();
                        assert.deepEqual(result, [
                            {
                                name: 'a',
                                kind: vscode_languageserver_types_1.SymbolKind.Class,
                                location: {
                                    uri: rootUri + 'a.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 0,
                                        },
                                        end: {
                                            line: 0,
                                            character: 33,
                                        },
                                    },
                                },
                            },
                            {
                                name: 'foo',
                                kind: vscode_languageserver_types_1.SymbolKind.Method,
                                location: {
                                    uri: rootUri + 'a.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 10,
                                        },
                                        end: {
                                            line: 0,
                                            character: 31,
                                        },
                                    },
                                },
                                containerName: 'a',
                            },
                            {
                                name: 'i',
                                kind: vscode_languageserver_types_1.SymbolKind.Constant,
                                location: {
                                    uri: rootUri + 'a.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 24,
                                        },
                                        end: {
                                            line: 0,
                                            character: 29,
                                        },
                                    },
                                },
                                containerName: 'foo',
                            },
                            {
                                name: '"c"',
                                kind: vscode_languageserver_types_1.SymbolKind.Module,
                                location: {
                                    uri: rootUri + 'c.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 0,
                                        },
                                        end: {
                                            line: 0,
                                            character: 28,
                                        },
                                    },
                                },
                            },
                            {
                                name: 'x',
                                containerName: '"c"',
                                kind: vscode_languageserver_types_1.SymbolKind.Variable,
                                location: {
                                    uri: rootUri + 'c.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 9,
                                        },
                                        end: {
                                            line: 0,
                                            character: 10,
                                        },
                                    },
                                },
                            },
                            {
                                name: 'b',
                                kind: vscode_languageserver_types_1.SymbolKind.Class,
                                location: {
                                    uri: rootUri + 'foo/b.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 0,
                                        },
                                        end: {
                                            line: 0,
                                            character: 57,
                                        },
                                    },
                                },
                            },
                            {
                                name: 'bar',
                                kind: vscode_languageserver_types_1.SymbolKind.Property,
                                location: {
                                    uri: rootUri + 'foo/b.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 10,
                                        },
                                        end: {
                                            line: 0,
                                            character: 22,
                                        },
                                    },
                                },
                                containerName: 'b',
                            },
                            {
                                name: 'baz',
                                kind: vscode_languageserver_types_1.SymbolKind.Method,
                                location: {
                                    uri: rootUri + 'foo/b.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 23,
                                        },
                                        end: {
                                            line: 0,
                                            character: 56,
                                        },
                                    },
                                },
                                containerName: 'b',
                            },
                            {
                                name: 'qux',
                                kind: vscode_languageserver_types_1.SymbolKind.Function,
                                location: {
                                    uri: rootUri + 'foo/b.ts',
                                    range: {
                                        start: {
                                            line: 0,
                                            character: 59,
                                        },
                                        end: {
                                            line: 0,
                                            character: 76,
                                        },
                                    },
                                },
                            },
                        ]);
                    });
                });
            });
        });
        describe('workspaceXreferences()', () => {
            it('should return all references to a method', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .workspaceXreferences({ query: { name: 'foo', kind: 'method', containerName: 'a' } })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            symbol: {
                                filePath: 'a.ts',
                                containerKind: '',
                                containerName: 'a',
                                name: 'foo',
                                kind: 'method',
                            },
                            reference: {
                                range: {
                                    end: {
                                        character: 13,
                                        line: 0,
                                    },
                                    start: {
                                        character: 9,
                                        line: 0,
                                    },
                                },
                                uri: rootUri + 'a.ts',
                            },
                        },
                    ]);
                });
            });
            it('should return all references to a method with hinted dependee package name', function () {
                return __awaiter(this, void 0, void 0, function* () {
                    const result = yield this.service
                        .workspaceXreferences({
                        query: {
                            name: 'foo',
                            kind: 'method',
                            containerName: 'a',
                        },
                        hints: {
                            dependeePackageName: 'mypkg',
                        },
                    })
                        .reduce(fast_json_patch_1.applyReducer, null)
                        .toPromise();
                    assert.deepEqual(result, [
                        {
                            symbol: {
                                filePath: 'a.ts',
                                containerKind: '',
                                containerName: 'a',
                                name: 'foo',
                                kind: 'method',
                            },
                            reference: {
                                range: {
                                    end: {
                                        character: 13,
                                        line: 0,
                                    },
                                    start: {
                                        character: 9,
                                        line: 0,
                                    },
                                },
                                uri: rootUri + 'a.ts',
                            },