Merge branch 'master' into isidorn/cgmanifest

This commit is contained in:
Alex Dima 2018-11-16 17:52:27 +01:00
commit 976cfe3aa7
246 changed files with 3005 additions and 7332 deletions

20
.vscode/launch.json vendored
View file

@ -9,17 +9,14 @@
"stopOnEntry": true,
"args": [
"hygiene"
],
"cwd": "${workspaceFolder}"
]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Extension Host",
"protocol": "inspector",
"port": 5870,
"restart": true,
"smartStep": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
@ -28,9 +25,7 @@
"type": "node",
"request": "attach",
"name": "Attach to Shared Process",
"protocol": "inspector",
"port": 5871,
"smartStep": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
@ -38,10 +33,8 @@
{
"type": "node",
"request": "attach",
"protocol": "inspector",
"name": "Attach to Search Process",
"port": 5876,
"smartStep": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
@ -50,9 +43,7 @@
"type": "node",
"request": "attach",
"name": "Attach to CLI Process",
"protocol": "inspector",
"port": 5874,
"smartStep": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
@ -61,9 +52,7 @@
"type": "node",
"request": "attach",
"name": "Attach to Main Process",
"protocol": "inspector",
"port": 5875,
"smartStep": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
@ -129,7 +118,6 @@
"type": "chrome",
"request": "attach",
"name": "Attach to VS Code",
"smartStep": true,
"port": 9222
},
{
@ -149,7 +137,6 @@
"runtimeArgs": [
"--inspect=5875", "--no-cached-data"
],
"smartStep": true,
"skipFiles": [
"**/winjs*.js"
],
@ -163,7 +150,6 @@
"runtimeArgs": [
"--no-cached-data"
],
"smartStep": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
@ -172,7 +158,6 @@
"type": "node",
"request": "launch",
"name": "Git Unit Tests",
"protocol": "inspector",
"program": "${workspaceFolder}/extensions/git/node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"cwd": "${workspaceFolder}/extensions/git",
@ -212,7 +197,6 @@
"type": "node",
"request": "launch",
"name": "Unit Tests",
"protocol": "inspector",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
"windows": {
@ -289,4 +273,4 @@
]
}
]
}
}

View file

@ -1,7 +1,7 @@
[
{
"name": "ms-vscode.node-debug",
"version": "1.29.2",
"version": "1.30.1",
"repo": "https://github.com/Microsoft/vscode-node-debug",
"metadata": {
"id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6",
@ -16,7 +16,7 @@
},
{
"name": "ms-vscode.node-debug2",
"version": "1.30.0",
"version": "1.30.1",
"repo": "https://github.com/Microsoft/vscode-node-debug2",
"metadata": {
"id": "36d19e17-7569-4841-a001-947eb18602b2",
@ -31,10 +31,10 @@
},
{
"name": "ms-vscode.references-view",
"version": "0.0.8",
"version": "0.0.9",
"repo": "https://github.com/Microsoft/vscode-reference-view",
"metadata": {
"id": "36d19e17-7569-4841-a001-947eb18602b2",
"id": "dc489f46-520d-4556-ae85-1f9eab3c412d",
"publisherId": {
"publisherId": "5f5636e7-69ed-4afe-b5d6-8d231fb3d3ee",
"publisherName": "ms-vscode",

View file

@ -152,10 +152,19 @@ gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro', 'ext
});
});
gulp.task('compile-editor-esm', ['extract-editor-esm', 'clean-editor-distro'], function () {
const result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], {
cwd: path.join(__dirname, '../out-editor-esm')
});
console.log(result.stdout.toString());
if (process.platform === 'win32') {
const result = cp.spawnSync(`..\\node_modules\\.bin\\tsc.cmd`, {
cwd: path.join(__dirname, '../out-editor-esm')
});
console.log(result.stdout.toString());
console.log(result.stderr.toString());
} else {
const result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], {
cwd: path.join(__dirname, '../out-editor-esm')
});
console.log(result.stdout.toString());
console.log(result.stderr.toString());
}
});
function toExternalDTS(contents) {

View file

@ -36,7 +36,7 @@ function fromLocalWebpack(extensionPath, sourceMappingURLBase) {
const result = es.through();
const packagedDependencies = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (Array.isArray(packageJsonConfig.dependencies)) {
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path.join(extensionPath, 'extension.webpack.config.js'));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
@ -77,7 +77,7 @@ function fromLocalWebpack(extensionPath, sourceMappingURLBase) {
return data;
}))
.pipe(packageJsonFilter.restore);
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => {
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => () => {
const webpackDone = (err, stats) => {
util.log(`Bundled extension: ${util.colors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
@ -118,7 +118,7 @@ function fromLocalWebpack(extensionPath, sourceMappingURLBase) {
this.emit('data', data);
}));
});
es.merge(...webpackStreams, patchFilesStream)
es.merge(sequence(webpackStreams), patchFilesStream)
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
@ -216,10 +216,10 @@ function packageExtensionsStream(optsIn) {
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
const localExtensions = () => es.merge(...localExtensionDescriptions.map(extension => {
return fromLocal(extension.path, opts.sourceMappingURLBase)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
}));
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
return fromLocal(extension.path, opts.sourceMappingURLBase)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
})]);
const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' });
const marketplaceExtensions = () => es.merge(...builtInExtensions
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)

View file

@ -39,7 +39,7 @@ function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string |
const packagedDependencies: string[] = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (Array.isArray(packageJsonConfig.dependencies)) {
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path.join(extensionPath, 'extension.webpack.config.js'));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
@ -90,7 +90,7 @@ function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string |
.pipe(packageJsonFilter.restore);
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => {
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => () => {
const webpackDone = (err: any, stats: any) => {
util.log(`Bundled extension: ${util.colors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
@ -139,7 +139,7 @@ function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string |
}));
});
es.merge(...webpackStreams, patchFilesStream)
es.merge(sequence(webpackStreams), patchFilesStream)
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
@ -270,10 +270,10 @@ export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): Nod
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
const localExtensions = () => es.merge(...localExtensionDescriptions.map(extension => {
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
return fromLocal(extension.path, opts.sourceMappingURLBase)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
}));
})]);
const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' });

View file

@ -90,6 +90,7 @@ function extractEditor(options) {
}
}
}
delete tsConfig.compilerOptions.moduleResolution;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
[
'vs/css.build.js',
@ -126,7 +127,7 @@ function createESMSourcesAndResources2(options) {
if (file === 'tsconfig.json') {
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
tsConfig.compilerOptions.module = 'es6';
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs');
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
continue;
}
@ -154,15 +155,16 @@ function createESMSourcesAndResources2(options) {
importedFilepath = path.join(path.dirname(file), importedFilepath);
}
let relativePath;
if (importedFilepath === path.dirname(file)) {
if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) {
relativePath = '../' + path.basename(path.dirname(file));
}
else if (importedFilepath === path.dirname(path.dirname(file))) {
else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(file)));
}
else {
relativePath = path.relative(path.dirname(file), importedFilepath);
}
relativePath = relativePath.replace(/\\/g, '/');
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}

View file

@ -99,6 +99,7 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
}
}
delete tsConfig.compilerOptions.moduleResolution;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
[
@ -148,7 +149,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void {
if (file === 'tsconfig.json') {
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
tsConfig.compilerOptions.module = 'es6';
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs');
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
continue;
}
@ -181,13 +182,14 @@ export function createESMSourcesAndResources2(options: IOptions2): void {
}
let relativePath: string;
if (importedFilepath === path.dirname(file)) {
if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) {
relativePath = '../' + path.basename(path.dirname(file));
} else if (importedFilepath === path.dirname(path.dirname(file))) {
} else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(file)));
} else {
relativePath = path.relative(path.dirname(file), importedFilepath);
}
relativePath = relativePath.replace(/\\/g, '/');
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}

View file

@ -57,7 +57,7 @@ function createTypeScriptLanguageService(options) {
const FILES = discoverAndReadFiles(options);
// Add fake usage files
options.inlineEntryPoints.forEach((inlineEntryPoint, index) => {
FILES[`inlineEntryPoint:${index}.ts`] = inlineEntryPoint;
FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint;
});
// Add additional typings
options.typings.forEach((typing) => {
@ -336,7 +336,7 @@ function markNodes(languageService, options) {
}
options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts'));
// Add fake usage files
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint:${index}.ts`));
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`));
let step = 0;
const checker = program.getTypeChecker();
while (black_queue.length > 0 || gray_queue.length > 0) {

View file

@ -110,7 +110,7 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu
// Add fake usage files
options.inlineEntryPoints.forEach((inlineEntryPoint, index) => {
FILES[`inlineEntryPoint:${index}.ts`] = inlineEntryPoint;
FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint;
});
// Add additional typings
@ -445,7 +445,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts'));
// Add fake usage files
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint:${index}.ts`));
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`));
let step = 0;

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,8 @@ jobs:
- template: win32/continuous-build-win32.yml
- job: Linux
pool: Hosted Linux Preview
pool:
vmImage: 'Ubuntu-16.04'
steps:
- template: linux/continuous-build-linux.yml

View file

@ -1,14 +1,12 @@
steps:
- script: |
set -e
apt-get update
apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 libgconf-2-4 dbus xvfb libgtk-3-0
cp build/tfs/linux/xvfb.init /etc/init.d/xvfb
chmod +x /etc/init.d/xvfb
update-rc.d xvfb defaults
ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon
service xvfb start
service dbus start
sudo apt-get update
sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 libgconf-2-4 dbus xvfb libgtk-3-0
sudo cp build/tfs/linux/xvfb.init /etc/init.d/xvfb
sudo chmod +x /etc/init.d/xvfb
sudo update-rc.d xvfb defaults
sudo service xvfb start
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"

View file

@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const documentdb_1 = require("documentdb");
function createDefaultConfig(quality) {
return {
id: quality,
frozen: false
};
}
function getConfig(quality) {
const client = new documentdb_1.DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT'], { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
const collection = 'dbs/builds/colls/config';
const query = {
query: `SELECT TOP 1 * FROM c WHERE c.id = @quality`,
parameters: [
{ name: '@quality', value: quality }
]
};
return new Promise((c, e) => {
client.queryDocuments(collection, query).toArray((err, results) => {
if (err && err.code !== 409) {
return e(err);
}
c(!results || results.length === 0 ? createDefaultConfig(quality) : results[0]);
});
});
}
getConfig(process.argv[2])
.then(config => {
console.log(config.frozen);
process.exit(0);
})
.catch(err => {
console.error(err);
process.exit(1);
});

View file

@ -283,4 +283,4 @@ vscode.languages.registerDocumentSymbolProvider({ pattern: '**/launch.json', lan
return result;
}
});
}, { label: 'Launch Targets' });

View file

@ -60,6 +60,10 @@ export class ApiRepository implements Repository {
constructor(private _repository: BaseRepository) { }
apply(patch: string, reverse?: boolean): Promise<void> {
return this._repository.apply(patch, reverse);
}
getConfigs(): Promise<{ key: string; value: string; }[]> {
return this._repository.getConfigs();
}
@ -96,6 +100,10 @@ export class ApiRepository implements Repository {
return this._repository.clean(paths.map(p => Uri.file(p)));
}
diff(cached?: boolean) {
return this._repository.diff(cached);
}
diffWithHEAD(path: string): Promise<string> {
return this._repository.diffWithHEAD(path);
}

View file

@ -128,6 +128,8 @@ export interface Repository {
clean(paths: string[]): Promise<void>;
apply(patch: string, reverse?: boolean): Promise<void>;
diff(cached?: boolean): Promise<string>;
diffWithHEAD(path: string): Promise<string>;
diffWith(ref: string, path: string): Promise<string>;
diffIndexWithHEAD(path: string): Promise<string>;

View file

@ -822,15 +822,23 @@ export class Repository {
}
}
async diff(path: string, cached = false): Promise<string> {
async apply(patch: string, reverse?: boolean): Promise<void> {
const args = ['apply', patch];
if (reverse) {
args.push('-R');
}
await this.run(args);
}
async diff(cached = false): Promise<string> {
const args = ['diff'];
if (cached) {
args.push('--cached');
}
args.push('--', path);
const result = await this.run(args);
return result.stdout;
}

View file

@ -295,6 +295,7 @@ export const enum Operation {
GetObjectDetails = 'GetObjectDetails',
SubmoduleUpdate = 'SubmoduleUpdate',
RebaseContinue = 'RebaseContinue',
Apply = 'Apply'
}
function isReadOnly(operation: Operation): boolean {
@ -705,6 +706,10 @@ export class Repository implements Disposable {
await this.run(Operation.Status);
}
diff(cached?: boolean): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diff(cached));
}
diffWithHEAD(path: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffWithHEAD(path));
}
@ -1050,6 +1055,10 @@ export class Repository implements Disposable {
return this.run(Operation.Show, () => this.repository.detectObjectType(object));
}
async apply(patch: string, reverse?: boolean): Promise<void> {
return await this.run(Operation.Apply, () => this.repository.apply(patch, reverse));
}
async getStashes(): Promise<Stash[]> {
return await this.repository.getStashes();
}

View file

@ -33,7 +33,7 @@ export function combinedDisposable(disposables: IDisposable[]): IDisposable {
export const EmptyDisposable = toDisposable(() => null);
export function fireEvent<T>(event: Event<T>): Event<T> {
return (listener, thisArgs = null, disposables?) => event(_ => listener.call(thisArgs), null, disposables);
return (listener, thisArgs = null, disposables?) => event(_ => (listener as any).call(thisArgs), null, disposables);
}
export function mapEvent<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {

View file

@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/11cf764606cb2cde54badb5d0e5a0758a8871c4b",
"version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/47e0c947d0a8d13c07e06a086a5c0c9bbffc6cf6",
"name": "Markdown",
"scopeName": "text.html.markdown",
"patterns": [
@ -2115,7 +2115,7 @@
"include": "source.yaml"
}
],
"end": "(^|\\G)-{3}|\\.{3}\\s*$\""
"end": "(^|\\G)-{3}|\\.{3}\\s*$"
},
"inline": {
"patterns": [

View file

@ -53,7 +53,7 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi
this.getRegions(document),
this.getHeaderFoldingRanges(document),
this.getBlockFoldingRanges(document)]);
return [].concat.apply([], foldables).slice(0, rangeLimit);
return ([] as vscode.FoldingRange[]).concat.apply([], foldables).slice(0, rangeLimit);
}
private async getHeaderFoldingRanges(document: vscode.TextDocument) {

View file

@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "3.1.4"
"typescript": "3.2.0-rc"
},
"scripts": {
"postinstall": "node ./postinstall"

View file

@ -11,10 +11,10 @@
"contributes": {
"languages": [{
"id": "shellscript",
"aliases": ["Shell Script", "shellscript", "bash", "sh", "zsh"],
"extensions": [".sh", ".bash", ".bashrc", ".bash_aliases", ".bash_profile", ".bash_login", ".ebuild", ".install", ".profile", ".bash_logout", ".zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".zshenv", ".zsh-theme"],
"aliases": ["Shell Script", "shellscript", "bash", "sh", "zsh", "ksh"],
"extensions": [".sh", ".bash", ".bashrc", ".bash_aliases", ".bash_profile", ".bash_login", ".ebuild", ".install", ".profile", ".bash_logout", ".zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".zshenv", ".zsh-theme", ".ksh"],
"filenames": ["PKGBUILD"],
"firstLine": "^#!.*\\b(bash|zsh|sh|tcsh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-",
"firstLine": "^#!.*\\b(bash|zsh|sh|tcsh|ksh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-",
"configuration": "./language-configuration.json",
"mimetypes": ["text/x-shellscript"]
}],

View file

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
interface ApiV0 {
readonly onCompletionAccepted: vscode.Event<vscode.CompletionItem>;
}
export interface Api {
getAPI(version: 0): ApiV0 | undefined;
}
export function getExtensionApi(
onCompletionAccepted: vscode.Event<vscode.CompletionItem>
): Api {
return {
getAPI(version) {
if (version === 0) {
return {
onCompletionAccepted: onCompletionAccepted
} as ApiV0;
}
return undefined;
}
};
}

View file

@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Command } from '../utils/commandManager';
import { PluginManager } from '../utils/plugins';
export class ConfigurePluginCommand implements Command {
public readonly id = '_typescript.configurePlugin';
public constructor(
private readonly pluginManager: PluginManager,
) { }
public execute(pluginId: string, configuration: any) {
this.pluginManager.setConfiguration(pluginId, configuration);
}
}

View file

@ -5,77 +5,14 @@
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import TypeScriptServiceClientHost from './typeScriptServiceClientHost';
import { Command } from './utils/commandManager';
import { Lazy } from './utils/lazy';
import { isImplicitProjectConfigFile, openOrCreateConfigFile } from './utils/tsconfig';
import { nulToken } from './utils/cancellation';
import { PluginConfigProvider } from './typescriptServiceClient';
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { nulToken } from '../utils/cancellation';
import { Command } from '../utils/commandManager';
import { Lazy } from '../utils/lazy';
import { isImplicitProjectConfigFile, openOrCreateConfigFile } from '../utils/tsconfig';
const localize = nls.loadMessageBundle();
export class ReloadTypeScriptProjectsCommand implements Command {
public readonly id = 'typescript.reloadProjects';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.reloadProjects();
}
}
export class ReloadJavaScriptProjectsCommand implements Command {
public readonly id = 'javascript.reloadProjects';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.reloadProjects();
}
}
export class SelectTypeScriptVersionCommand implements Command {
public readonly id = 'typescript.selectTypeScriptVersion';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.serviceClient.onVersionStatusClicked();
}
}
export class OpenTsServerLogCommand implements Command {
public readonly id = 'typescript.openTsServerLog';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.serviceClient.openTsServerLogFile();
}
}
export class RestartTsServerCommand implements Command {
public readonly id = 'typescript.restartTsServer';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.serviceClient.restartTsServer();
}
}
export class TypeScriptGoToProjectConfigCommand implements Command {
public readonly id = 'typescript.goToProjectConfig';
@ -106,18 +43,6 @@ export class JavaScriptGoToProjectConfigCommand implements Command {
}
}
export class ConfigurePluginCommand implements Command {
public readonly id = '_typescript.configurePlugin';
public constructor(
private readonly pluginConfigProvider: PluginConfigProvider,
) { }
public execute(pluginId: string, configuration: any) {
this.pluginConfigProvider.set(pluginId, configuration);
}
}
async function goToProjectConfig(
clientHost: TypeScriptServiceClientHost,
isTypeScriptProject: boolean,
@ -143,7 +68,7 @@ async function goToProjectConfig(
return;
}
let res: protocol.ProjectInfoResponse | undefined = undefined;
let res: protocol.ProjectInfoResponse | undefined;
try {
res = await client.execute('projectInfo', { file, needFileNameList: false }, nulToken);
} catch {
@ -164,7 +89,7 @@ async function goToProjectConfig(
enum ProjectConfigAction {
None,
CreateConfig,
LearnMore
LearnMore,
}
interface ProjectConfigMessageItem extends vscode.MessageItem {
@ -179,7 +104,7 @@ async function goToProjectConfig(
title: isTypeScriptProject
? localize('typescript.configureTsconfigQuickPick', 'Configure tsconfig.json')
: localize('typescript.configureJsconfigQuickPick', 'Configure jsconfig.json'),
id: ProjectConfigAction.CreateConfig
id: ProjectConfigAction.CreateConfig,
});
switch (selected && selected.id) {

View file

@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { CommandManager } from '../utils/commandManager';
import { Lazy } from '../utils/lazy';
import { PluginManager } from '../utils/plugins';
import { ConfigurePluginCommand } from './configurePlugin';
import { JavaScriptGoToProjectConfigCommand, TypeScriptGoToProjectConfigCommand } from './goToProjectConfiguration';
import { OpenTsServerLogCommand } from './openTsServerLog';
import { ReloadJavaScriptProjectsCommand, ReloadTypeScriptProjectsCommand } from './reloadProject';
import { RestartTsServerCommand } from './restartTsServer';
import { SelectTypeScriptVersionCommand } from './selectTypeScriptVersion';
export function registerCommands(
commandManager: CommandManager,
lazyClientHost: Lazy<TypeScriptServiceClientHost>,
pluginManager: PluginManager
) {
commandManager.register(new ReloadTypeScriptProjectsCommand(lazyClientHost));
commandManager.register(new ReloadJavaScriptProjectsCommand(lazyClientHost));
commandManager.register(new SelectTypeScriptVersionCommand(lazyClientHost));
commandManager.register(new OpenTsServerLogCommand(lazyClientHost));
commandManager.register(new RestartTsServerCommand(lazyClientHost));
commandManager.register(new TypeScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new JavaScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new ConfigurePluginCommand(pluginManager));
}

View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { Command } from '../utils/commandManager';
import { Lazy } from '../utils/lazy';
export class OpenTsServerLogCommand implements Command {
public readonly id = 'typescript.openTsServerLog';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.serviceClient.openTsServerLogFile();
}
}

View file

@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { Command } from '../utils/commandManager';
import { Lazy } from '../utils/lazy';
export class ReloadTypeScriptProjectsCommand implements Command {
public readonly id = 'typescript.reloadProjects';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.reloadProjects();
}
}
export class ReloadJavaScriptProjectsCommand implements Command {
public readonly id = 'javascript.reloadProjects';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.reloadProjects();
}
}

View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { Command } from '../utils/commandManager';
import { Lazy } from '../utils/lazy';
export class RestartTsServerCommand implements Command {
public readonly id = 'typescript.restartTsServer';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.serviceClient.restartTsServer();
}
}

View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { Command } from '../utils/commandManager';
import { Lazy } from '../utils/lazy';
export class SelectTypeScriptVersionCommand implements Command {
public readonly id = 'typescript.selectTypeScriptVersion';
public constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
) { }
public execute() {
this.lazyClientHost.value.serviceClient.onVersionStatusClicked();
}
}

View file

@ -4,7 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as commands from './commands';
import { Api, getExtensionApi } from './api';
import { registerCommands } from './commands/index';
import { LanguageConfigurationManager } from './features/languageConfiguration';
import TypeScriptTaskProviderManager from './features/task';
import TypeScriptServiceClientHost from './typeScriptServiceClientHost';
@ -15,39 +16,27 @@ import { standardLanguageDescriptions } from './utils/languageDescription';
import { lazy, Lazy } from './utils/lazy';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import ManagedFileContextManager from './utils/managedFileContext';
import { getContributedTypeScriptServerPlugins, TypeScriptServerPlugin } from './utils/plugins';
import { PluginManager } from './utils/plugins';
import * as ProjectStatus from './utils/projectStatus';
import { Surveyor } from './utils/surveyor';
import { PluginConfigProvider } from './typescriptServiceClient';
interface ApiV0 {
readonly onCompletionAccepted: vscode.Event<vscode.CompletionItem>;
}
interface Api {
getAPI(version: 0): ApiV0 | undefined;
}
export function activate(
context: vscode.ExtensionContext
): Api {
const plugins = getContributedTypeScriptServerPlugins();
const pluginConfigProvider = new PluginConfigProvider();
const pluginManager = new PluginManager();
context.subscriptions.push(pluginManager);
const commandManager = new CommandManager();
context.subscriptions.push(commandManager);
const onCompletionAccepted = new vscode.EventEmitter();
const onCompletionAccepted = new vscode.EventEmitter<vscode.CompletionItem>();
context.subscriptions.push(onCompletionAccepted);
const lazyClientHost = createLazyClientHost(context, plugins, pluginConfigProvider, commandManager, item => {
const lazyClientHost = createLazyClientHost(context, pluginManager, commandManager, item => {
onCompletionAccepted.fire(item);
});
registerCommands(commandManager, lazyClientHost, pluginConfigProvider);
registerCommands(commandManager, lazyClientHost, pluginManager);
context.subscriptions.push(new TypeScriptTaskProviderManager(lazyClientHost.map(x => x.serviceClient)));
context.subscriptions.push(new LanguageConfigurationManager());
@ -57,7 +46,7 @@ export function activate(
const supportedLanguage = flatten([
...standardLanguageDescriptions.map(x => x.modeIds),
...plugins.map(x => x.languages)
...pluginManager.plugins.map(x => x.languages)
]);
function didOpenTextDocument(textDocument: vscode.TextDocument): boolean {
if (isSupportedDocument(supportedLanguage, textDocument)) {
@ -80,22 +69,12 @@ export function activate(
}
}
return {
getAPI(version) {
if (version === 0) {
return {
onCompletionAccepted: onCompletionAccepted.event
} as ApiV0;
}
return undefined;
}
} as Api;
return getExtensionApi(onCompletionAccepted.event);
}
function createLazyClientHost(
context: vscode.ExtensionContext,
plugins: TypeScriptServerPlugin[],
pluginConfigProvider: PluginConfigProvider,
pluginManager: PluginManager,
commandManager: CommandManager,
onCompletionAccepted: (item: vscode.CompletionItem) => void,
): Lazy<TypeScriptServiceClientHost> {
@ -105,18 +84,14 @@ function createLazyClientHost(
const clientHost = new TypeScriptServiceClientHost(
standardLanguageDescriptions,
context.workspaceState,
plugins,
pluginConfigProvider,
pluginManager,
commandManager,
logDirectoryProvider,
onCompletionAccepted);
context.subscriptions.push(clientHost);
const surveyor = new Surveyor(context.globalState);
context.subscriptions.push(clientHost.serviceClient.onSurveyReady(e => surveyor.surveyReady(e.surveyId)));
context.subscriptions.push(new Surveyor(context.globalState, clientHost.serviceClient));
clientHost.serviceClient.onReady(() => {
context.subscriptions.push(
@ -129,21 +104,6 @@ function createLazyClientHost(
});
}
function registerCommands(
commandManager: CommandManager,
lazyClientHost: Lazy<TypeScriptServiceClientHost>,
pluginConfigProvider: PluginConfigProvider,
) {
commandManager.register(new commands.ReloadTypeScriptProjectsCommand(lazyClientHost));
commandManager.register(new commands.ReloadJavaScriptProjectsCommand(lazyClientHost));
commandManager.register(new commands.SelectTypeScriptVersionCommand(lazyClientHost));
commandManager.register(new commands.OpenTsServerLogCommand(lazyClientHost));
commandManager.register(new commands.RestartTsServerCommand(lazyClientHost));
commandManager.register(new commands.TypeScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new commands.JavaScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new commands.ConfigurePluginCommand(pluginConfigProvider));
}
function isSupportedDocument(
supportedLanguage: string[],
document: vscode.TextDocument

View file

@ -55,7 +55,7 @@ class SyncedBuffer {
}
if (this.client.apiVersion.gte(API.v240)) {
const tsPluginsForDocument = this.client.plugins
const tsPluginsForDocument = this.client.pluginManager.plugins
.filter(x => x.languages.indexOf(this.document.languageId) >= 0);
if (tsPluginsForDocument.length) {

View file

@ -21,7 +21,6 @@ import FileConfigurationManager from './fileConfigurationManager';
const localize = nls.loadMessageBundle();
interface CommitCharactersSettings {
readonly isNewIdentifierLocation: boolean;
readonly isInValidCommitCharacterContext: boolean;
@ -223,7 +222,6 @@ class CompositeCommand implements Command {
}
}
class CompletionAcceptedCommand implements Command {
public static readonly ID = '_typescript.onCompletionAccepted';
public readonly id = CompletionAcceptedCommand.ID;
@ -359,7 +357,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
...typeConverters.Position.toFileLocationRequestArgs(file, position),
includeExternalModuleExports: completionConfiguration.autoImportSuggestions,
includeInsertTextCompletions: true,
triggerCharacter: this.getTsTriggerCharacter(context)
triggerCharacter: this.getTsTriggerCharacter(context),
};
let isNewIdentifierLocation = true;

View file

@ -37,11 +37,11 @@ export default class TypeScriptDefinitionProvider extends DefinitionProviderBase
return response.body.definitions
.map(location => {
const target = typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location);
return <vscode.DefinitionLink>{
return {
originSelectionRange: span,
targetRange: target.range,
targetUri: target.uri,
};
} as vscode.DefinitionLink;
});
}

View file

@ -10,7 +10,7 @@ import { DiagnosticLanguage, allDiagnosticLangauges } from '../utils/languageDes
export const enum DiagnosticKind {
Syntax,
Semantic,
Suggestion
Suggestion,
}
class FileDiagnostics {
@ -97,7 +97,7 @@ class DiagnosticSettings {
public setValidate(language: DiagnosticLanguage, value: boolean): boolean {
return this.update(language, settings => ({
validate: value,
enableSuggestions: settings.enableSuggestions
enableSuggestions: settings.enableSuggestions,
}));
}

View file

@ -8,8 +8,6 @@ import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import * as typeConverters from '../utils/typeConverters';
class TypeScriptDocumentHighlightProvider implements vscode.DocumentHighlightProvider {
public constructor(
private readonly client: ITypeScriptServiceClient
@ -26,21 +24,21 @@ class TypeScriptDocumentHighlightProvider implements vscode.DocumentHighlightPro
}
const args = typeConverters.Position.toFileLocationRequestArgs(file, position);
const response = await this.client.execute('occurrences', args, token);
const response = await this.client.execute('references', args, token);
if (response.type !== 'response' || !response.body) {
return [];
}
return response.body
.filter(x => !x.isInString)
.map(documentHighlightFromOccurance);
return response.body.refs
.filter(ref => ref.file === file)
.map(documentHighlightFromReference);
}
}
function documentHighlightFromOccurance(occurrence: Proto.OccurrencesResponseItem): vscode.DocumentHighlight {
function documentHighlightFromReference(reference: Proto.ReferencesResponseItem): vscode.DocumentHighlight {
return new vscode.DocumentHighlight(
typeConverters.Range.fromTextSpan(occurrence),
occurrence.isWriteAccess ? vscode.DocumentHighlightKind.Write : vscode.DocumentHighlightKind.Read);
typeConverters.Range.fromTextSpan(reference),
reference.isWriteAccess ? vscode.DocumentHighlightKind.Write : vscode.DocumentHighlightKind.Read);
}
export function register(

View file

@ -99,5 +99,5 @@ export function register(
client: ITypeScriptServiceClient,
) {
return vscode.languages.registerDocumentSymbolProvider(selector,
new TypeScriptDocumentSymbolProvider(client));
new TypeScriptDocumentSymbolProvider(client), { label: 'TypeScript' });
}

View file

@ -41,7 +41,7 @@ export default class FileConfigurationManager {
public constructor(
private readonly client: ITypeScriptServiceClient
) {
this.onDidCloseTextDocumentSub = vscode.workspace.onDidCloseTextDocument((textDocument) => {
this.onDidCloseTextDocumentSub = vscode.workspace.onDidCloseTextDocument(textDocument => {
// When a document gets closed delete the cached formatting options.
// This is necessary since the tsserver now closed a project when its
// last file in it closes which drops the stored formatting options

View file

@ -23,25 +23,25 @@ const jsTsLanguageConfiguration: vscode.LanguageConfiguration = {
// e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' }
action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' },
}, {
// e.g. /** ...|
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: { indentAction: vscode.IndentAction.None, appendText: ' * ' }
action: { indentAction: vscode.IndentAction.None, appendText: ' * ' },
}, {
// e.g. * ...|
beforeText: /^(\t|[ ])*[ ]\*([ ]([^\*]|\*(?!\/))*)?$/,
oneLineAboveText: /^(\s*(\/\*\*|\*)).*/,
action: { indentAction: vscode.IndentAction.None, appendText: '* ' }
action: { indentAction: vscode.IndentAction.None, appendText: '* ' },
}, {
// e.g. */|
beforeText: /^(\t|[ ])*[ ]\*\/\s*$/,
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
action: { indentAction: vscode.IndentAction.None, removeText: 1 },
},
{
// e.g. *-----*/|
beforeText: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$/,
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
action: { indentAction: vscode.IndentAction.None, removeText: 1 },
}
]
};

View file

@ -82,7 +82,7 @@ class ApplyFixAllCodeAction implements Command {
type: 'file',
args: { file }
},
fixId: tsAction.fixId
fixId: tsAction.fixId,
};
const response = await this.client.execute('getCombinedCodeFix', args, nulToken);

View file

@ -40,13 +40,13 @@ class ApplyRefactoringCommand implements Command {
}
*/
this.telemetryReporter.logTelemetry('refactor.execute', {
action: action
action: action,
});
const args: Proto.GetEditsForRefactorRequestArgs = {
...typeConverters.Range.toFileRangeRequestArgs(file, range),
refactor,
action
action,
};
const response = await this.client.execute('getEditsForRefactor', args, nulToken);
if (response.type !== 'response' || !response.body || !response.body.edits.length) {
@ -94,7 +94,7 @@ class SelectRefactorCommand implements Command {
): Promise<boolean> {
const selected = await vscode.window.showQuickPick(info.actions.map((action): vscode.QuickPickItem => ({
label: action.name,
description: action.description
description: action.description,
})));
if (!selected) {
return false;
@ -119,7 +119,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
}
public static readonly metadata: vscode.CodeActionProviderMetadata = {
providedCodeActionKinds: [vscode.CodeActionKind.Refactor]
providedCodeActionKinds: [vscode.CodeActionKind.Refactor],
};
public async provideCodeActions(

View file

@ -11,14 +11,6 @@ import { ITypeScriptServiceClient, ServerResponse } from '../typescriptService';
import API from '../utils/api';
import * as typeConverters from '../utils/typeConverters';
// TODO: Remove when we pick up TS 3.2
declare module '../protocol' {
interface RenameTextSpan extends Proto.TextSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
}
const localize = nls.loadMessageBundle();
class TypeScriptRenameProvider implements vscode.RenameProvider {

View file

@ -80,7 +80,6 @@ class TagClosing extends Disposable {
return;
}
const rangeStart = lastChange.range.start;
const version = document.version;
this._timeout = setTimeout(async () => {
this._timeout = undefined;
@ -89,9 +88,12 @@ class TagClosing extends Disposable {
return;
}
let position = new vscode.Position(rangeStart.line, rangeStart.character + lastChange.text.length);
const args: Proto.JsxClosingTagRequestArgs = typeConverters.Position.toFileLocationRequestArgs(filepath, position);
const addedLines = lastChange.text.split(/\r\n|\n/g);
const position = addedLines.length <= 1
? lastChange.range.start.translate({ characterDelta: lastChange.text.length })
: new vscode.Position(lastChange.range.start.line + addedLines.length - 1, addedLines[addedLines.length - 1].length);
const args: Proto.JsxClosingTagRequestArgs = typeConverters.Position.toFileLocationRequestArgs(filepath, position);
this._cancel = new vscode.CancellationTokenSource();
const response = await this.client.execute('jsxClosingTag', args, this._cancel.token);
if (response.type !== 'response' || !response.body) {

View file

@ -296,14 +296,14 @@ class UpdateImportsOnFileRenameHandler {
start: change.start,
end: {
line: change.end.line,
offset: change.end.offset - match[1].length
}
offset: change.end.offset - match[1].length,
},
};
});
return {
fileName: edit.fileName,
textChanges
textChanges,
};
}
}

View file

@ -36,12 +36,9 @@ export default class LanguageProvider extends Disposable {
vscode.workspace.onDidChangeConfiguration(this.configurationChanged, this, this._disposables);
this.configurationChanged();
client.onReady(async () => {
await this.registerProviders();
});
client.onReady(() => this.registerProviders());
}
@memoize
private get documentSelector(): vscode.DocumentFilter[] {
const documentSelector = [];

View file

@ -75,4 +75,3 @@ suite('typescript.jsDocSnippet', () => {
].join('\n'));
});
});

View file

@ -11,7 +11,7 @@ suite('RequestQueue', () => {
test('should be empty on creation', async () => {
const queue = new RequestQueue();
assert.strictEqual(queue.length, 0);
assert.strictEqual(queue.shift(), undefined);
assert.strictEqual(queue.dequeue(), undefined);
});
suite('RequestQueue.createRequest', () => {
@ -33,25 +33,25 @@ suite('RequestQueue', () => {
assert.strictEqual(queue.length, 0);
const request1 = queue.createRequest('a', 1);
queue.push({ request: request1, expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
queue.enqueue({ request: request1, expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
assert.strictEqual(queue.length, 1);
const request2 = queue.createRequest('b', 2);
queue.push({ request: request2, expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
queue.enqueue({ request: request2, expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
assert.strictEqual(queue.length, 2);
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 1);
assert.strictEqual(item!.request.command, 'a');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 0);
assert.strictEqual(item!.request.command, 'b');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(item, undefined);
assert.strictEqual(queue.length, 0);
}
@ -61,28 +61,28 @@ suite('RequestQueue', () => {
const queue = new RequestQueue();
assert.strictEqual(queue.length, 0);
queue.push({ request: queue.createRequest('low-1', 1), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.push({ request: queue.createRequest('low-2', 1), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.push({ request: queue.createRequest('normal-1', 2), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
queue.push({ request: queue.createRequest('normal-2', 2), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
queue.enqueue({ request: queue.createRequest('low-1', 1), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.enqueue({ request: queue.createRequest('low-2', 1), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.enqueue({ request: queue.createRequest('normal-1', 2), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
queue.enqueue({ request: queue.createRequest('normal-2', 2), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 3);
assert.strictEqual(item!.request.command, 'normal-1');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 2);
assert.strictEqual(item!.request.command, 'normal-2');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 1);
assert.strictEqual(item!.request.command, 'low-1');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 0);
assert.strictEqual(item!.request.command, 'low-2');
}
@ -92,28 +92,28 @@ suite('RequestQueue', () => {
const queue = new RequestQueue();
assert.strictEqual(queue.length, 0);
queue.push({ request: queue.createRequest('low-1', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.push({ request: queue.createRequest('fence', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Fence });
queue.push({ request: queue.createRequest('low-2', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.push({ request: queue.createRequest('normal', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
queue.enqueue({ request: queue.createRequest('low-1', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.enqueue({ request: queue.createRequest('fence', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Fence });
queue.enqueue({ request: queue.createRequest('low-2', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.LowPriority });
queue.enqueue({ request: queue.createRequest('normal', 0), expectsResponse: true, isAsync: false, queueingType: RequestQueueingType.Normal });
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 3);
assert.strictEqual(item!.request.command, 'low-1');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 2);
assert.strictEqual(item!.request.command, 'fence');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 1);
assert.strictEqual(item!.request.command, 'normal');
}
{
const item = queue.shift();
const item = queue.dequeue();
assert.strictEqual(queue.length, 0);
assert.strictEqual(item!.request.command, 'low-2');
}

View file

@ -32,8 +32,7 @@ export class CallbackMap<R extends Proto.Response> {
public add(seq: number, callback: CallbackItem<ServerResponse<R> | undefined>, isAsync: boolean) {
if (isAsync) {
this._asyncCallbacks.set(seq, callback);
}
else {
} else {
this._callbacks.set(seq, callback);
}
}

View file

@ -19,7 +19,7 @@ export enum RequestQueueingType {
/**
* A fence that blocks request reordering.
*
* Fences are not reordered but unlike a normal request, a fence will never jump in front of a low priority request
* Fences are not reordered. Unlike a normal request, a fence will never jump in front of a low priority request
* in the request queue.
*/
Fence = 3,
@ -40,7 +40,7 @@ export class RequestQueue {
return this.queue.length;
}
public push(item: RequestItem): void {
public enqueue(item: RequestItem): void {
if (item.queueingType === RequestQueueingType.Normal) {
let index = this.queue.length - 1;
while (index >= 0) {
@ -51,16 +51,16 @@ export class RequestQueue {
}
this.queue.splice(index + 1, 0, item);
} else {
//if none is low priority just push to end
// Only normal priority requests can be reordered. All other requests just go to the end.
this.queue.push(item);
}
}
public shift(): RequestItem | undefined {
public dequeue(): RequestItem | undefined {
return this.queue.shift();
}
public tryCancelPendingRequest(seq: number): boolean {
public tryDeletePendingRequest(seq: number): boolean {
for (let i = 0; i < this.queue.length; i++) {
if (this.queue[i].request.seq === seq) {
this.queue.splice(i, 1);

View file

@ -16,13 +16,13 @@ import * as electron from '../utils/electron';
import LogDirectoryProvider from '../utils/logDirectoryProvider';
import Logger from '../utils/logger';
import { TypeScriptPluginPathsProvider } from '../utils/pluginPathsProvider';
import { TypeScriptServerPlugin } from '../utils/plugins';
import { PluginManager } from '../utils/plugins';
import TelemetryReporter from '../utils/telemetry';
import Tracer from '../utils/tracer';
import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider';
import { Reader } from '../utils/wireProtocol';
import { CallbackMap } from './callbackMap';
import { RequestQueue, RequestItem, RequestQueueingType } from './requestQueue';
import { RequestItem, RequestQueue, RequestQueueingType } from './requestQueue';
export class TypeScriptServerSpawner {
public constructor(
@ -37,11 +37,11 @@ export class TypeScriptServerSpawner {
public spawn(
version: TypeScriptVersion,
configuration: TypeScriptServiceConfiguration,
plugins: ReadonlyArray<TypeScriptServerPlugin>
pluginManager: PluginManager
): TypeScriptServer {
const apiVersion = version.version || API.defaultVersion;
const { args, cancellationPipeName, tsServerLogFile } = this.getTsServerArgs(configuration, version, plugins);
const { args, cancellationPipeName, tsServerLogFile } = this.getTsServerArgs(configuration, version, pluginManager);
if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) {
if (tsServerLogFile) {
@ -60,7 +60,7 @@ export class TypeScriptServerSpawner {
private getForkOptions() {
const debugPort = TypeScriptServerSpawner.getDebugPort();
const tsServerForkOptions: electron.IForkOptions = {
const tsServerForkOptions: electron.ForkOptions = {
execArgv: debugPort ? [`--inspect=${debugPort}`] : [],
};
return tsServerForkOptions;
@ -69,11 +69,11 @@ export class TypeScriptServerSpawner {
private getTsServerArgs(
configuration: TypeScriptServiceConfiguration,
currentVersion: TypeScriptVersion,
plugins: ReadonlyArray<TypeScriptServerPlugin>,
pluginManager: PluginManager,
): { args: string[], cancellationPipeName: string | undefined, tsServerLogFile: string | undefined } {
const args: string[] = [];
let cancellationPipeName: string | undefined = undefined;
let tsServerLogFile: string | undefined = undefined;
let cancellationPipeName: string | undefined;
let tsServerLogFile: string | undefined;
const apiVersion = currentVersion.version || API.defaultVersion;
@ -110,11 +110,11 @@ export class TypeScriptServerSpawner {
if (apiVersion.gte(API.v230)) {
const pluginPaths = this._pluginPathsProvider.getPluginPaths();
if (plugins.length) {
args.push('--globalPlugins', plugins.map(x => x.name).join(','));
if (pluginManager.plugins.length) {
args.push('--globalPlugins', pluginManager.plugins.map(x => x.name).join(','));
if (currentVersion.path === this._versionProvider.defaultVersion.path) {
pluginPaths.push(...plugins.map(x => x.path));
pluginPaths.push(...pluginManager.plugins.map(x => x.path));
}
}
@ -178,7 +178,7 @@ export class TypeScriptServer extends Disposable {
private readonly _tracer: Tracer,
) {
super();
this._reader = new Reader<Proto.Response>(this._childProcess.stdout);
this._reader = this._register(new Reader<Proto.Response>(this._childProcess.stdout));
this._reader.onData(msg => this.dispatchMessage(msg));
this._childProcess.on('exit', code => this.handleExit(code));
this._childProcess.on('error', error => this.handleError(error));
@ -253,7 +253,7 @@ export class TypeScriptServer extends Disposable {
private tryCancelRequest(seq: number, command: string): boolean {
try {
if (this._requestQueue.tryCancelPendingRequest(seq)) {
if (this._requestQueue.tryDeletePendingRequest(seq)) {
this._tracer.logTrace(`TypeScript Server: canceled request with sequence number ${seq}`);
return true;
}
@ -298,7 +298,7 @@ export class TypeScriptServer extends Disposable {
public executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<any> {
const request = this._requestQueue.createRequest(command, args);
const requestInfo: RequestItem = {
request: request,
request,
expectsResponse: executeInfo.expectsResult,
isAsync: executeInfo.isAsync,
queueingType: getQueueingType(command, executeInfo.lowPriority)
@ -337,7 +337,7 @@ export class TypeScriptServer extends Disposable {
} else {
result = Promise.resolve(null);
}
this._requestQueue.push(requestInfo);
this._requestQueue.enqueue(requestInfo);
this.sendNextRequests();
return result;
@ -369,7 +369,7 @@ export class TypeScriptServer extends Disposable {
private sendNextRequests(): void {
while (this._pendingResponses.size === 0 && this._requestQueue.length > 0) {
const item = this._requestQueue.shift();
const item = this._requestQueue.dequeue();
if (item) {
this.sendRequest(item);
}

View file

@ -14,13 +14,13 @@ import FileConfigurationManager from './features/fileConfigurationManager';
import LanguageProvider from './languageProvider';
import * as Proto from './protocol';
import * as PConst from './protocol.const';
import TypeScriptServiceClient, { PluginConfigProvider } from './typescriptServiceClient';
import TypeScriptServiceClient from './typescriptServiceClient';
import API from './utils/api';
import { CommandManager } from './utils/commandManager';
import { Disposable } from './utils/dispose';
import { LanguageDescription, DiagnosticLanguage } from './utils/languageDescription';
import { DiagnosticLanguage, LanguageDescription } from './utils/languageDescription';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import { TypeScriptServerPlugin } from './utils/plugins';
import { PluginManager } from './utils/plugins';
import * as typeConverters from './utils/typeConverters';
import TypingsStatus, { AtaProgressReporter } from './utils/typingsStatus';
import VersionStatus from './utils/versionStatus';
@ -48,8 +48,7 @@ export default class TypeScriptServiceClientHost extends Disposable {
constructor(
descriptions: LanguageDescription[],
workspaceState: vscode.Memento,
plugins: TypeScriptServerPlugin[],
pluginConfigProvider: PluginConfigProvider,
pluginManager: PluginManager,
private readonly commandManager: CommandManager,
logDirectoryProvider: LogDirectoryProvider,
onCompletionAccepted: (item: vscode.CompletionItem) => void,
@ -73,8 +72,7 @@ export default class TypeScriptServiceClientHost extends Disposable {
this.client = this._register(new TypeScriptServiceClient(
workspaceState,
version => this.versionStatus.onDidChangeTypeScriptVersion(version),
plugins,
pluginConfigProvider,
pluginManager,
logDirectoryProvider,
allModeIds));
@ -111,7 +109,7 @@ export default class TypeScriptServiceClientHost extends Disposable {
}
const languages = new Set<string>();
for (const plugin of plugins) {
for (const plugin of pluginManager.plugins) {
for (const language of plugin.languages) {
languages.add(language);
}

View file

@ -9,10 +9,10 @@ import * as Proto from './protocol';
import API from './utils/api';
import { TypeScriptServiceConfiguration } from './utils/configuration';
import Logger from './utils/logger';
import { TypeScriptServerPlugin } from './utils/plugins';
import { PluginManager } from './utils/plugins';
export class CancelledResponse {
readonly type: 'cancelled' = 'cancelled';
public readonly type: 'cancelled' = 'cancelled';
constructor(
public readonly reason: string
@ -20,7 +20,7 @@ export class CancelledResponse {
}
export class NoContentResponse {
readonly type: 'noContent' = 'noContent';
public readonly type: 'noContent' = 'noContent';
}
export type ServerResponse<T extends Proto.Response> = T | CancelledResponse | NoContentResponse;
@ -57,7 +57,6 @@ interface TypeScriptRequestTypes {
'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse];
}
export interface ITypeScriptServiceClient {
/**
* Convert a resource (VS Code) to a normalized path (TypeScript).
@ -87,7 +86,7 @@ export interface ITypeScriptServiceClient {
readonly onTypesInstallerInitializationFailed: vscode.Event<Proto.TypesInstallerInitializationFailedEventBody>;
readonly apiVersion: API;
readonly plugins: TypeScriptServerPlugin[];
readonly pluginManager: PluginManager;
readonly configuration: TypeScriptServiceConfiguration;
readonly logger: Logger;
readonly bufferSyncSupport: BufferSyncSupport;

View file

@ -16,11 +16,10 @@ import API from './utils/api';
import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration';
import { Disposable } from './utils/dispose';
import * as fileSchemes from './utils/fileSchemes';
import * as is from './utils/is';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import Logger from './utils/logger';
import { TypeScriptPluginPathsProvider } from './utils/pluginPathsProvider';
import { TypeScriptServerPlugin } from './utils/plugins';
import { PluginManager } from './utils/plugins';
import TelemetryReporter from './utils/telemetry';
import Tracer from './utils/tracer';
import { inferredProjectConfig } from './utils/tsconfig';
@ -29,22 +28,6 @@ import { TypeScriptVersion, TypeScriptVersionProvider } from './utils/versionPro
const localize = nls.loadMessageBundle();
export class PluginConfigProvider extends Disposable {
private readonly _config = new Map<string, {}>();
private readonly _onDidUpdateConfig = this._register(new vscode.EventEmitter<{ pluginId: string, config: {} }>());
public readonly onDidUpdateConfig = this._onDidUpdateConfig.event;
public set(pluginId: string, config: {}) {
this._config.set(pluginId, config);
this._onDidUpdateConfig.fire({ pluginId, config });
}
public entries(): IterableIterator<[string, {}]> {
return this._config.entries();
}
}
export interface TsDiagnostics {
readonly kind: DiagnosticKind;
readonly resource: vscode.Uri;
@ -90,8 +73,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
constructor(
private readonly workspaceState: vscode.Memento,
private readonly onDidChangeTypeScriptVersion: (version: TypeScriptVersion) => void,
public readonly plugins: TypeScriptServerPlugin[],
private readonly pluginConfigProvider: PluginConfigProvider,
public readonly pluginManager: PluginManager,
private readonly logDirectoryProvider: LogDirectoryProvider,
allModeIds: string[]
) {
@ -150,7 +132,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer);
this._register(this.pluginConfigProvider.onDidUpdateConfig(update => {
this._register(this.pluginManager.onDidUpdateConfig(update => {
this.configurePlugin(update.pluginId, update.config);
}));
}
@ -274,7 +256,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this.lastError = null;
let mytoken = ++this.token;
const handle = this.typescriptServerSpawner.spawn(currentVersion, this.configuration, this.plugins);
const handle = this.typescriptServerSpawner.spawn(currentVersion, this.configuration, this.pluginManager);
this.lastStart = Date.now();
handle.onError((err: Error) => {
@ -420,7 +402,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
private serviceStarted(resendModels: boolean): void {
const configureOptions: Proto.ConfigureRequestArguments = {
hostInfo: 'vscode'
hostInfo: 'vscode',
};
this.executeWithoutWaitingForResponse('configure', configureOptions);
this.setCompilerOptionsForInferredProjects(this._configuration);
@ -429,7 +411,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
}
// Reconfigure any plugins
for (const [config, pluginName] of this.pluginConfigProvider.entries()) {
for (const [config, pluginName] of this.pluginManager.configurations()) {
this.configurePlugin(config, pluginName);
}
}
@ -485,7 +467,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
localize('serverDiedAfterStart', 'The TypeScript language service died 5 times right after it got started. The service will not be restarted.'),
{
title: localize('serverDiedReportIssue', 'Report Issue'),
id: MessageAction.reportIssue
id: MessageAction.reportIssue,
});
/* __GDPR__
"serviceExited" : {
@ -634,7 +616,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this._tsServerLoading = undefined;
}
const diagnosticEvent: Proto.DiagnosticEvent = event;
const diagnosticEvent = event as Proto.DiagnosticEvent;
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
this._onDiagnosticsReceived.fire({
kind: getDignosticsKind(event),
@ -700,10 +682,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType
const typingsInstalledPayload: Proto.TypingsInstalledTelemetryEventPayload = (telemetryData.payload as Proto.TypingsInstalledTelemetryEventPayload);
properties['installedPackages'] = typingsInstalledPayload.installedPackages;
if (is.defined(typingsInstalledPayload.installSuccess)) {
if (typeof typingsInstalledPayload.installSuccess === 'boolean') {
properties['installSuccess'] = typingsInstalledPayload.installSuccess.toString();
}
if (is.string(typingsInstalledPayload.typingsInstallerVersion)) {
if (typeof typingsInstalledPayload.typingsInstallerVersion === 'string') {
properties['typingsInstallerVersion'] = typingsInstalledPayload.typingsInstallerVersion;
}
break;
@ -714,7 +696,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
Object.keys(payload).forEach((key) => {
try {
if (payload.hasOwnProperty(key)) {
properties[key] = is.string(payload[key]) ? payload[key] : JSON.stringify(payload[key]);
properties[key] = typeof payload[key] === 'string' ? payload[key] : JSON.stringify(payload[key]);
}
} catch (e) {
// noop

View file

@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export function equals<T>(one: T[], other: T[], itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
export function equals<T>(one: ReadonlyArray<T>, other: ReadonlyArray<T>, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
if (one.length !== other.length) {
return false;
}
@ -16,6 +16,6 @@ export function equals<T>(one: T[], other: T[], itemEquals: (a: T, b: T) => bool
return true;
}
export function flatten<T>(arr: T[][]): T[] {
return [].concat.apply([], arr);
export function flatten<T>(arr: ReadonlyArray<ReadonlyArray<T>>): T[] {
return ([] as T[]).concat.apply([], arr);
}

View file

@ -38,7 +38,7 @@ function generatePatchedEnv(env: any, modulePath: string): any {
return newEnv;
}
export interface IForkOptions {
export interface ForkOptions {
readonly cwd?: string;
readonly execArgv?: string[];
}
@ -46,7 +46,7 @@ export interface IForkOptions {
export function fork(
modulePath: string,
args: string[],
options: IForkOptions,
options: ForkOptions,
): cp.ChildProcess {
const newEnv = generatePatchedEnv(process.env, modulePath);
return cp.fork(modulePath, args, {

View file

@ -1,18 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const toString = Object.prototype.toString;
export function defined(value: any): boolean {
return typeof value !== 'undefined';
}
export function boolean(value: any): value is boolean {
return value === true || value === false;
}
export function string(value: any): value is string {
return toString.call(value) === '[object String]';
}

View file

@ -5,11 +5,12 @@
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import * as is from './is';
import { memoize } from './memoize';
const localize = nls.loadMessageBundle();
type LogLevel = 'Trace' | 'Info' | 'Error';
export default class Logger {
@memoize
@ -19,17 +20,11 @@ export default class Logger {
private data2String(data: any): string {
if (data instanceof Error) {
if (is.string(data.stack)) {
return data.stack;
}
return (data as Error).message;
return data.stack || data.message;
}
if (is.boolean(data.success) && !data.success && is.string(data.message)) {
if (data.success === false && data.message) {
return data.message;
}
if (is.string(data)) {
return data;
}
return data.toString();
}
@ -37,10 +32,6 @@ export default class Logger {
this.logLevel('Info', message, data);
}
public warn(message: string, data?: any): void {
this.logLevel('Warn', message, data);
}
public error(message: string, data?: any): void {
// See https://github.com/Microsoft/TypeScript/issues/10496
if (data && data.message === 'No content available.') {
@ -49,7 +40,7 @@ export default class Logger {
this.logLevel('Error', message, data);
}
public logLevel(level: string, message: string, data?: any): void {
public logLevel(level: LogLevel, message: string, data?: any): void {
this.output.appendLine(`[${level} - ${(new Date().toLocaleTimeString())}] ${message}`);
if (data) {
this.output.appendLine(this.data2String(data));

View file

@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
export function memoize(_target: any, key: string, descriptor: any) {
let fnKey: string | undefined = undefined;
let fn: Function | undefined = undefined;
let fnKey: string | undefined;
let fn: Function | undefined;
if (typeof descriptor.value === 'function') {
fnKey = 'value';

View file

@ -4,26 +4,45 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { Disposable } from './dispose';
import { memoize } from './memoize';
export interface TypeScriptServerPlugin {
readonly path: string;
readonly name: string;
readonly languages: string[];
readonly languages: ReadonlyArray<string>;
}
export function getContributedTypeScriptServerPlugins(): TypeScriptServerPlugin[] {
const plugins: TypeScriptServerPlugin[] = [];
for (const extension of vscode.extensions.all) {
const pack = extension.packageJSON;
if (pack.contributes && pack.contributes.typescriptServerPlugins && Array.isArray(pack.contributes.typescriptServerPlugins)) {
for (const plugin of pack.contributes.typescriptServerPlugins) {
plugins.push({
name: plugin.name,
path: extension.extensionPath,
languages: Array.isArray(plugin.languages) ? plugin.languages : [],
});
export class PluginManager extends Disposable {
private readonly _pluginConfigurations = new Map<string, {}>();
@memoize
public get plugins(): ReadonlyArray<TypeScriptServerPlugin> {
const plugins: TypeScriptServerPlugin[] = [];
for (const extension of vscode.extensions.all) {
const pack = extension.packageJSON;
if (pack.contributes && Array.isArray(pack.contributes.typescriptServerPlugins)) {
for (const plugin of pack.contributes.typescriptServerPlugins) {
plugins.push({
name: plugin.name,
path: extension.extensionPath,
languages: Array.isArray(plugin.languages) ? plugin.languages : [],
});
}
}
}
return plugins;
}
return plugins;
}
private readonly _onDidUpdateConfig = this._register(new vscode.EventEmitter<{ pluginId: string, config: {} }>());
public readonly onDidUpdateConfig = this._onDidUpdateConfig.event;
public setConfiguration(pluginId: string, config: {}) {
this._pluginConfigurations.set(pluginId, config);
this._onDidUpdateConfig.fire({ pluginId, config });
}
public configurations(): IterableIterator<[string, {}]> {
return this._pluginConfigurations.entries();
}
}

View file

@ -5,6 +5,9 @@
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import TypeScriptServiceClient from '../typescriptServiceClient';
import { Disposable } from './dispose';
import { memoize } from './memoize';
const localize = nls.loadMessageBundle();
@ -121,18 +124,24 @@ class Survey {
}
}
export class Surveyor {
private readonly surveys: Map<string, Survey>;
export class Surveyor extends Disposable {
public constructor(
memento: vscode.Memento
private readonly memento: vscode.Memento,
serviceClient: TypeScriptServiceClient,
) {
this.surveys = new Map<string, Survey>(allSurveys.map(data =>
[data.id, new Survey(data, memento)] as [string, Survey]));
super();
this._register(serviceClient.onSurveyReady(e => this.surveyReady(e.surveyId)));
}
public surveyReady(surveyId: string): void {
@memoize
private get surveys(): Map<string, Survey> {
return new Map<string, Survey>(
allSurveys.map(data => [data.id, new Survey(data, this.memento)] as [string, Survey]));
}
private surveyReady(surveyId: string): void {
const survey = this.tryGetActiveSurvey(surveyId);
if (survey && survey.trigger()) {
survey.willShow();

View file

@ -7,7 +7,7 @@ import * as vscode from 'vscode';
import VsCodeTelemetryReporter from 'vscode-extension-telemetry';
import { memoize } from './memoize';
interface IPackageInfo {
interface PackageInfo {
readonly name: string;
readonly version: string;
readonly aiKey: string;
@ -58,7 +58,7 @@ export default class TelemetryReporter {
}
@memoize
private get packageInfo(): IPackageInfo | null {
private get packageInfo(): PackageInfo | null {
const { packageJSON } = vscode.extensions.getExtension('vscode.typescript-language-features')!;
if (packageJSON) {
return {

View file

@ -10,7 +10,7 @@ import Logger from './logger';
enum Trace {
Off,
Messages,
Verbose
Verbose,
}
namespace Trace {

View file

@ -8,7 +8,6 @@ import * as vscode from 'vscode';
import * as Proto from '../protocol';
import { TypeScriptServiceConfiguration } from './configuration';
export function isImplicitProjectConfigFile(configFileName: string) {
return configFileName.indexOf('/dev/null/') === 0;
}

View file

@ -41,7 +41,7 @@ export namespace Position {
export const toFileLocationRequestArgs = (file: string, position: vscode.Position): Proto.FileLocationRequestArgs => ({
file,
line: position.line + 1,
offset: position.character + 1
offset: position.character + 1,
});
}

View file

@ -19,7 +19,7 @@ interface MyQuickPickItem extends vscode.QuickPickItem {
enum MessageAction {
useLocal,
useBundled,
learnMore
learnMore,
}
export class TypeScriptVersionPicker {
@ -61,7 +61,7 @@ export class TypeScriptVersionPicker {
: '') + localize('useVSCodeVersionOption', 'Use VS Code\'s Version'),
description: shippedVersion.versionString,
detail: shippedVersion.pathLabel,
id: MessageAction.useBundled
id: MessageAction.useBundled,
});
for (const version of this.versionProvider.localVersions) {
@ -72,7 +72,7 @@ export class TypeScriptVersionPicker {
description: version.versionString,
detail: version.pathLabel,
id: MessageAction.useLocal,
version: version
version
});
}
@ -86,7 +86,7 @@ export class TypeScriptVersionPicker {
placeHolder: localize(
'selectTsVersion',
'Select the TypeScript version used for JavaScript and TypeScript language features'),
ignoreFocusOut: firstRun
ignoreFocusOut: firstRun,
});
if (!selected) {
@ -112,7 +112,6 @@ export class TypeScriptVersionPicker {
this._currentVersion = shippedVersion;
return { oldVersion: previousVersion, newVersion: shippedVersion };
case MessageAction.learnMore:
vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=839919'));
return { oldVersion: this.currentVersion };

View file

@ -87,7 +87,6 @@ export class TypeScriptVersion {
}
}
export class TypeScriptVersionProvider {
private readonly relativePathResolver: RelativeWorkspacePathResolver = new RelativeWorkspacePathResolver();

View file

@ -18,7 +18,7 @@ export default class VersionStatus {
this._onChangeEditorSub = vscode.window.onDidChangeActiveTextEditor(this.showHideStatus, this);
}
dispose() {
public dispose() {
this._versionBarEntry.dispose();
this._onChangeEditorSub.dispose();
}

View file

@ -7,29 +7,29 @@ import * as stream from 'stream';
import * as vscode from 'vscode';
import { Disposable } from './dispose';
const DefaultSize: number = 8192;
const ContentLength: string = 'Content-Length: ';
const ContentLengthSize: number = Buffer.byteLength(ContentLength, 'utf8');
const Blank: number = Buffer.from(' ', 'utf8')[0];
const BackslashR: number = Buffer.from('\r', 'utf8')[0];
const BackslashN: number = Buffer.from('\n', 'utf8')[0];
const defaultSize: number = 8192;
const contentLength: string = 'Content-Length: ';
const contentLengthSize: number = Buffer.byteLength(contentLength, 'utf8');
const blank: number = Buffer.from(' ', 'utf8')[0];
const backslashR: number = Buffer.from('\r', 'utf8')[0];
const backslashN: number = Buffer.from('\n', 'utf8')[0];
class ProtocolBuffer {
private index: number = 0;
private buffer: Buffer = Buffer.allocUnsafe(DefaultSize);
private buffer: Buffer = Buffer.allocUnsafe(defaultSize);
public append(data: string | Buffer): void {
let toAppend: Buffer | null = null;
if (Buffer.isBuffer(data)) {
toAppend = <Buffer>data;
toAppend = data;
} else {
toAppend = Buffer.from(<string>data, 'utf8');
toAppend = Buffer.from(data, 'utf8');
}
if (this.buffer.length - this.index >= toAppend.length) {
toAppend.copy(this.buffer, this.index, 0, toAppend.length);
} else {
let newSize = (Math.ceil((this.index + toAppend.length) / DefaultSize) + 1) * DefaultSize;
let newSize = (Math.ceil((this.index + toAppend.length) / defaultSize) + 1) * defaultSize;
if (this.index === 0) {
this.buffer = Buffer.allocUnsafe(newSize);
toAppend.copy(this.buffer, 0, 0, toAppend.length);
@ -44,18 +44,18 @@ class ProtocolBuffer {
let result = -1;
let current = 0;
// we are utf8 encoding...
while (current < this.index && (this.buffer[current] === Blank || this.buffer[current] === BackslashR || this.buffer[current] === BackslashN)) {
while (current < this.index && (this.buffer[current] === blank || this.buffer[current] === backslashR || this.buffer[current] === backslashN)) {
current++;
}
if (this.index < current + ContentLengthSize) {
if (this.index < current + contentLengthSize) {
return result;
}
current += ContentLengthSize;
current += contentLengthSize;
let start = current;
while (current < this.index && this.buffer[current] !== BackslashR) {
while (current < this.index && this.buffer[current] !== backslashR) {
current++;
}
if (current + 3 >= this.index || this.buffer[current + 1] !== BackslashN || this.buffer[current + 2] !== BackslashR || this.buffer[current + 3] !== BackslashN) {
if (current + 3 >= this.index || this.buffer[current + 1] !== backslashN || this.buffer[current + 2] !== backslashR || this.buffer[current + 3] !== backslashN) {
return result;
}
let data = this.buffer.toString('utf8', start, current);
@ -71,7 +71,7 @@ class ProtocolBuffer {
}
let result = this.buffer.toString('utf8', 0, length);
let sourceStart = length;
while (sourceStart < this.index && (this.buffer[sourceStart] === BackslashR || this.buffer[sourceStart] === BackslashN)) {
while (sourceStart < this.index && (this.buffer[sourceStart] === backslashR || this.buffer[sourceStart] === backslashN)) {
sourceStart++;
}
this.buffer.copy(this.buffer, 0, sourceStart);

View file

@ -2,7 +2,7 @@
# yarn lockfile v1
typescript@3.1.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.4.tgz#c74ef7b3c2da65beff548b903022cb8c3cd997ed"
integrity sha512-JZHJtA6ZL15+Q3Dqkbh8iCUmvxD3iJ7ujXS+fVkKnwIVAdHc5BJTDNM0aTrnr2luKulFjU7W+SRhDZvi66Ru7Q==
typescript@3.2.0-rc:
version "3.2.0-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.0-rc.tgz#7c3816f1c761b096f4f1712382e872f4da8f263e"
integrity sha512-RgKDOpEdbU9dAkB4TzxWy46wiyNUKQo0NM0bB7WfvEFw50yu046ldQXpOUYMUTLIAHnToOCtHsu39MYE8o6NCw==

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.30.0",
"distro": "7b34aa08a00cdf1f648720c2605f9ad2cab9c05d",
"distro": "cedfc514fbce202dad3ec5f86033796d70369b2a",
"author": {
"name": "Microsoft Corporation"
},
@ -124,10 +124,10 @@
"sinon": "^1.17.2",
"source-map": "^0.4.4",
"ts-loader": "^4.4.2",
"tslint": "^5.9.1",
"tslint": "^5.11.0",
"typescript": "3.1.4",
"typescript-formatter": "7.1.0",
"typescript-tslint-plugin": "^0.0.5",
"typescript-tslint-plugin": "^0.0.7",
"uglify-es": "^3.0.18",
"underscore": "^1.8.2",
"vinyl": "^0.4.5",

View file

@ -658,8 +658,10 @@
"./vs/workbench/services/configuration/common/configurationModels.ts",
"./vs/workbench/services/configuration/common/jsonEditing.ts",
"./vs/workbench/services/configurationResolver/common/configurationResolver.ts",
"./vs/workbench/services/configurationResolver/common/configurationResolverUtils.ts",
"./vs/workbench/services/crashReporter/electron-browser/crashReporterService.ts",
"./vs/workbench/services/decorations/browser/decorations.ts",
"./vs/workbench/services/decorations/browser/decorationsService.ts",
"./vs/workbench/services/extensions/common/extensions.ts",
"./vs/workbench/services/extensions/common/extensionsRegistry.ts",
"./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts",
@ -688,6 +690,7 @@
"./vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper.ts",
"./vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts",
"./vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts",
"./vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts",
"./vs/workbench/services/mode/common/workbenchModeService.ts",
"./vs/workbench/services/notification/common/notificationService.ts",
"./vs/workbench/services/panel/common/panelService.ts",

View file

@ -20,6 +20,12 @@ export function clearNode(node: HTMLElement): void {
}
}
export function removeNode(node: HTMLElement): void {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
}
export function isInDOM(node: Node | null): boolean {
while (node) {
if (node === document.body) {

View file

@ -6,7 +6,7 @@
import * as DOM from 'vs/base/browser/dom';
import { defaultGenerator } from 'vs/base/common/idGenerator';
import { escape } from 'vs/base/common/strings';
import { removeMarkdownEscapes, IMarkdownString } from 'vs/base/common/htmlContent';
import { removeMarkdownEscapes, IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
import * as marked from 'vs/base/common/marked/marked';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { IDisposable } from 'vs/base/common/lifecycle';
@ -122,6 +122,12 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions
return text;
} else {
// HTML Encode href
href.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
return `<a href="#" data-href="${href}" title="${title || href}">${text}</a>`;
}
};
@ -176,11 +182,11 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions
}
const markedOptions: marked.MarkedOptions = {
sanitize: true,
sanitize: markdown instanceof MarkdownString ? markdown.sanitize : true,
renderer
};
element.innerHTML = marked(markdown.value, markedOptions);
element.innerHTML = marked.parse(markdown.value, markedOptions);
signalInnerHTML!();
return element;

View file

@ -3,9 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as browser from 'vs/base/browser/browser';
import { IframeUtils } from 'vs/base/browser/iframe';
import * as platform from 'vs/base/common/platform';
export interface IMouseEvent {
readonly browserEvent: MouseEvent;
@ -113,26 +111,14 @@ export class DragMouseEvent extends StandardMouseEvent {
}
interface IWebKitMouseWheelEvent {
wheelDeltaY: number;
wheelDeltaX: number;
}
export class StandardWheelEvent {
interface IGeckoMouseWheelEvent {
HORIZONTAL_AXIS: number;
VERTICAL_AXIS: number;
axis: number;
detail: number;
}
export class StandardMouseWheelEvent {
public readonly browserEvent: MouseWheelEvent | null;
public readonly browserEvent: WheelEvent | null;
public readonly deltaY: number;
public readonly deltaX: number;
public readonly target: Node;
constructor(e: MouseWheelEvent | null, deltaX: number = 0, deltaY: number = 0) {
constructor(e: WheelEvent | null, deltaX: number = 0, deltaY: number = 0) {
this.browserEvent = e || null;
this.target = e ? (e.target || (<any>e).targetNode || e.srcElement) : null;
@ -141,30 +127,12 @@ export class StandardMouseWheelEvent {
this.deltaX = deltaX;
if (e) {
let e1 = <IWebKitMouseWheelEvent><any>e;
let e2 = <IGeckoMouseWheelEvent><any>e;
// vertical delta scroll
if (typeof e1.wheelDeltaY !== 'undefined') {
this.deltaY = e1.wheelDeltaY / 120;
} else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) {
this.deltaY = -e2.detail / 3;
}
// horizontal delta scroll
if (typeof e1.wheelDeltaX !== 'undefined') {
if (browser.isSafari && platform.isWindows) {
this.deltaX = - (e1.wheelDeltaX / 120);
} else {
this.deltaX = e1.wheelDeltaX / 120;
}
} else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) {
this.deltaX = -e.detail / 3;
}
// Assume a vertical scroll if nothing else worked
if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) {
this.deltaY = e.wheelDelta / 120;
if (e.deltaMode === e.DOM_DELTA_LINE) {
this.deltaX = -e.deltaX / 3;
this.deltaY = -e.deltaY / 3;
} else if (e.deltaMode === e.DOM_DELTA_PIXEL) {
this.deltaX = -e.deltaX / 120;
this.deltaY = -e.deltaY / 120;
}
}
}
@ -184,4 +152,4 @@ export class StandardMouseWheelEvent {
}
}
}
}
}

View file

@ -206,7 +206,7 @@ export class BaseActionItem extends Disposable implements IActionItem {
dispose(): void {
if (this.element) {
this.element.remove();
DOM.removeNode(this.element);
this.element = null;
}
@ -775,7 +775,7 @@ export class ActionBar extends Disposable implements IActionRunner {
}
this.items = null;
this.getContainer().remove();
DOM.removeNode(this.getContainer());
super.dispose();
}

View file

@ -6,7 +6,7 @@
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor';
import { IMouseEvent, StandardMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { IMouseEvent, StandardWheelEvent } from 'vs/base/browser/mouseEvent';
import { ScrollbarArrow, ScrollbarArrowOptions } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';
import { ScrollbarVisibilityController } from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
@ -25,7 +25,7 @@ export interface ISimplifiedMouseEvent {
}
export interface ScrollbarHost {
onMouseWheel(mouseWheelEvent: StandardMouseWheelEvent): void;
onMouseWheel(mouseWheelEvent: StandardWheelEvent): void;
onDragStart(): void;
onDragEnd(): void;
}

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { StandardMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { StandardWheelEvent } from 'vs/base/browser/mouseEvent';
import { AbstractScrollbar, ISimplifiedMouseEvent, ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
import { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
@ -38,7 +38,7 @@ export class HorizontalScrollbar extends AbstractScrollbar {
right: void 0,
bgWidth: options.arrowSize,
bgHeight: options.horizontalScrollbarSize,
onActivate: () => this._host.onMouseWheel(new StandardMouseWheelEvent(null, 1, 0)),
onActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, 1, 0)),
});
this._createArrow({
@ -49,7 +49,7 @@ export class HorizontalScrollbar extends AbstractScrollbar {
right: arrowDelta,
bgWidth: options.arrowSize,
bgHeight: options.horizontalScrollbarSize,
onActivate: () => this._host.onMouseWheel(new StandardMouseWheelEvent(null, -1, 0)),
onActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, -1, 0)),
});
}

View file

@ -6,7 +6,7 @@
import 'vs/css!./media/scrollbars';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IMouseEvent, StandardMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { IMouseEvent, StandardWheelEvent } from 'vs/base/browser/mouseEvent';
import { ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
import { HorizontalScrollbar } from 'vs/base/browser/ui/scrollbar/horizontalScrollbar';
import { ScrollableElementChangeOptions, ScrollableElementCreationOptions, ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
@ -178,7 +178,7 @@ export abstract class AbstractScrollableElement extends Widget {
}));
let scrollbarHost: ScrollbarHost = {
onMouseWheel: (mouseWheelEvent: StandardMouseWheelEvent) => this._onMouseWheel(mouseWheelEvent),
onMouseWheel: (mouseWheelEvent: StandardWheelEvent) => this._onMouseWheel(mouseWheelEvent),
onDragStart: () => this._onDragStart(),
onDragEnd: () => this._onDragEnd(),
};
@ -307,17 +307,15 @@ export abstract class AbstractScrollableElement extends Widget {
// Start listening (if necessary)
if (shouldListen) {
let onMouseWheel = (browserEvent: MouseWheelEvent) => {
let e = new StandardMouseWheelEvent(browserEvent);
this._onMouseWheel(e);
let onMouseWheel = (browserEvent: WheelEvent) => {
this._onMouseWheel(new StandardWheelEvent(browserEvent));
};
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, 'mousewheel', onMouseWheel));
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, 'DOMMouseScroll', onMouseWheel));
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, 'wheel', onMouseWheel));
}
}
private _onMouseWheel(e: StandardMouseWheelEvent): void {
private _onMouseWheel(e: StandardWheelEvent): void {
const classifier = MouseWheelClassifier.INSTANCE;
if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) {

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { StandardMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { StandardWheelEvent } from 'vs/base/browser/mouseEvent';
import { AbstractScrollbar, ISimplifiedMouseEvent, ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
import { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
@ -39,7 +39,7 @@ export class VerticalScrollbar extends AbstractScrollbar {
right: void 0,
bgWidth: options.verticalScrollbarSize,
bgHeight: options.arrowSize,
onActivate: () => this._host.onMouseWheel(new StandardMouseWheelEvent(null, 0, 1)),
onActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, 0, 1)),
});
this._createArrow({
@ -50,7 +50,7 @@ export class VerticalScrollbar extends AbstractScrollbar {
right: void 0,
bgWidth: options.verticalScrollbarSize,
bgHeight: options.arrowSize,
onActivate: () => this._host.onMouseWheel(new StandardMouseWheelEvent(null, 0, -1)),
onActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, 0, -1)),
});
}

View file

@ -18,6 +18,7 @@
font-size: 10px;
text-align: right;
margin-right: 6px;
flex-shrink: 0;
}
.monaco-tl-contents {

View file

@ -334,7 +334,14 @@ export function move(array: any[], from: number, to: number): void {
* and not empty.
*/
export function isFalsyOrEmpty(obj: any): boolean {
return !Array.isArray(obj) || (<Array<any>>obj).length === 0;
return !Array.isArray(obj) || obj.length === 0;
}
/**
* @returns {{true}} if the provided object is an array and has at least one element.
*/
export function isNonEmptyArray<T>(obj: ReadonlyArray<T> | undefined | null): obj is Array<T> {
return Array.isArray(obj) && obj.length > 0;
}
/**

View file

@ -16,6 +16,7 @@ export class MarkdownString implements IMarkdownString {
value: string;
isTrusted?: boolean;
sanitize: boolean = true;
constructor(value: string = '') {
this.value = value;

View file

@ -10,7 +10,7 @@ import { CharCode } from 'vs/base/common/charCode';
*/
export const empty = '';
export function isFalsyOrWhitespace(str: string): boolean {
export function isFalsyOrWhitespace(str: string | undefined): boolean {
if (!str || typeof str !== 'string') {
return true;
}

View file

@ -6,6 +6,15 @@
import { transformErrorForSerialization } from 'vs/base/common/errors';
import { Disposable } from 'vs/base/common/lifecycle';
import { isWeb } from 'vs/base/common/platform';
import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise';
var global: any = self;
// When missing, polyfill the native promise
// with our winjs-based polyfill
if (typeof global.Promise === 'undefined') {
global.Promise = PolyfillPromise;
}
const INITIALIZE = '$initialize';

View file

@ -17,7 +17,7 @@ export const UTF16le = 'utf16le';
export interface IDecodeStreamOptions {
guessEncoding?: boolean;
minBytesRequiredForDetection?: number;
overwriteEncoding?(detectedEncoding: string): string;
overwriteEncoding?(detectedEncoding: string | null): string;
}
export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions): Promise<{ detected: IDetectedEncodingResult, stream: NodeJS.ReadableStream }> {
@ -78,7 +78,7 @@ export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions
this._decodeStreamConstruction = Promise.resolve(detectEncodingFromBuffer({
buffer: Buffer.concat(this._buffer), bytesRead: this._bytesBuffered
}, options.guessEncoding)).then(detected => {
if (options.overwriteEncoding && detected.encoding) {
if (options.overwriteEncoding) {
detected.encoding = options.overwriteEncoding(detected.encoding);
}
this._decodeStream = decodeStream(detected.encoding);

View file

@ -19,8 +19,8 @@ import * as errors from 'vs/base/common/errors';
* We should move all implementations to use named ipc.net, so we stop depending on cp.fork.
*/
export class Server extends IPCServer {
constructor() {
export class Server<TContext extends string> extends IPCServer<TContext> {
constructor(ctx: TContext) {
super({
send: r => {
try {
@ -30,7 +30,7 @@ export class Server extends IPCServer {
} catch (e) { /* not much to do */ }
},
onMessage: fromNodeEventEmitter(process, 'message', msg => Buffer.from(msg, 'base64'))
});
}, ctx);
process.once('disconnect', () => this.dispose());
}

View file

@ -231,15 +231,15 @@ export class Server extends IPCServer {
}
}
export class Client extends IPCClient {
export class Client<TContext = string> extends IPCClient<TContext> {
static fromSocket(socket: Socket, id: string): Client {
static fromSocket<TContext = string>(socket: Socket, id: TContext): Client<TContext> {
return new Client(new Protocol(socket), id);
}
get onClose(): Event<void> { return this.protocol.onClose; }
constructor(private protocol: Protocol, id: string) {
constructor(private protocol: Protocol, id: TContext) {
super(protocol, id);
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter, once, filterEvent, toPromise, Relay } from 'vs/base/common/event';
import { Event, Emitter, once, toPromise, Relay } from 'vs/base/common/event';
import { always, CancelablePromise, createCancelablePromise, timeout } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
@ -62,12 +62,22 @@ export interface IChannel {
listen<T>(event: string, arg?: any): Event<T>;
}
/**
* An `IServerChannel` is the couter part to `IChannel`,
* on the server-side. You should implement this interface
* if you'd like to handle remote promises or events.
*/
export interface IServerChannel<TContext = string> {
call<T>(ctx: TContext, command: string, arg?: any, cancellationToken?: CancellationToken): Thenable<T>;
listen<T>(ctx: TContext, event: string, arg?: any): Event<T>;
}
/**
* An `IChannelServer` hosts a collection of channels. You are
* able to register channels onto it, provided a channel name.
*/
export interface IChannelServer {
registerChannel(channelName: string, channel: IChannel): void;
export interface IChannelServer<TContext = string> {
registerChannel(channelName: string, channel: IServerChannel<TContext>): void;
}
/**
@ -78,14 +88,23 @@ export interface IChannelClient {
getChannel<T extends IChannel>(channelName: string): T;
}
export interface Client<TContext> {
readonly ctx: TContext;
}
export interface IConnectionHub<TContext> {
readonly connections: Connection<TContext>[];
readonly onDidChangeConnections: Event<Connection<TContext>>;
}
/**
* An `IClientRouter` is responsible for routing calls to specific
* channels, in scenarios in which there are multiple possible
* channels (each from a separate client) to pick from.
*/
export interface IClientRouter {
routeCall(clientIds: string[], command: string, arg?: any, cancellationToken?: CancellationToken): Thenable<string>;
routeEvent(clientIds: string[], event: string, arg?: any): Thenable<string>;
export interface IClientRouter<TContext = string> {
routeCall(hub: IConnectionHub<TContext>, command: string, arg?: any, cancellationToken?: CancellationToken): Thenable<Client<TContext>>;
routeEvent(hub: IConnectionHub<TContext>, event: string, arg?: any): Thenable<Client<TContext>>;
}
/**
@ -95,8 +114,8 @@ export interface IClientRouter {
* the same channel. You'll need to pass in an `IClientRouter` in
* order to pick the right one.
*/
export interface IRoutingChannelClient {
getChannel<T extends IChannel>(channelName: string, router: IClientRouter): T;
export interface IRoutingChannelClient<TContext = string> {
getChannel<T extends IChannel>(channelName: string, router: IClientRouter<TContext>): T;
}
interface IReader {
@ -207,18 +226,18 @@ function deserialize(reader: IReader): any {
}
}
export class ChannelServer implements IChannelServer, IDisposable {
export class ChannelServer<TContext = string> implements IChannelServer<TContext>, IDisposable {
private channels = new Map<string, IChannel>();
private channels = new Map<string, IServerChannel<TContext>>();
private activeRequests = new Map<number, IDisposable>();
private protocolListener: IDisposable | null;
constructor(private protocol: IMessagePassingProtocol) {
constructor(private protocol: IMessagePassingProtocol, private ctx: TContext) {
this.protocolListener = this.protocol.onMessage(msg => this.onRawMessage(msg));
this.sendResponse({ type: ResponseType.Initialize });
}
registerChannel(channelName: string, channel: IChannel): void {
registerChannel(channelName: string, channel: IServerChannel<TContext>): void {
this.channels.set(channelName, channel);
}
@ -274,7 +293,7 @@ export class ChannelServer implements IChannelServer, IDisposable {
let promise: Thenable<any>;
try {
promise = channel.call(request.name, request.arg, cancellationTokenSource.token);
promise = channel.call(this.ctx, request.name, request.arg, cancellationTokenSource.token);
} catch (err) {
promise = Promise.reject(err);
}
@ -308,7 +327,7 @@ export class ChannelServer implements IChannelServer, IDisposable {
const channel = this.channels.get(request.channelName);
const id = request.id;
const event = channel.listen(request.name, request.arg);
const event = channel.listen(this.ctx, request.name, request.arg);
const disposable = event(data => this.sendResponse(<IRawResponse>{ id, data, type: ResponseType.EventFire }));
this.activeRequests.set(request.id, disposable);
@ -543,6 +562,10 @@ export interface ClientConnectionEvent {
onDidClientDisconnect: Event<void>;
}
interface Connection<TContext> extends Client<TContext> {
readonly channelClient: ChannelClient;
}
/**
* An `IPCServer` is both a channel server and a routing channel
* client.
@ -551,15 +574,17 @@ export interface ClientConnectionEvent {
* and the `IPCClient` classes to get IPC implementations
* for your protocol.
*/
export class IPCServer implements IChannelServer, IRoutingChannelClient, IDisposable {
export class IPCServer<TContext = string> implements IChannelServer<TContext>, IRoutingChannelClient<TContext>, IConnectionHub<TContext>, IDisposable {
private channels = new Map<string, IChannel>();
private channelClients = new Map<string, ChannelClient>();
private onClientAdded = new Emitter<string>();
private channels = new Map<string, IServerChannel<TContext>>();
private _connections = new Set<Connection<TContext>>();
private get clientKeys(): string[] {
const result: string[] = [];
this.channelClients.forEach((_, key) => result.push(key));
private _onDidChangeConnections = new Emitter<Connection<TContext>>();
readonly onDidChangeConnections: Event<Connection<TContext>> = this._onDidChangeConnections.event;
get connections(): Connection<TContext>[] {
const result: Connection<TContext>[] = [];
this._connections.forEach(ctx => result.push(ctx));
return result;
}
@ -567,46 +592,42 @@ export class IPCServer implements IChannelServer, IRoutingChannelClient, IDispos
onDidClientConnect(({ protocol, onDidClientDisconnect }) => {
const onFirstMessage = once(protocol.onMessage);
onFirstMessage(rawId => {
const channelServer = new ChannelServer(protocol);
onFirstMessage(msg => {
const reader = new BufferReader(msg);
const ctx = deserialize(reader) as TContext;
const channelServer = new ChannelServer(protocol, ctx);
const channelClient = new ChannelClient(protocol);
this.channels.forEach((channel, name) => channelServer.registerChannel(name, channel));
const id = rawId.toString();
if (this.channelClients.has(id)) {
console.warn(`IPC client with id '${id}' is already registered.`);
}
this.channelClients.set(id, channelClient);
this.onClientAdded.fire(id);
const connection: Connection<TContext> = { channelClient, ctx };
this._connections.add(connection);
this._onDidChangeConnections.fire(connection);
onDidClientDisconnect(() => {
channelServer.dispose();
channelClient.dispose();
this.channelClients.delete(id);
this._connections.delete(connection);
});
});
});
}
getChannel<T extends IChannel>(channelName: string, router: IClientRouter): T {
getChannel<T extends IChannel>(channelName: string, router: IClientRouter<TContext>): T {
const that = this;
return {
call(command: string, arg?: any, cancellationToken?: CancellationToken) {
const channelPromise = router.routeCall(that.clientKeys, command, arg)
.then(id => that.getClient(id))
.then(client => client.getChannel(channelName));
const channelPromise = router.routeCall(that, command, arg)
.then(connection => (connection as Connection<TContext>).channelClient.getChannel(channelName));
return getDelayedChannel(channelPromise)
.call(command, arg, cancellationToken);
},
listen(event: string, arg: any) {
const channelPromise = router.routeEvent(that.clientKeys, event, arg)
.then(id => that.getClient(id))
.then(client => client.getChannel(channelName));
const channelPromise = router.routeEvent(that, event, arg)
.then(connection => (connection as Connection<TContext>).channelClient.getChannel(channelName));
return getDelayedChannel(channelPromise)
.listen(event, arg);
@ -614,31 +635,14 @@ export class IPCServer implements IChannelServer, IRoutingChannelClient, IDispos
} as T;
}
registerChannel(channelName: string, channel: IChannel): void {
registerChannel(channelName: string, channel: IServerChannel<TContext>): void {
this.channels.set(channelName, channel);
}
private getClient(clientId: string): Thenable<IChannelClient> {
if (!clientId) {
return Promise.reject(new Error('Client id should be provided'));
}
const client = this.channelClients.get(clientId);
if (client) {
return Promise.resolve(client);
}
return new Promise<IChannelClient>(c => {
const onClient = once(filterEvent(this.onClientAdded.event, id => id === clientId));
onClient(() => c(this.channelClients.get(clientId)));
});
}
dispose(): void {
this.channels.clear();
this.channelClients.clear();
this.onClientAdded.dispose();
this._connections.clear();
this._onDidChangeConnections.dispose();
}
}
@ -649,22 +653,25 @@ export class IPCServer implements IChannelServer, IRoutingChannelClient, IDispos
* and the `IPCClient` classes to get IPC implementations
* for your protocol.
*/
export class IPCClient implements IChannelClient, IChannelServer, IDisposable {
export class IPCClient<TContext = string> implements IChannelClient, IChannelServer<TContext>, IDisposable {
private channelClient: ChannelClient;
private channelServer: ChannelServer;
private channelServer: ChannelServer<TContext>;
constructor(protocol: IMessagePassingProtocol, ctx: TContext) {
const writer = new BufferWriter();
serialize(writer, ctx);
protocol.send(writer.buffer);
constructor(protocol: IMessagePassingProtocol, id: string) {
protocol.send(Buffer.from(id));
this.channelClient = new ChannelClient(protocol);
this.channelServer = new ChannelServer(protocol);
this.channelServer = new ChannelServer(protocol, ctx);
}
getChannel<T extends IChannel>(channelName: string): T {
return this.channelClient.getChannel(channelName) as T;
}
registerChannel(channelName: string, channel: IChannel): void {
registerChannel(channelName: string, channel: IServerChannel<TContext>): void {
this.channelServer.registerChannel(channelName, channel);
}
@ -716,3 +723,27 @@ export function getNextTickChannel<T extends IChannel>(channel: T): T {
}
} as T;
}
export class StaticRouter<TContext = string> implements IClientRouter<TContext> {
constructor(private fn: (ctx: TContext) => boolean | Thenable<boolean>) { }
routeCall(hub: IConnectionHub<TContext>): Thenable<Client<TContext>> {
return this.route(hub);
}
routeEvent(hub: IConnectionHub<TContext>): Thenable<Client<TContext>> {
return this.route(hub);
}
private async route(hub: IConnectionHub<TContext>): Promise<Client<TContext>> {
for (const connection of hub.connections) {
if (await Promise.resolve(this.fn(connection.ctx))) {
return Promise.resolve(connection);
}
}
await toPromise(hub.onDidChangeConnections);
return await this.route(hub);
}
}

View file

@ -6,7 +6,7 @@
import * as assert from 'assert';
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
import { always } from 'vs/base/common/async';
import { ITestChannel, TestServiceClient } from './testService';
import { TestServiceClient } from './testService';
import { getPathFromAmdModule } from 'vs/base/common/amd';
function createClient(): Client {
@ -19,7 +19,7 @@ function createClient(): Client {
suite('IPC, Child Process', () => {
test('createChannel', () => {
const client = createClient();
const channel = client.getChannel<ITestChannel>('test');
const channel = client.getChannel('test');
const service = new TestServiceClient(channel);
const result = service.pong('ping').then(r => {
@ -32,7 +32,7 @@ suite('IPC, Child Process', () => {
test('events', () => {
const client = createClient();
const channel = client.getChannel<ITestChannel>('test');
const channel = client.getChannel('test');
const service = new TestServiceClient(channel);
const event = new Promise((c, e) => {
@ -54,7 +54,7 @@ suite('IPC, Child Process', () => {
test('event dispose', () => {
const client = createClient();
const channel = client.getChannel<ITestChannel>('test');
const channel = client.getChannel('test');
const service = new TestServiceClient(channel);
let count = 0;

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Emitter, toPromise, Event } from 'vs/base/common/event';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors';
@ -54,7 +54,7 @@ function createProtocolPair(): [IMessagePassingProtocol, IMessagePassingProtocol
return [one, other];
}
class TestIPCClient extends IPCClient {
class TestIPCClient extends IPCClient<string> {
private _onDidDisconnect = new Emitter<void>();
readonly onDidDisconnect = this._onDidDisconnect.event;
@ -69,7 +69,7 @@ class TestIPCClient extends IPCClient {
}
}
class TestIPCServer extends IPCServer {
class TestIPCServer extends IPCServer<string> {
private onDidClientConnect: Emitter<ClientConnectionEvent>;
@ -79,7 +79,7 @@ class TestIPCServer extends IPCServer {
this.onDidClientConnect = onDidClientConnect;
}
createConnection(id: string): IPCClient {
createConnection(id: string): IPCClient<string> {
const [pc, ps] = createProtocolPair();
const client = new TestIPCClient(pc, id);
@ -138,23 +138,11 @@ class TestService implements ITestService {
}
}
interface ITestChannel extends IChannel {
call(command: 'marco'): Thenable<string>;
call(command: 'error'): Thenable<void>;
call(command: 'neverComplete'): Thenable<void>;
call(command: 'neverCompleteCT', arg: undefined, cancellationToken: CancellationToken): Thenable<void>;
call(command: 'buffersLength', arg: [Buffer, Buffer]): Thenable<void>;
call<T>(command: string, arg?: any, cancellationToken?: CancellationToken): Thenable<T>;
listen(event: 'pong'): Event<string>;
listen<T>(event: string, arg?: any): Event<T>;
}
class TestChannel implements ITestChannel {
class TestChannel implements IServerChannel {
constructor(private service: ITestService) { }
call(command: string, arg?: any, cancellationToken?: CancellationToken): Thenable<any> {
call(_, command: string, arg?: any, cancellationToken?: CancellationToken): Thenable<any> {
switch (command) {
case 'marco': return this.service.marco();
case 'error': return this.service.error(arg);
@ -165,7 +153,7 @@ class TestChannel implements ITestChannel {
}
}
listen(event: string, arg?: any): Event<any> {
listen(_, event: string, arg?: any): Event<any> {
switch (event) {
case 'pong': return this.service.pong;
default: throw new Error('not implemented');
@ -179,7 +167,7 @@ class TestChannelClient implements ITestService {
return this.channel.listen('pong');
}
constructor(private channel: ITestChannel) { }
constructor(private channel: IChannel) { }
marco(): Thenable<string> {
return this.channel.call('marco');

View file

@ -6,6 +6,6 @@
import { Server } from 'vs/base/parts/ipc/node/ipc.cp';
import { TestChannel, TestService } from './testService';
const server = new Server();
const server = new Server('test');
const service = new TestService();
server.registerChannel('test', new TestChannel(service));

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async';
@ -37,21 +37,11 @@ export class TestService implements ITestService {
}
}
export interface ITestChannel extends IChannel {
listen<IMarcoPoloEvent>(event: 'marco'): Event<IMarcoPoloEvent>;
listen<T>(event: string, arg?: any): Event<T>;
call(command: 'marco'): Thenable<any>;
call(command: 'pong', ping: string): Thenable<any>;
call(command: 'cancelMe'): Thenable<any>;
call(command: string, ...args: any[]): Thenable<any>;
}
export class TestChannel implements ITestChannel {
export class TestChannel implements IServerChannel {
constructor(private testService: ITestService) { }
listen(event: string, arg?: any): Event<any> {
listen(_, event: string): Event<any> {
switch (event) {
case 'marco': return this.testService.onMarco;
}
@ -59,12 +49,12 @@ export class TestChannel implements ITestChannel {
throw new Error('Event not found');
}
call(command: string, ...args: any[]): Thenable<any> {
call(_, command: string, ...args: any[]): Thenable<any> {
switch (command) {
case 'pong': return this.testService.pong(args[0]);
case 'cancelMe': return this.testService.cancelMe();
case 'marco': return this.testService.marco();
default: return Promise.reject(new Error('command not found'));
default: return Promise.reject(new Error(`command not found: ${command}`));
}
}
}
@ -73,7 +63,7 @@ export class TestServiceClient implements ITestService {
get onMarco(): Event<IMarcoPoloEvent> { return this.channel.listen('marco'); }
constructor(private channel: ITestChannel) { }
constructor(private channel: IChannel) { }
marco(): Thenable<string> {
return this.channel.call('marco');

View file

@ -849,6 +849,7 @@ export class TreeView extends HeightMap {
}
private set scrollHeight(scrollHeight: number) {
scrollHeight = scrollHeight + (this.horizontalScrolling ? 10 : 0);
this.scrollableElement.setScrollDimensions({ scrollHeight });
}
@ -871,12 +872,9 @@ export class TreeView extends HeightMap {
}
public set scrollTop(scrollTop: number) {
this.scrollableElement.setScrollDimensions({
scrollHeight: this.getContentHeight()
});
this.scrollableElement.setScrollPosition({
scrollTop: scrollTop
});
const scrollHeight = this.getContentHeight() + (this.horizontalScrolling ? 10 : 0);
this.scrollableElement.setScrollDimensions({ scrollHeight });
this.scrollableElement.setScrollPosition({ scrollTop });
}
public getScrollPosition(): number {

View file

@ -5,16 +5,15 @@
import * as assert from 'assert';
import { IPager, PagedModel } from 'vs/base/common/paging';
import { TPromise } from 'vs/base/common/winjs.base';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { isPromiseCanceledError, canceled } from 'vs/base/common/errors';
function getPage(pageIndex: number, cancellationToken: CancellationToken): Thenable<number[]> {
if (cancellationToken.isCancellationRequested) {
return TPromise.wrapError(canceled());
return Promise.reject(canceled());
}
return TPromise.as([0, 1, 2, 3, 4].map(i => i + (pageIndex * 5)));
return Promise.resolve([0, 1, 2, 3, 4].map(i => i + (pageIndex * 5)));
}
class TestPager implements IPager<number> {
@ -102,7 +101,7 @@ suite('PagedModel', () => {
test('preemptive cancellation works', async function () {
const pager = new TestPager(() => {
assert(false);
return TPromise.wrap([]);
return Promise.resolve([]);
});
const model = new PagedModel(pager);
@ -117,7 +116,7 @@ suite('PagedModel', () => {
});
test('cancellation works', function () {
const pager = new TestPager((_, token) => new TPromise((_, e) => {
const pager = new TestPager((_, token) => new Promise((_, e) => {
token.onCancellationRequested(() => e(canceled()));
}));
@ -140,7 +139,7 @@ suite('PagedModel', () => {
const pager = new TestPager((pageIndex, token) => {
state = 'resolving';
return new TPromise((_, e) => {
return new Promise((_, e) => {
token.onCancellationRequested(() => {
state = 'idle';
e(canceled());
@ -180,6 +179,6 @@ suite('PagedModel', () => {
}, 10);
}, 10);
return TPromise.join([promise1, promise2]);
return Promise.all([promise1, promise2]);
});
});
});

View file

@ -24,7 +24,7 @@ import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/commo
import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
@ -283,7 +283,7 @@ export class IssueReporter extends Disposable {
const instantiationService = new InstantiationService(serviceCollection, true);
if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender')));
const appender = combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(logService));
const commonProperties = resolveCommonProperties(product.commit, pkg.version, configuration.machineId, this.environmentService.installSourcePath);
const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath];

View file

@ -8,7 +8,6 @@ import * as platform from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import { serve, Server, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { TPromise } from 'vs/base/common/winjs.base';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
@ -46,6 +45,8 @@ import { IDownloadService } from 'vs/platform/download/common/download';
import { RemoteAuthorityResolverService } from 'vs/platform/remote/node/remoteAuthorityResolverService';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { RemoteAuthorityResolverChannel } from 'vs/platform/remote/node/remoteAuthorityResolverChannel';
import { StaticRouter } from 'vs/base/parts/ipc/node/ipc';
import { DefaultURITransformer } from 'vs/base/common/uriIpc';
export interface ISharedProcessConfiguration {
readonly machineId: string;
@ -75,8 +76,9 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I
disposables.push(server);
const environmentService = new EnvironmentService(initData.args, process.execPath);
const mainRoute = () => TPromise.as('main');
const logLevelClient = new LogLevelSetterChannelClient(server.getChannel('loglevel', { routeCall: mainRoute, routeEvent: mainRoute }));
const mainRouter = new StaticRouter(ctx => ctx === 'main');
const logLevelClient = new LogLevelSetterChannelClient(server.getChannel('loglevel', mainRouter));
const logService = new FollowerLogService(logLevelClient, createSpdLogService('sharedprocess', initData.logLevel, environmentService.logsPath));
disposables.push(logService);
@ -88,14 +90,13 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I
services.set(IRequestService, new SyncDescriptor(RequestService));
services.set(IDownloadService, new SyncDescriptor(DownloadService));
const windowsChannel = server.getChannel('windows', { routeCall: mainRoute, routeEvent: mainRoute });
const windowsChannel = server.getChannel('windows', mainRouter);
const windowsService = new WindowsChannelClient(windowsChannel);
services.set(IWindowsService, windowsService);
const activeWindowManager = new ActiveWindowManager(windowsService);
const route = () => activeWindowManager.getActiveClientId();
const dialogChannel = server.getChannel('dialog', { routeCall: route, routeEvent: route });
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
const dialogChannel = server.getChannel('dialog', activeWindowRouter);
services.set(IDialogService, new DialogChannelClient(dialogChannel));
const instantiationService = new InstantiationService(services);
@ -140,7 +141,7 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I
server.registerChannel('remoteAuthorityResolver', remoteAuthorityResolverChannel);
const extensionManagementService = accessor.get(IExtensionManagementService);
const channel = new ExtensionManagementChannel(extensionManagementService);
const channel = new ExtensionManagementChannel(extensionManagementService, () => DefaultURITransformer);
server.registerChannel('extensions', channel);
// clean up deprecated extensions
@ -191,15 +192,14 @@ function setupIPC(hook: string): Thenable<Server> {
return setup(true);
}
function startHandshake(): TPromise<ISharedProcessInitData> {
return new TPromise<ISharedProcessInitData>((c, e) => {
async function handshake(configuration: ISharedProcessConfiguration): Promise<void> {
const data = await new Promise<ISharedProcessInitData>(c => {
ipcRenderer.once('handshake:hey there', (_: any, r: ISharedProcessInitData) => c(r));
ipcRenderer.send('handshake:hello');
});
}
function handshake(configuration: ISharedProcessConfiguration): TPromise<void> {
return startHandshake()
.then(data => setupIPC(data.sharedIPCHandle).then(server => main(server, data, configuration)))
.then(() => ipcRenderer.send('handshake:im ready'));
const server = await setupIPC(data.sharedIPCHandle);
main(server, data, configuration);
ipcRenderer.send('handshake:im ready');
}

View file

@ -29,10 +29,10 @@ import { IURLService } from 'vs/platform/url/common/url';
import { URLHandlerChannelClient, URLServiceChannel } from 'vs/platform/url/node/urlIpc';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/node/ipc';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
@ -57,7 +57,7 @@ import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
import * as errors from 'vs/base/common/errors';
import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener';
import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver';
import { connectRemoteAgentManagement } from 'vs/platform/remote/node/remoteAgentConnection';
import { connectRemoteAgentManagement, RemoteAgentConnectionContext } from 'vs/platform/remote/node/remoteAgentConnection';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { MenubarService } from 'vs/platform/menubar/electron-main/menubarService';
import { MenubarChannel } from 'vs/platform/menubar/node/menubarIpc';
@ -70,8 +70,8 @@ import { nativeSep, join } from 'vs/base/common/paths';
import { homedir } from 'os';
import { localize } from 'vs/nls';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IRemoteAuthorityResolverChannel, RemoteAuthorityResolverChannelClient } from 'vs/platform/remote/node/remoteAuthorityResolverChannel';
import { IRemoteAgentFileSystemChannel, REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/platform/remote/node/remoteAgentFileSystemChannel';
import { RemoteAuthorityResolverChannelClient } from 'vs/platform/remote/node/remoteAuthorityResolverChannel';
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/platform/remote/node/remoteAgentFileSystemChannel';
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { SnapUpdateService } from 'vs/platform/update/electron-main/updateService.snap';
@ -174,13 +174,13 @@ export class CodeApplication {
class ActiveConnection {
private _authority: string;
private _client: TPromise<Client>;
private _client: TPromise<Client<RemoteAgentConnectionContext>>;
private _disposeRunner: RunOnceScheduler;
constructor(authority: string, connectionInfo: TPromise<ResolvedAuthority>) {
this._authority = authority;
this._client = connectionInfo.then(({ host, port }) => {
return connectRemoteAgentManagement(host, port, `main`);
return connectRemoteAgentManagement(authority, host, port, `main`);
});
this._disposeRunner = new RunOnceScheduler(() => this._dispose(), 5000);
}
@ -193,7 +193,7 @@ export class CodeApplication {
});
}
public getClient(): TPromise<Client> {
public getClient(): TPromise<Client<RemoteAgentConnectionContext>> {
this._disposeRunner.schedule();
return this._client;
}
@ -210,7 +210,7 @@ export class CodeApplication {
activeConnection = connectionPool.get(uri.authority);
} else {
if (this.sharedProcessClient) {
const remoteAuthorityResolverChannel = getDelayedChannel<IRemoteAuthorityResolverChannel>(this.sharedProcessClient.then(c => c.getChannel('remoteAuthorityResolver')));
const remoteAuthorityResolverChannel = getDelayedChannel(this.sharedProcessClient.then(c => c.getChannel('remoteAuthorityResolver')));
const remoteAuthorityResolverChannelClient = new RemoteAuthorityResolverChannelClient(remoteAuthorityResolverChannel);
activeConnection = new ActiveConnection(uri.authority, remoteAuthorityResolverChannelClient.resolveAuthority(uri.authority));
connectionPool.set(uri.authority, activeConnection);
@ -219,8 +219,10 @@ export class CodeApplication {
try {
const rawClient = await activeConnection.getClient();
if (connectionPool.has(uri.authority)) { // not disposed in the meantime
const channel = rawClient.getChannel<IRemoteAgentFileSystemChannel>(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
const fileContents = await channel.call('readFile', [uri.authority, uri]);
const channel = rawClient.getChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
// TODO@alex don't use call directly, wrap it around a `RemoteExtensionsFileSystemProvider`
const fileContents = await channel.call<Uint8Array>('readFile', [uri]);
callback(Buffer.from(fileContents));
} else {
callback(null);
@ -510,7 +512,7 @@ export class CodeApplication {
// Telemtry
if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
const channel = getDelayedChannel<ITelemetryAppenderChannel>(this.sharedProcessClient.then(c => c.getChannel('telemetryAppender')));
const channel = getDelayedChannel(this.sharedProcessClient.then(c => c.getChannel('telemetryAppender')));
const appender = combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(this.logService));
const commonProperties = resolveCommonProperties(product.commit, pkg.version, machineId, this.environmentService.installSourcePath);
const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath];
@ -573,8 +575,8 @@ export class CodeApplication {
// Create a URL handler which forwards to the last active window
const activeWindowManager = new ActiveWindowManager(windowsService);
const route = () => activeWindowManager.getActiveClientId();
const urlHandlerChannel = this.electronIpcServer.getChannel('urlHandler', { routeCall: route, routeEvent: route });
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
const urlHandlerChannel = this.electronIpcServer.getChannel('urlHandler', activeWindowRouter);
const multiplexURLHandler = new URLHandlerChannelClient(urlHandlerChannel);
// On Mac, Code can be running without any open windows, so we must create a window to handle urls,

View file

@ -9,12 +9,12 @@ import * as fs from 'fs';
import * as path from 'path';
import { localize } from 'vs/nls';
import { ILaunchChannel } from 'vs/platform/launch/electron-main/launchService';
import product from 'vs/platform/node/product';
import { IRequestService } from 'vs/platform/request/node/request';
import { IRequestContext } from 'vs/base/node/request';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ILaunchService } from 'vs/platform/launch/electron-main/launchService';
interface PostResult {
readonly blob_id: string;
@ -32,7 +32,7 @@ class Endpoint {
}
export async function uploadLogs(
channel: ILaunchChannel,
launchService: ILaunchService,
requestService: IRequestService,
environmentService: IEnvironmentService
): Promise<any> {
@ -42,7 +42,7 @@ export async function uploadLogs(
return;
}
const logsPath = await channel.call('get-logs-path', null);
const logsPath = await launchService.getLogsPath();
if (await promptUserToConfirmLogUpload(logsPath, environmentService)) {
console.log(localize('beginUploading', 'Uploading...'));

View file

@ -15,7 +15,7 @@ import { validatePaths } from 'vs/code/node/paths';
import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { TPromise } from 'vs/base/common/winjs.base';
import { ILaunchChannel, LaunchChannelClient } from 'vs/platform/launch/electron-main/launchService';
import { LaunchChannelClient } from 'vs/platform/launch/electron-main/launchService';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/node/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@ -196,7 +196,7 @@ function setupIPC(accessor: ServicesAccessor): Thenable<Server> {
}, 10000);
}
const channel = client.getChannel<ILaunchChannel>('launch');
const channel = client.getChannel('launch');
const service = new LaunchChannelClient(channel);
// Process Info
@ -208,7 +208,7 @@ function setupIPC(accessor: ServicesAccessor): Thenable<Server> {
// Log uploader
if (typeof environmentService.args['upload-logs'] !== 'undefined') {
return uploadLogs(channel, requestService, environmentService)
return uploadLogs(service, requestService, environmentService)
.then(() => Promise.reject(new ExpectedError()));
}

Some files were not shown because too many files have changed in this diff Show more