From 249ecba198954e8e3a9b396e664c50197c31318b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 3 Oct 2017 15:58:08 +0200 Subject: [PATCH 001/394] integrate smoketest in product builds --- build/tfs/darwin/build.sh | 10 +++++++++ build/tfs/darwin/build2.sh | 41 ------------------------------------- build/tfs/linux/build.sh | 15 ++++++++++++++ build/tfs/win32/1_build.ps1 | 7 +++++++ 4 files changed, 32 insertions(+), 41 deletions(-) delete mode 100755 build/tfs/darwin/build2.sh diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index b13aaa78820..663207eae9e 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -37,6 +37,16 @@ step "Run unit tests" \ step "Run integration tests" \ ./scripts/test-integration.sh +function smoketest { + SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" + rm -rf $SCREENSHOTS + + npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS +} + +step "Run smoke test" \ + smoketest + step "Publish release" \ ./build/tfs/darwin/release.sh diff --git a/build/tfs/darwin/build2.sh b/build/tfs/darwin/build2.sh deleted file mode 100755 index 350f594da7d..00000000000 --- a/build/tfs/darwin/build2.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -. ./build/tfs/common/node.sh -. ./scripts/env.sh -. ./build/tfs/common/common.sh - -export VSCODE_MIXIN_PASSWORD="$1" -export AZURE_STORAGE_ACCESS_KEY="$2" -export AZURE_STORAGE_ACCESS_KEY_2="$3" -export MOONCAKE_STORAGE_ACCESS_KEY="$4" -export AZURE_DOCUMENTDB_MASTERKEY="$5" -VSO_PAT="$6" - -echo "machine monacotools.visualstudio.com password $VSO_PAT" > ~/.netrc - -step "Install dependencies" \ - npm install - -step "Hygiene" \ - npm run gulp -- hygiene - -step "Mix in repository from vscode-distro" \ - npm run gulp -- mixin - -step "Install distro dependencies" \ - node build/tfs/common/installDistro.js - -step "Build minified & upload source maps" \ - npm run gulp -- vscode-darwin-min - -REPO=`pwd` -ZIP=$REPO/../VSCode-darwin.zip -BUILD=$REPO/../VSCode-darwin - -function createZip { - rm -rf $ZIP - cd $BUILD && zip -r -X -y $ZIP * -} - -step "Create unsigned archive" \ - createZip diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 4af53947033..272ba266916 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -39,5 +39,20 @@ step "Build minified" \ step "Run unit tests" \ ./scripts/test.sh --build --reporter dot +function smoketest { + SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" + rm -rf $SCREENSHOTS + mkdir -p $SCREENSHOTS + + id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) + sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' + chown -R testuser $SCREENSHOTS + + DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-x64 --screenshots $SCREENSHOTS" +} + +step "Run smoke test" \ + smoketest + step "Publish release" \ ./build/tfs/linux/release.sh diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1 index 0090920d506..73045dd4624 100644 --- a/build/tfs/win32/1_build.ps1 +++ b/build/tfs/win32/1_build.ps1 @@ -52,4 +52,11 @@ step "Run unit tests" { # exec { & .\scripts\test-integration.bat } # } +step "Run smoke test" { + $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" + Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots + + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" } +} + done From ef7702ae47a63371e054dec33c65efd0ce0f3389 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 3 Oct 2017 16:27:35 +0200 Subject: [PATCH 002/394] fix linux-ia32 smoketest launcher --- build/tfs/linux/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 272ba266916..29075d57b76 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -48,7 +48,7 @@ function smoketest { sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' chown -R testuser $SCREENSHOTS - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-x64 --screenshots $SCREENSHOTS" + DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS" } step "Run smoke test" \ From af15a2808c6f47a9b7b9fd6cd02bc5a8d5bafe33 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 3 Oct 2017 16:36:09 +0200 Subject: [PATCH 003/394] smoketest in unsigned windows builds --- build/tfs/win32/build_unsigned.ps1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/tfs/win32/build_unsigned.ps1 b/build/tfs/win32/build_unsigned.ps1 index dbb505b5683..28925bb3cd7 100644 --- a/build/tfs/win32/build_unsigned.ps1 +++ b/build/tfs/win32/build_unsigned.ps1 @@ -47,6 +47,13 @@ step "Run unit tests" { exec { & .\scripts\test.bat --build --reporter dot } } +step "Run smoke test" { + $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" + Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots + + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" } +} + step "Create archive and setup package" { exec { & npm run gulp -- "vscode-win32-$global:arch-archive" "vscode-win32-$global:arch-setup" } } From 8dbc74e36fbc7429ae7b6603e1fb62ca34e33e66 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Oct 2017 09:59:58 +0200 Subject: [PATCH 004/394] Configuration API blueprint --- .../configuration/common/configuration2.ts | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/vs/platform/configuration/common/configuration2.ts diff --git a/src/vs/platform/configuration/common/configuration2.ts b/src/vs/platform/configuration/common/configuration2.ts new file mode 100644 index 00000000000..a3edb5c0048 --- /dev/null +++ b/src/vs/platform/configuration/common/configuration2.ts @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TPromise } from 'vs/base/common/winjs.base'; +import URI from 'vs/base/common/uri'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import Event from 'vs/base/common/event'; + +export const IConfigurationService = createDecorator('configurationService'); + +export interface IConfigurationOverrides { + overrideIdentifier?: string; + resource?: URI; +} + +export enum ConfigurationTarget { + USER, + WORKSPACE, + WORKSPACE_FOLDER, + MEMORY +} + +export interface IConfigurationServiceEvent { + sections: string[]; + keys: string[]; +} + +export interface IConfiguration { + readonly [key: string]: any; +} + +export interface IConfigurationService { + _serviceBrand: any; + + onDidUpdateConfiguration: Event; + + getConfiguration(): T; + getConfiguration(section: string): T; + getConfiguration(overrides: IConfigurationOverrides): T; + getConfiguration(section: string, overrides: IConfigurationOverrides): T; + + updateConfiguration(key: string, value: any): TPromise; + updateConfiguration(key: string, value: any, overrides: IConfigurationOverrides): TPromise; + updateConfiguration(key: string, value: any, target: ConfigurationTarget): TPromise; + updateConfiguration(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise; + + inspect(key: string): { + default: T, + user: T, + workspace: T, + workspaceFolder: T + value: T, + }; + + keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + }; +} \ No newline at end of file From 7ec6ecda504c22197b1fec07dc85839f55e4a1c5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Oct 2017 10:09:58 +0200 Subject: [PATCH 005/394] Adopt to new configuration API --- .../configuration/common/configuration.ts | 55 +++++--------- .../common/configurationRegistry.ts | 14 ++-- .../node/configurationService.ts | 73 ++++++++++--------- .../configuration/common/configuration.ts | 2 +- 4 files changed, 61 insertions(+), 83 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index d541ed739df..16dc333a62f 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -240,7 +240,13 @@ export class Configuration { return section ? configModel.getContentsFor(section) : configModel.contents; } - lookup(key: string, overrides: IConfigurationOverrides = {}): IConfigurationValue { + lookup(key: string, overrides: IConfigurationOverrides = {}): { + default: C, + user: C, + workspace: C, + workspaceFolder: C + value: C, + } { // make sure to clone the configuration so that the receiver does not tamper with the values const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); @@ -248,53 +254,26 @@ export class Configuration { default: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key)), user: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key)), workspace: objects.clone(this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0), //Check on workspace exists or not because _workspaceConfiguration is never null - folder: objects.clone(folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0), + workspaceFolder: objects.clone(folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0), value: objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)) }; } - keys(overrides: IConfigurationOverrides = {}): IConfigurationKeys { - const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); + keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + } { + const folderConfigurationModel = this.getFolderConfigurationModelForResource(); return { default: this._defaults.keys, user: this._user.keys, workspace: this._workspaceConfiguration.keys, - folder: folderConfigurationModel ? folderConfigurationModel.keys : [] + workspaceFolder: folderConfigurationModel ? folderConfigurationModel.keys : [] }; } - values(): IConfigurationValues { - const result = Object.create(null); - const keyset = this.keys(); - const keys = [...keyset.workspace, ...keyset.user, ...keyset.default].sort(); - - let lastKey: string; - for (const key of keys) { - if (key !== lastKey) { - lastKey = key; - result[key] = this.lookup(key); - } - } - - return result; - } - - values2(): Map> { - const result: Map> = new Map>(); - const keyset = this.keys(); - const keys = [...keyset.workspace, ...keyset.user, ...keyset.default].sort(); - - let lastKey: string; - for (const key of keys) { - if (key !== lastKey) { - lastKey = key; - result.set(key, this.lookup(key)); - } - } - - return result; - } - private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides); return overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel; @@ -317,7 +296,7 @@ export class Configuration { return this._foldersConsolidatedConfigurations.get(root.uri) || this._workspaceConsolidatedConfiguration; } - private getFolderConfigurationModelForResource(resource: URI): ConfigurationModel { + private getFolderConfigurationModelForResource(resource?: URI): ConfigurationModel { if (!this._workspace || !resource) { return null; } diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 0d3276bf69d..f93837028b1 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -35,7 +35,7 @@ export interface IConfigurationRegistry { * Event that fires whenver a configuratio has been * registered. */ - onDidRegisterConfiguration: Event; + onDidRegisterConfiguration: Event; /** * Returns all configuration nodes contributed to this registry. @@ -90,27 +90,25 @@ export const editorConfigurationSchemaId = 'vscode://schemas/settings/editor'; const contributionRegistry = Registry.as(JSONExtensions.JSONContribution); class ConfigurationRegistry implements IConfigurationRegistry { + private configurationContributors: IConfigurationNode[]; private configurationProperties: { [qualifiedKey: string]: IJSONSchema }; private editorConfigurationSchema: IJSONSchema; - private _onDidRegisterConfiguration: Emitter; private overrideIdentifiers: string[] = []; private overridePropertyPattern: string; + private _onDidRegisterConfiguration: Emitter = new Emitter(); + readonly onDidRegisterConfiguration: Event = this._onDidRegisterConfiguration.event; + constructor() { this.configurationContributors = []; this.editorConfigurationSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting' }; - this._onDidRegisterConfiguration = new Emitter(); this.configurationProperties = {}; this.computeOverridePropertyPattern(); contributionRegistry.registerSchema(editorConfigurationSchemaId, this.editorConfigurationSchema); } - public get onDidRegisterConfiguration() { - return this._onDidRegisterConfiguration.event; - } - public registerConfiguration(configuration: IConfigurationNode, validate: boolean = true): void { this.registerConfigurations([configuration], validate); } @@ -123,7 +121,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { this.updateSchemaForOverrideSettingsConfiguration(configuration); }); - this._onDidRegisterConfiguration.fire(this); + this._onDidRegisterConfiguration.fire(configurations); } public registerOverrideIdentifiers(overrideIdentifiers: string[]): void { diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 8f6005c6430..843cd285b4d 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { TPromise } from 'vs/base/common/winjs.base'; import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { ConfigurationSource, IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, IConfigurationKeys, ConfigurationModel, IConfigurationOverrides, Configuration, IConfigurationValues, IConfigurationData } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationServiceEvent, IConfigurationOverrides, IConfiguration } from 'vs/platform/configuration/common/configuration2'; +import { ConfigurationModel, Configuration } from 'vs/platform/configuration/common/configuration'; import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; import Event, { Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -40,52 +40,53 @@ export class ConfigurationService extends Disposable implements IConfiguratio this._register(this.userConfigModelWatcher); // Listeners - this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onConfigurationChange(ConfigurationSource.User))); - this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(() => this.onConfigurationChange(ConfigurationSource.Default))); + this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onDidUpdateConfigModel())); + this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(configurationNodes => this.onDidRegisterConfiguration(configurationNodes))); } - public configuration(): Configuration { + public get configuration(): Configuration { return this._configuration || (this._configuration = this.consolidateConfigurations()); } - private onConfigurationChange(source: ConfigurationSource): void { + private onDidUpdateConfigModel(): void { + // get the diff + // reset and trigger + this.onConfigurationChange([], []); + } + + private onDidRegisterConfiguration(configurations: IConfigurationNode[]): void { + // get the diff + // reset and trigger + this.onConfigurationChange([], []); + } + + private onConfigurationChange(sections: string[], keys: string[]): void { this.reset(); // reset our caches - const cache = this.configuration(); - - this._onDidUpdateConfiguration.fire({ - source, - sourceConfig: source === ConfigurationSource.Default ? cache.defaults.contents : cache.user.contents - }); + this._onDidUpdateConfiguration.fire({ sections, keys }); } - public reloadConfiguration(section?: string): TPromise { - return new TPromise(c => { - this.userConfigModelWatcher.reload(() => { - this.reset(); // reset our caches - c(this.getConfiguration(section)); - }); - }); + public getConfiguration(section?: string, options?: IConfigurationOverrides): IConfiguration { + return this.configuration.getValue(section, options); } - public getConfiguration(section?: string, options?: IConfigurationOverrides): C { - return this.configuration().getValue(section, options); + public inspect(key: string): { + default: T, + user: T, + workspace: T, + workspaceFolder: T + value: T + } { + return this.configuration.lookup(key); } - public lookup(key: string, overrides?: IConfigurationOverrides): IConfigurationValue { - return this.configuration().lookup(key, overrides); - } - - public keys(overrides?: IConfigurationOverrides): IConfigurationKeys { - return this.configuration().keys(overrides); - } - - public values(): IConfigurationValues { - return this._configuration.values(); - } - - public getConfigurationData(): IConfigurationData { - return this.configuration().toData(); + public keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + } { + return this.configuration.keys(); } private reset(): void { diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index 28c1b711fed..9dffb9cba33 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration2'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const CONFIG_DEFAULT_NAME = 'settings'; From 08e6c5d09efb2c294dca2adc40e880cdc2d8ca74 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 Oct 2017 21:20:41 +0200 Subject: [PATCH 006/394] disable updates in smoketests --- src/vs/platform/environment/common/environment.ts | 2 ++ src/vs/platform/environment/node/argv.ts | 3 ++- src/vs/platform/environment/node/environmentService.ts | 2 ++ src/vs/platform/update/electron-main/updateService.ts | 8 +++++++- test/smoke/src/spectron/application.ts | 5 ++++- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index dad4ea1cc5f..2dd0c004b87 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -44,6 +44,7 @@ export interface ParsedArgs { 'disable-telemetry'?: boolean; 'export-default-configuration'?: string; 'install-source'?: string; + 'disable-updates'?: string; } export const IEnvironmentService = createDecorator('environmentService'); @@ -106,4 +107,5 @@ export interface IEnvironmentService { nodeCachedDataDir: string; installSource: string; + disableUpdates: boolean; } diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 2396982a61f..b82511d8c71 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -50,7 +50,8 @@ const options: minimist.Opts = { 'nolazy', 'skip-getting-started', 'sticky-quickopen', - 'disable-telemetry' + 'disable-telemetry', + 'disable-updates' ], alias: { add: 'a', diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 0270370c755..f5637497e53 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -125,6 +125,8 @@ export class EnvironmentService implements IEnvironmentService { @memoize get nodeCachedDataDir(): string { return this.isBuilt ? path.join(this.userDataPath, 'CachedData', product.commit || new Array(41).join('0')) : undefined; } + get disableUpdates(): boolean { return !!this._args['disable-updates']; } + readonly machineUUID: string; readonly installSource: string; diff --git a/src/vs/platform/update/electron-main/updateService.ts b/src/vs/platform/update/electron-main/updateService.ts index 70571cda7ab..2dbdbbf6d1c 100644 --- a/src/vs/platform/update/electron-main/updateService.ts +++ b/src/vs/platform/update/electron-main/updateService.ts @@ -22,6 +22,7 @@ import product from 'vs/platform/node/product'; import { TPromise } from 'vs/base/common/winjs.base'; import { IUpdateService, State, IAutoUpdater, IUpdate, IRawUpdate } from 'vs/platform/update/common/update'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; export class UpdateService implements IUpdateService { @@ -87,7 +88,8 @@ export class UpdateService implements IUpdateService { @IRequestService requestService: IRequestService, @ILifecycleService private lifecycleService: ILifecycleService, @IConfigurationService private configurationService: IConfigurationService, - @ITelemetryService private telemetryService: ITelemetryService + @ITelemetryService private telemetryService: ITelemetryService, + @IEnvironmentService private environmentService: IEnvironmentService ) { if (process.platform === 'win32') { this.raw = new Win32AutoUpdaterImpl(requestService); @@ -99,6 +101,10 @@ export class UpdateService implements IUpdateService { return; } + if (this.environmentService.disableUpdates) { + return; + } + const channel = this.getUpdateChannel(); const feedUrl = this.getUpdateFeedUrl(channel); diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 77ef6fd4207..72ebd5a1e7c 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -127,9 +127,12 @@ export class SpectronApplication { // Prevent Quick Open from closing when focus is stolen, this allows concurrent smoketest suite running args.push('--sticky-quickopen'); - // Disable telemetry for smoke tests + // Disable telemetry args.push('--disable-telemetry'); + // Disable updates + args.push('--disable-updates'); + // Ensure that running over custom extensions directory, rather than picking up the one that was used by a tester previously args.push(`--extensions-dir=${EXTENSIONS_DIR}`); From d78d5da119e8aacf5ef252c2314d34502d800257 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 Oct 2017 22:27:28 +0200 Subject: [PATCH 007/394] smoke: kill all testuser processes before smoketest --- build/tfs/linux/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 29075d57b76..c7e8b2a4692 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -48,6 +48,7 @@ function smoketest { sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' chown -R testuser $SCREENSHOTS + ps -o pid= -u testuser | xargs sudo kill -9 DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS" } From 827d103d4d45d3606b1f40fd4586bb68d77c7717 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 09:22:46 +0200 Subject: [PATCH 008/394] smoke: prevent 64bit ad --- src/vs/workbench/parts/update/electron-browser/update.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/update/electron-browser/update.ts b/src/vs/workbench/parts/update/electron-browser/update.ts index 9795b43c6ed..33e1a4f19a8 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.ts @@ -32,6 +32,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { IUpdateService, State as UpdateState } from 'vs/platform/update/common/update'; import * as semver from 'semver'; import { OS, isLinux, isWindows } from 'vs/base/common/platform'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; class ApplyUpdateAction extends Action { constructor( @IUpdateService private updateService: IUpdateService) { @@ -267,8 +268,13 @@ export class Win3264BitContribution implements IWorkbenchContribution { @IStorageService storageService: IStorageService, @IInstantiationService instantiationService: IInstantiationService, @IMessageService messageService: IMessageService, - @IWorkbenchEditorService editorService: IWorkbenchEditorService + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IEnvironmentService environmentService: IEnvironmentService ) { + if (environmentService.disableUpdates) { + return; + } + const neverShowAgain = new NeverShowAgain(Win3264BitContribution.KEY, storageService); if (!neverShowAgain.shouldShow()) { From d0974f2bd4baf5b62c9fec2a0f9fc90a8ce1a61c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 10:58:19 +0200 Subject: [PATCH 009/394] smoke: get more screenshots --- test/smoke/src/areas/preferences/preferences.test.ts | 4 ++-- test/smoke/src/areas/preferences/settings.ts | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index 795c3aba1d2..5239518928d 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -17,13 +17,13 @@ describe('Preferences', () => { it('turns off editor line numbers and verifies the live change', async function () { await app.workbench.explorer.openFile('app.js'); let lineNumbers = await app.client.waitForElements('.line-numbers'); - await app.screenCapturer.capture('line numbers'); + await app.screenCapturer.capture('app.js has line numbers'); assert.ok(!!lineNumbers.length, 'Line numbers are not present in the editor before disabling them.'); await app.workbench.settingsEditor.addUserSetting('editor.lineNumbers', '"off"'); - await app.workbench.selectTab('app.js'); lineNumbers = await app.client.waitForElements('.line-numbers', result => !result || result.length === 0); + await app.screenCapturer.capture('line numbers hidden'); assert.ok(!lineNumbers.length, 'Line numbers are still present in the editor after disabling them.'); }); diff --git a/test/smoke/src/areas/preferences/settings.ts b/test/smoke/src/areas/preferences/settings.ts index b771b3702cc..24fd9d63e12 100644 --- a/test/smoke/src/areas/preferences/settings.ts +++ b/test/smoke/src/areas/preferences/settings.ts @@ -29,9 +29,11 @@ export class SettingsEditor { async addUserSetting(setting: string, value: string): Promise { await this.openUserSettings(); - await this.focusEditableSettings(); + await this.spectron.screenCapturer.capture('user settings is open and focused'); + await this.spectron.client.keys(`"${setting}": ${value},`); await this.spectron.workbench.saveOpenedFile(); + await this.spectron.screenCapturer.capture('user settings has changed'); } } \ No newline at end of file From d85a7b126df943527b052dd07d9a5a0b6eb30cd7 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 12:54:07 +0200 Subject: [PATCH 010/394] smoke: comment --- build/tfs/linux/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index c7e8b2a4692..9872b14640a 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -50,6 +50,7 @@ function smoketest { ps -o pid= -u testuser | xargs sudo kill -9 DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS" + # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32" } step "Run smoke test" \ From d73a3e355f6ff832e8ce678ed9b14cb7d035f714 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 14:53:51 +0200 Subject: [PATCH 011/394] smoke: collect chromedriver and webdriver logs --- build/tfs/darwin/build.sh | 5 +++-- build/tfs/darwin/smoketest.sh | 5 +++-- build/tfs/linux/build.sh | 6 +++++- build/tfs/linux/smoketest.sh | 7 ++++++- build/tfs/win32/1_build.ps1 | 5 ++++- build/tfs/win32/build_unsigned.ps1 | 5 ++++- build/tfs/win32/smoketest.ps1 | 5 ++++- test/smoke/src/main.ts | 12 +++++++++++- test/smoke/src/spectron/application.ts | 16 ++++++++++++---- 9 files changed, 52 insertions(+), 14 deletions(-) diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index 663207eae9e..080deb976c5 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -39,9 +39,10 @@ step "Run integration tests" \ function smoketest { SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" - rm -rf $SCREENSHOTS + LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" + rm -rf $SCREENSHOTS $LOGS - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS + npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS --logs $LOGS } step "Run smoke test" \ diff --git a/build/tfs/darwin/smoketest.sh b/build/tfs/darwin/smoketest.sh index cb89a32b783..0d4510edcb3 100755 --- a/build/tfs/darwin/smoketest.sh +++ b/build/tfs/darwin/smoketest.sh @@ -23,9 +23,10 @@ step "Build minified & upload source maps" \ function runSmokeTest { SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" - rm -rf $SCREENSHOTS + LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" + rm -rf $SCREENSHOTS $LOGS - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS + npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS --logs $LOGS } step "Run smoke test" \ diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 9872b14640a..b0c471bf796 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -44,12 +44,16 @@ function smoketest { rm -rf $SCREENSHOTS mkdir -p $SCREENSHOTS + LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" + rm -rf $LOGS + mkdir -p $LOGS + id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' chown -R testuser $SCREENSHOTS ps -o pid= -u testuser | xargs sudo kill -9 - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS" + DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS --logs $LOGS" # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32" } diff --git a/build/tfs/linux/smoketest.sh b/build/tfs/linux/smoketest.sh index 08cbdff405a..558d6082d64 100644 --- a/build/tfs/linux/smoketest.sh +++ b/build/tfs/linux/smoketest.sh @@ -12,6 +12,7 @@ VSO_PAT="$2" echo "machine monacotools.visualstudio.com password $VSO_PAT" > ~/.netrc export SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" +export LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" function configureEnvironment { id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) @@ -20,10 +21,14 @@ function configureEnvironment { sudo rm -rf $SCREENSHOTS mkdir -p $SCREENSHOTS chown -R testuser $SCREENSHOTS + + sudo rm -rf $LOGS + mkdir -p $LOGS + chown -R testuser $LOGS } function runSmokeTest { - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-x64 --screenshots $SCREENSHOTS" + DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-x64 --screenshots $SCREENSHOTS --logs $LOGS" } step "Install dependencies" \ diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1 index 73045dd4624..9c913f7446a 100644 --- a/build/tfs/win32/1_build.ps1 +++ b/build/tfs/win32/1_build.ps1 @@ -56,7 +56,10 @@ step "Run smoke test" { $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" } + $Logs = "$env:AGENT_BUILDDIRECTORY\smoketest-logs" + Remove-Item -Recurse -Force -ErrorAction Ignore $Logs + + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" --logs "$Logs" } } done diff --git a/build/tfs/win32/build_unsigned.ps1 b/build/tfs/win32/build_unsigned.ps1 index 28925bb3cd7..68c0acd3183 100644 --- a/build/tfs/win32/build_unsigned.ps1 +++ b/build/tfs/win32/build_unsigned.ps1 @@ -51,7 +51,10 @@ step "Run smoke test" { $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" } + $Logs = "$env:AGENT_BUILDDIRECTORY\smoketest-logs" + Remove-Item -Recurse -Force -ErrorAction Ignore $Logs + + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" --logs "$Logs" } } step "Create archive and setup package" { diff --git a/build/tfs/win32/smoketest.ps1 b/build/tfs/win32/smoketest.ps1 index 6a2b457bf98..1fb60a05fd9 100644 --- a/build/tfs/win32/smoketest.ps1 +++ b/build/tfs/win32/smoketest.ps1 @@ -41,7 +41,10 @@ step "Run smoke test" { $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" } + $Logs = "$env:AGENT_BUILDDIRECTORY\smoketest-logs" + Remove-Item -Recurse -Force -ErrorAction Ignore $Logs + + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" --logs "$Logs" } } done \ No newline at end of file diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index 31dbaf71149..b3c81458aee 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -17,9 +17,18 @@ const testDataPath = tmpDir.name; process.once('exit', () => rimraf.sync(testDataPath)); const [, , ...args] = process.argv; -const opts = minimist(args, { string: ['build', 'stable-build', 'screenshots', 'wait-time'] }); +const opts = minimist(args, { + string: [ + 'build', + 'stable-build', + 'screenshots', + 'logs', + 'wait-time' + ] +}); opts.screenshots = opts.screenshots === '' ? path.join(testDataPath, 'screenshots') : opts.screenshots; +opts.logs = opts.logs === '' ? path.join(testDataPath, 'logs') : opts.logs; const workspacePath = path.join(testDataPath, 'smoketest.code-workspace'); const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express'; @@ -99,6 +108,7 @@ process.env.SMOKETEST_REPO = testRepoLocalDir; process.env.VSCODE_WORKSPACE_PATH = workspacePath; process.env.VSCODE_KEYBINDINGS_PATH = keybindingsPath; process.env.SCREENSHOTS_DIR = opts.screenshots || ''; +process.env.LOGS_DIR = opts.logs || ''; process.env.WAIT_TIME = opts['wait-time'] || '20'; if (process.env.VSCODE_DEV === '1') { diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 72ebd5a1e7c..5cc927c82f0 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -20,6 +20,7 @@ export const USER_DIR = process.env.VSCODE_USER_DIR as string; export const EXTENSIONS_DIR = process.env.VSCODE_EXTENSIONS_DIR as string; export const VSCODE_EDITION = process.env.VSCODE_EDITION as string; export const SCREENSHOTS_DIR = process.env.SCREENSHOTS_DIR as string; +export const LOGS_DIR = process.env.LOGS_DIR as string; export const WAIT_TIME = parseInt(process.env.WAIT_TIME as string); export enum VSCODE_BUILD { @@ -138,15 +139,15 @@ export class SpectronApplication { args.push(...codeArgs); - chromeDriverArgs.push(`--user-data-dir=${path.join(this._userDir, String(SpectronApplication.count++))}`); + const id = String(SpectronApplication.count++); + chromeDriverArgs.push(`--user-data-dir=${path.join(this._userDir, id)}`); // Spectron always uses the same port number for the chrome driver // and it handles gracefully when two instances use the same port number // This works, but when one of the instances quits, it takes down // chrome driver with it, leaving the other instance in DISPAIR!!! :( const port = await findFreePort(); - - this.spectron = new Application({ + const opts: any = { path: this._electronPath, port, args, @@ -154,7 +155,14 @@ export class SpectronApplication { chromeDriverArgs, startTimeout: 10000, requireName: 'nodeRequire' - }); + }; + + if (LOGS_DIR) { + opts.chromeDriverLogPath = path.join(LOGS_DIR, id, 'chromedriver'); + opts.webdriverLogPath = path.join(LOGS_DIR, id, 'webdriver'); + } + + this.spectron = new Application(opts); await this.spectron.start(); this._screenCapturer = new ScreenCapturer(this.spectron, testSuiteName); From cee94c30ceeeb721f617ee7de85280e8a644888f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 15:28:15 +0200 Subject: [PATCH 012/394] smoke: fix darwin launcher --- build/tfs/darwin/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index 080deb976c5..2d84a8be12a 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -41,6 +41,7 @@ function smoketest { SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" rm -rf $SCREENSHOTS $LOGS + mkdir -p $SCREENSHOTS $LOGS npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS --logs $LOGS } From 64c07f19b4bce418efd3998df856d1f114ea2bff Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 15:32:37 +0200 Subject: [PATCH 013/394] smoke: mkdir logs --- test/smoke/package.json | 1 + test/smoke/src/spectron/application.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/test/smoke/package.json b/test/smoke/package.json index c6458a2173a..95d42199ece 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -17,6 +17,7 @@ "@types/rimraf": "^2.0.2", "@types/webdriverio": "^4.6.1", "htmlparser2": "^3.9.2", + "mkdirp": "^0.5.1", "mocha": "^3.2.0", "ncp": "^2.0.0", "portastic": "^1.0.1", diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 5cc927c82f0..544852d0049 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -11,6 +11,7 @@ import { Workbench } from '../areas/workbench/workbench'; import * as fs from 'fs'; import * as cp from 'child_process'; import * as path from 'path'; +import * as mkdirp from 'mkdirp'; export const LATEST_PATH = process.env.VSCODE_PATH as string; export const STABLE_PATH = process.env.VSCODE_STABLE_PATH || ''; @@ -159,7 +160,10 @@ export class SpectronApplication { if (LOGS_DIR) { opts.chromeDriverLogPath = path.join(LOGS_DIR, id, 'chromedriver'); + mkdirp.sync(opts.chromeDriverLogPath); + opts.webdriverLogPath = path.join(LOGS_DIR, id, 'webdriver'); + mkdirp.sync(opts.webdriverLogPath); } this.spectron = new Application(opts); From 0a7e61642bab32750852fa0d8a511a3876a39b07 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 16:47:42 +0200 Subject: [PATCH 014/394] smoketest: logs permissions --- build/tfs/linux/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index b0c471bf796..8118c2a2d2f 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -51,6 +51,7 @@ function smoketest { id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' chown -R testuser $SCREENSHOTS + chown -R testuser $LOGS ps -o pid= -u testuser | xargs sudo kill -9 DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS --logs $LOGS" From 0e8aca28236793af0b9a69fbc28b851b40a264ff Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 5 Oct 2017 16:51:10 +0200 Subject: [PATCH 015/394] smoketest: fix logs --- test/smoke/src/spectron/application.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 544852d0049..e382b92156a 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -159,10 +159,11 @@ export class SpectronApplication { }; if (LOGS_DIR) { - opts.chromeDriverLogPath = path.join(LOGS_DIR, id, 'chromedriver'); - mkdirp.sync(opts.chromeDriverLogPath); + const dir = path.join(LOGS_DIR, id); + opts.chromeDriverLogPath = path.join(dir, 'chromedriver.log'); + mkdirp.sync(dir); - opts.webdriverLogPath = path.join(LOGS_DIR, id, 'webdriver'); + opts.webdriverLogPath = path.join(dir, 'webdriver'); mkdirp.sync(opts.webdriverLogPath); } From 75cf7dabb50ace4604806404c7f134e546406828 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 5 Oct 2017 23:13:18 +0200 Subject: [PATCH 016/394] Refactor Configuration Service - API to get a value given a key - API to update value smartly - Fine grained configuration change event - Smart reload API - Remove unnecessary APIs --- .../browser/referencesController.ts | 2 +- .../standalone/browser/simpleServices.ts | 49 +- .../configuration/common/configuration.ts | 148 ++-- .../configuration/common/configuration2.ts | 63 -- .../common/configurationRegistry.ts | 22 +- .../node/configurationService.ts | 106 ++- .../test/common/testConfigurationService.ts | 38 +- .../test/node/configurationService.test.ts | 13 +- .../telemetry/common/telemetryUtils.ts | 8 +- .../electron-browser/telemetryService.test.ts | 18 +- .../mainThreadConfiguration.ts | 2 +- .../mainThreadSaveParticipant.ts | 8 +- .../api/node/extHostConfiguration.ts | 2 +- .../browser/parts/editor/editorStatus.ts | 2 +- .../browser/parts/titlebar/titlebarPart.ts | 2 +- src/vs/workbench/electron-browser/actions.ts | 4 +- src/vs/workbench/electron-browser/main.ts | 2 +- src/vs/workbench/electron-browser/window.ts | 2 +- .../workbench/electron-browser/workbench.ts | 30 +- .../electron-browser/wordWrapMigration.ts | 2 +- .../parts/debug/browser/debugActionItems.ts | 2 +- .../debug/electron-browser/debugService.ts | 2 +- .../browser/preferencesRenderers.ts | 6 +- .../preferences/browser/preferencesService.ts | 2 + .../preferences/common/preferencesModels.ts | 4 +- .../electron-browser/terminalConfigHelper.ts | 4 +- .../terminalConfigHelper.test.ts | 11 +- .../electron-browser/themes.contribution.ts | 4 +- .../watermark/electron-browser/watermark.ts | 4 +- .../page/electron-browser/welcomePage.ts | 4 +- .../electron-browser/walkThroughPart.ts | 6 +- .../configuration/common/configuration.ts | 9 +- .../common/configurationExtensionPoint.ts | 212 ++++++ .../common/configurationModels.ts | 91 ++- .../node/configurationEditingService.ts | 6 +- ...nfiguration.ts => configurationService.ts} | 717 +++++++----------- .../node/configurationEditingService.test.ts | 14 +- ...n.test.ts => configurationService.test.ts} | 62 +- .../node/configurationResolverService.test.ts | 11 +- .../electron-browser/extensionHost.ts | 2 +- .../electron-browser/workbenchThemeService.ts | 16 +- .../workspace/node/workspaceEditingService.ts | 4 +- src/vs/workbench/workbench.main.ts | 3 + 43 files changed, 969 insertions(+), 750 deletions(-) delete mode 100644 src/vs/platform/configuration/common/configuration2.ts create mode 100644 src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts rename src/vs/workbench/services/configuration/node/{configuration.ts => configurationService.ts} (56%) rename src/vs/workbench/services/configuration/test/node/{configuration.test.ts => configurationService.test.ts} (90%) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts index d268a392aff..7678766238c 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts @@ -123,7 +123,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { switch (kind) { case 'open': if (event.source === 'editor' - && this._configurationService.lookup('editor.stablePeek').value) { + && this._configurationService.getValue('editor.stablePeek')) { // when stable peek is configured we don't close // the peek window on selecting the editor diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 41ddb0f59ee..75aaa4492f9 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -8,7 +8,7 @@ import { Schemas } from 'vs/base/common/network'; import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, IConfigurationKeys, IConfigurationValues, Configuration, IConfigurationData, ConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent, Configuration, ConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IEditor, IEditorInput, IEditorOptions, IEditorService, IResourceInput, Position } from 'vs/platform/editor/common/editor'; import { ICommandService, ICommand, ICommandEvent, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -428,12 +428,19 @@ export class StandaloneKeybindingService extends AbstractKeybindingService { } } +function isConfigurationOverrides(thing: any): thing is IConfigurationOverrides { + return thing + && typeof thing === 'object' + && (!thing.overrideIdentifier || typeof thing.overrideIdentifier === 'string') + && (!thing.resource || thing.resource instanceof URI); +} + export class SimpleConfigurationService implements IConfigurationService { _serviceBrand: any; - private _onDidUpdateConfiguration = new Emitter(); - public onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _onDidUpdateConfiguration = new Emitter(); + public onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; private _configuration: Configuration; @@ -445,28 +452,40 @@ export class SimpleConfigurationService implements IConfigurationService { return this._configuration; } - public reloadConfiguration(section?: string): TPromise { - return TPromise.as(this.getConfiguration(section)); + getConfiguration(): T + getConfiguration(section: string): T + getConfiguration(overrides: IConfigurationOverrides): T + getConfiguration(section: string, overrides: IConfigurationOverrides): T + getConfiguration(arg1?: any, arg2?: any): any { + const section = typeof arg1 === 'string' ? arg1 : void 0; + const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; + return this.configuration().getValue(section, overrides); } - public getConfiguration(section?: string, options?: IConfigurationOverrides): C { - return this.configuration().getValue(section, options); + public getValue(key: string, options?: IConfigurationOverrides): C { + return this.configuration().getValue2(key, options); } - public lookup(key: string, options?: IConfigurationOverrides): IConfigurationValue { + public updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { + return TPromise.as(null); + } + + public inspect(key: string, options?: IConfigurationOverrides): { + default: C, + user: C, + workspace: C, + workspaceFolder: C + value: C, + } { return this.configuration().lookup(key, options); } - public keys(): IConfigurationKeys { + public keys() { return this.configuration().keys(); } - public values(): IConfigurationValues { - return this._configuration.values(); - } - - public getConfigurationData(): IConfigurationData { - return this.configuration().toData(); + public reloadConfiguration(): TPromise { + return TPromise.as(null); } } diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 16dc333a62f..20f1b668201 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -9,9 +9,10 @@ import * as types from 'vs/base/common/types'; import * as objects from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import { StrictResourceMap } from 'vs/base/common/map'; -import { Workspace } from 'vs/platform/workspace/common/workspace'; +import { Workspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import Event from 'vs/base/common/event'; +import { OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; export const IConfigurationService = createDecorator('configurationService'); @@ -20,80 +21,79 @@ export interface IConfigurationOverrides { resource?: URI; } -export type IConfigurationValues = { [key: string]: IConfigurationValue }; +export enum ConfigurationTarget { + DEFAULT = 1, + USER, + WORKSPACE, + WORKSPACE_FOLDER, + MEMORY +} + +export interface IConfigurationChangeEvent { + keys: string[]; + sections: string[]; + overrideIdentifiers?: string[]; + + hasSectionChanged(section: string): boolean; + hasKeyChanged(key: string): boolean; + + // Following data is used for telemetry + source: ConfigurationTarget; + sourceConfig: any; +} export interface IConfigurationService { _serviceBrand: any; - getConfigurationData(): IConfigurationData; + onDidUpdateConfiguration: Event; - /** - * Fetches the appropriate section of the configuration JSON file. - * This will be an object keyed off the section name. - */ - getConfiguration(section?: string, overrides?: IConfigurationOverrides): T; + getConfiguration(): T; + getConfiguration(section: string): T; + getConfiguration(overrides: IConfigurationOverrides): T; + getConfiguration(section: string, overrides: IConfigurationOverrides): T; - /** - * Resolves a configuration key to its values in the different scopes - * the setting is defined. - */ - lookup(key: string, overrides?: IConfigurationOverrides): IConfigurationValue; + getValue(key: string, overrides?: IConfigurationOverrides): T; - /** - * Returns the defined keys of configurations in the different scopes - * the key is defined. - */ - keys(overrides?: IConfigurationOverrides): IConfigurationKeys; + updateValue(key: string, value: any): TPromise; + updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise; + updateValue(key: string, value: any, target: ConfigurationTarget): TPromise; + updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise; - /** - * Similar to #getConfiguration() but ensures that the latest configuration - * from disk is fetched. - */ - reloadConfiguration(section?: string): TPromise; + reloadConfiguration(): TPromise; + reloadConfiguration(folder?: IWorkspaceFolder): TPromise; - /** - * Event that fires when the configuration changes. - */ - onDidUpdateConfiguration: Event; + inspect(key: string): { + default: T, + user: T, + workspace: T, + workspaceFolder: T + value: T, + }; - /** - * Returns the defined values of configurations in the different scopes. - */ - values(): IConfigurationValues; + keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + }; } -export enum ConfigurationSource { - Default = 1, - User, - Workspace -} +export function toConfigurationUpdateEvent(udpated: string[], source: ConfigurationTarget, sourceConfig: any): IConfigurationChangeEvent { + const overrideIdentifiers = []; + const keys: string[] = []; + for (const key of udpated) { + if (OVERRIDE_PROPERTY_PATTERN.test(key)) { + overrideIdentifiers.push(key); + } else { + keys.push(key); + } + } + const sections = arrays.distinct(keys.map(key => key.split('.')[0])); + const hasSectionChanged = (section) => sections.indexOf(section) !== -1; + const hasKeyChanged = (key) => keys.indexOf(key) !== -1; -export interface IConfigurationServiceEvent { - /** - * The type of source that triggered this event. - */ - source: ConfigurationSource; - /** - * The part of the configuration contributed by the source of this event. - */ - sourceConfig: any; + return { keys, sections, overrideIdentifiers, source, sourceConfig, hasSectionChanged, hasKeyChanged }; } - -export interface IConfigurationValue { - value: T; - default: T; - user: T; - workspace: T; - folder: T; -} - -export interface IConfigurationKeys { - default: string[]; - user: string[]; - workspace: string[]; - folder: string[]; -} - /** * A helper function to get the configuration value with a specific settings path (e.g. config.some.setting) */ @@ -197,6 +197,22 @@ export class ConfigurationModel implements IConfiguraionModel { } } +export function compare(from: ConfigurationModel, to: ConfigurationModel): { added: string[], removed: string[], updated: string[] } { + const added = to.keys.filter(key => from.keys.indexOf(key) === -1); + const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); + const updated = []; + + for (const key of from.keys) { + const value1 = getConfigurationValue(from.contents, key); + const value2 = getConfigurationValue(to.contents, key); + if (!objects.equals(value1, value2)) { + updated.push(key); + } + } + + return { added, removed, updated }; +} + export interface IConfigurationData { defaults: IConfiguraionModel; user: IConfiguraionModel; @@ -222,6 +238,10 @@ export class Configuration { return this._user; } + get workspace(): ConfigurationModel { + return this._workspaceConfiguration; + } + protected merge(): void { this._globalConfiguration = new ConfigurationModel().merge(this._defaults).merge(this._user); this._workspaceConsolidatedConfiguration = new ConfigurationModel().merge(this._globalConfiguration).merge(this._workspaceConfiguration); @@ -240,6 +260,12 @@ export class Configuration { return section ? configModel.getContentsFor(section) : configModel.contents; } + getValue2(key: string, overrides: IConfigurationOverrides = {}): any { + // make sure to clone the configuration so that the receiver does not tamper with the values + const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); + return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); + } + lookup(key: string, overrides: IConfigurationOverrides = {}): { default: C, user: C, diff --git a/src/vs/platform/configuration/common/configuration2.ts b/src/vs/platform/configuration/common/configuration2.ts deleted file mode 100644 index a3edb5c0048..00000000000 --- a/src/vs/platform/configuration/common/configuration2.ts +++ /dev/null @@ -1,63 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TPromise } from 'vs/base/common/winjs.base'; -import URI from 'vs/base/common/uri'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; - -export const IConfigurationService = createDecorator('configurationService'); - -export interface IConfigurationOverrides { - overrideIdentifier?: string; - resource?: URI; -} - -export enum ConfigurationTarget { - USER, - WORKSPACE, - WORKSPACE_FOLDER, - MEMORY -} - -export interface IConfigurationServiceEvent { - sections: string[]; - keys: string[]; -} - -export interface IConfiguration { - readonly [key: string]: any; -} - -export interface IConfigurationService { - _serviceBrand: any; - - onDidUpdateConfiguration: Event; - - getConfiguration(): T; - getConfiguration(section: string): T; - getConfiguration(overrides: IConfigurationOverrides): T; - getConfiguration(section: string, overrides: IConfigurationOverrides): T; - - updateConfiguration(key: string, value: any): TPromise; - updateConfiguration(key: string, value: any, overrides: IConfigurationOverrides): TPromise; - updateConfiguration(key: string, value: any, target: ConfigurationTarget): TPromise; - updateConfiguration(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise; - - inspect(key: string): { - default: T, - user: T, - workspace: T, - workspaceFolder: T - value: T, - }; - - keys(): { - default: string[]; - user: string[]; - workspace: string[]; - workspaceFolder: string[]; - }; -} \ No newline at end of file diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index f93837028b1..83d78eda6da 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -32,10 +32,10 @@ export interface IConfigurationRegistry { registerDefaultConfigurations(defaultConfigurations: IDefaultConfigurationExtension[]): void; /** - * Event that fires whenver a configuratio has been + * Event that fires whenver a configuration has been * registered. */ - onDidRegisterConfiguration: Event; + onDidRegisterConfiguration: Event; /** * Returns all configuration nodes contributed to this registry. @@ -97,8 +97,8 @@ class ConfigurationRegistry implements IConfigurationRegistry { private overrideIdentifiers: string[] = []; private overridePropertyPattern: string; - private _onDidRegisterConfiguration: Emitter = new Emitter(); - readonly onDidRegisterConfiguration: Event = this._onDidRegisterConfiguration.event; + private _onDidRegisterConfiguration: Emitter = new Emitter(); + readonly onDidRegisterConfiguration: Event = this._onDidRegisterConfiguration.event; constructor() { this.configurationContributors = []; @@ -114,14 +114,15 @@ class ConfigurationRegistry implements IConfigurationRegistry { } public registerConfigurations(configurations: IConfigurationNode[], validate: boolean = true): void { + const properties = []; configurations.forEach(configuration => { - this.validateAndRegisterProperties(configuration, validate); // fills in defaults + properties.push(this.validateAndRegisterProperties(configuration, validate)); // fills in defaults this.configurationContributors.push(configuration); this.registerJSONConfiguration(configuration); this.updateSchemaForOverrideSettingsConfiguration(configuration); }); - this._onDidRegisterConfiguration.fire(configurations); + this._onDidRegisterConfiguration.fire(properties); } public registerOverrideIdentifiers(overrideIdentifiers: string[]): void { @@ -153,9 +154,10 @@ class ConfigurationRegistry implements IConfigurationRegistry { } } - private validateAndRegisterProperties(configuration: IConfigurationNode, validate: boolean = true, scope: ConfigurationScope = ConfigurationScope.WINDOW, overridable: boolean = false) { + private validateAndRegisterProperties(configuration: IConfigurationNode, validate: boolean = true, scope: ConfigurationScope = ConfigurationScope.WINDOW, overridable: boolean = false): string[] { scope = configuration.scope !== void 0 && configuration.scope !== null ? configuration.scope : scope; overridable = configuration.overridable || overridable; + let propertyKeys = []; let properties = configuration.properties; if (properties) { for (let key in properties) { @@ -180,14 +182,16 @@ class ConfigurationRegistry implements IConfigurationRegistry { } // add to properties map this.configurationProperties[key] = properties[key]; + propertyKeys.push(key); } } let subNodes = configuration.allOf; if (subNodes) { for (let node of subNodes) { - this.validateAndRegisterProperties(node, validate, scope, overridable); + propertyKeys.push(...this.validateAndRegisterProperties(node, validate, scope, overridable)); } } + return propertyKeys; } validateProperty(property: string): boolean { @@ -302,4 +306,4 @@ export function validateProperty(property: string): string { return nls.localize('config.property.duplicate', "Cannot register '{0}'. This property is already registered.", property); } return null; -} +} \ No newline at end of file diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 843cd285b4d..0d97199766b 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -6,14 +6,24 @@ import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { IConfigurationService, IConfigurationServiceEvent, IConfigurationOverrides, IConfiguration } from 'vs/platform/configuration/common/configuration2'; -import { ConfigurationModel, Configuration } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, toConfigurationUpdateEvent, ConfigurationModel, Configuration, compare } from 'vs/platform/configuration/common/configuration'; import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; import Event, { Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { onUnexpectedError } from 'vs/base/common/errors'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { equals } from 'vs/base/common/objects'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; + +export function isConfigurationOverrides(thing: any): thing is IConfigurationOverrides { + return thing + && typeof thing === 'object' + && (!thing.overrideIdentifier || typeof thing.overrideIdentifier === 'string') + && (!thing.resource || thing.resource instanceof URI); +} export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable { @@ -22,8 +32,8 @@ export class ConfigurationService extends Disposable implements IConfiguratio private _configuration: Configuration; private userConfigModelWatcher: ConfigWatcher>; - private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); - public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); + readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; constructor( @IEnvironmentService environmentService: IEnvironmentService @@ -39,38 +49,40 @@ export class ConfigurationService extends Disposable implements IConfiguratio }); this._register(this.userConfigModelWatcher); + this.reset(); + // Listeners this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onDidUpdateConfigModel())); - this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(configurationNodes => this.onDidRegisterConfiguration(configurationNodes))); + this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(configurationProperties => this.onDidRegisterConfiguration(configurationProperties))); } - public get configuration(): Configuration { - return this._configuration || (this._configuration = this.consolidateConfigurations()); + get configuration(): Configuration { + return this._configuration; } - private onDidUpdateConfigModel(): void { - // get the diff - // reset and trigger - this.onConfigurationChange([], []); + getConfiguration(): T + getConfiguration(section: string): T + getConfiguration(overrides: IConfigurationOverrides): T + getConfiguration(section: string, overrides: IConfigurationOverrides): T + getConfiguration(arg1?: any, arg2?: any): any { + const section = typeof arg1 === 'string' ? arg1 : void 0; + const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; + return this.configuration.getValue(section, overrides); } - private onDidRegisterConfiguration(configurations: IConfigurationNode[]): void { - // get the diff - // reset and trigger - this.onConfigurationChange([], []); + getValue(key: string, overrides: IConfigurationOverrides): any { + return this.configuration.getValue2(key, overrides); } - private onConfigurationChange(sections: string[], keys: string[]): void { - this.reset(); // reset our caches - - this._onDidUpdateConfiguration.fire({ sections, keys }); + updateValue(key: string, value: any): TPromise + updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise + updateValue(key: string, value: any, target: ConfigurationTarget): TPromise + updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise + updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { + return TPromise.wrapError(new Error('not supported')); } - public getConfiguration(section?: string, options?: IConfigurationOverrides): IConfiguration { - return this.configuration.getValue(section, options); - } - - public inspect(key: string): { + inspect(key: string): { default: T, user: T, workspace: T, @@ -80,7 +92,7 @@ export class ConfigurationService extends Disposable implements IConfiguratio return this.configuration.lookup(key); } - public keys(): { + keys(): { default: string[]; user: string[]; workspace: string[]; @@ -89,13 +101,47 @@ export class ConfigurationService extends Disposable implements IConfiguratio return this.configuration.keys(); } - private reset(): void { - this._configuration = this.consolidateConfigurations(); + reloadConfiguration(folder?: IWorkspaceFolder): TPromise { + return folder ? TPromise.as(null) : + new TPromise((c, e) => this.userConfigModelWatcher.reload(() => c(this.onDidUpdateConfigModel()))); } - private consolidateConfigurations(): Configuration { + private onDidUpdateConfigModel(): void { + let changedKeys = []; + const { added, updated, removed } = compare(this._configuration.user, this.userConfigModelWatcher.getConfig()); + changedKeys = [...added, ...updated, ...removed]; + if (changedKeys.length) { + const oldConfiguartion = this._configuration; + this.reset(); + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key), this._configuration.getValue2(key))); + if (changedKeys.length) { + this.trigger(changedKeys, ConfigurationTarget.USER); + } + } + } + + private onDidRegisterConfiguration(keys: string[]): void { + this.reset(); // reset our caches + this.trigger(keys, ConfigurationTarget.DEFAULT); + } + + private reset(): void { const defaults = new DefaultConfigurationModel(); const user = this.userConfigModelWatcher.getConfig(); - return new Configuration(defaults, user); + this._configuration = new Configuration(defaults, user); + } + + private trigger(keys: string[], source: ConfigurationTarget): void { + this._onDidUpdateConfiguration.fire(toConfigurationUpdateEvent(keys, source, this.getTargetConfiguration(source))); + } + + private getTargetConfiguration(target: ConfigurationTarget): any { + switch (target) { + case ConfigurationTarget.DEFAULT: + return this._configuration.defaults.contents; + case ConfigurationTarget.USER: + return this._configuration.user.contents; + } + return {}; } } \ No newline at end of file diff --git a/src/vs/platform/configuration/test/common/testConfigurationService.ts b/src/vs/platform/configuration/test/common/testConfigurationService.ts index aed4574d678..5653f211b14 100644 --- a/src/vs/platform/configuration/test/common/testConfigurationService.ts +++ b/src/vs/platform/configuration/test/common/testConfigurationService.ts @@ -10,7 +10,7 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { EventEmitter } from 'vs/base/common/eventEmitter'; import { getConfigurationKeys } from 'vs/platform/configuration/common/model'; -import { IConfigurationOverrides, IConfigurationService, getConfigurationValue, IConfigurationValue, IConfigurationKeys, IConfigurationValues, IConfigurationData, Configuration, ConfigurationModel } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationOverrides, IConfigurationService, getConfigurationValue } from 'vs/platform/configuration/common/configuration'; export class TestConfigurationService extends EventEmitter implements IConfigurationService { public _serviceBrand: any; @@ -19,11 +19,11 @@ export class TestConfigurationService extends EventEmitter implements IConfigura private configurationByRoot: TernarySearchTree = TernarySearchTree.forPaths(); - public reloadConfiguration(section?: string): TPromise { + public reloadConfiguration(): TPromise { return TPromise.as(this.getConfiguration()); } - public getConfiguration(section?: string, overrides?: IConfigurationOverrides): any { + public getConfiguration(section?: any, overrides?: any): C { if (overrides && overrides.resource) { const configForResource = this.configurationByRoot.findSubstr(overrides.resource.fsPath); return configForResource || this.configuration; @@ -32,8 +32,12 @@ export class TestConfigurationService extends EventEmitter implements IConfigura return this.configuration; } - public getConfigurationData(): IConfigurationData { - return new Configuration(new ConfigurationModel(), new ConfigurationModel(this.configuration)).toData(); + public getValue(key: string, overrides?: IConfigurationOverrides): any { + return this.inspect(key).value; + } + + public updateValue(key: string, overrides?: IConfigurationOverrides): TPromise { + return TPromise.as(null); } public setUserConfiguration(key: any, value: any, root?: URI): Thenable { @@ -52,28 +56,30 @@ export class TestConfigurationService extends EventEmitter implements IConfigura return { dispose() { } }; } - public lookup(key: string, overrides?: IConfigurationOverrides): IConfigurationValue { + public inspect(key: string, overrides?: IConfigurationOverrides): { + default: T, + user: T, + workspace: T, + workspaceFolder: T + value: T, + } { const config = this.getConfiguration(undefined, overrides); return { - value: getConfigurationValue(config, key), - default: getConfigurationValue(config, key), - user: getConfigurationValue(config, key), + value: getConfigurationValue(config, key), + default: getConfigurationValue(config, key), + user: getConfigurationValue(config, key), workspace: null, - folder: null + workspaceFolder: null }; } - public keys(): IConfigurationKeys { + public keys() { return { default: getConfigurationKeys(), user: Object.keys(this.configuration), workspace: [], - folder: [] + workspaceFolder: [] }; } - - public values(): IConfigurationValues { - return {}; - } } diff --git a/src/vs/platform/configuration/test/node/configurationService.test.ts b/src/vs/platform/configuration/test/node/configurationService.test.ts index 594a6eb5287..60652d4b614 100644 --- a/src/vs/platform/configuration/test/node/configurationService.test.ts +++ b/src/vs/platform/configuration/test/node/configurationService.test.ts @@ -122,7 +122,8 @@ suite('ConfigurationService - Node', () => { assert.equal(config.foo, 'bar'); // force a reload to get latest - service.reloadConfiguration<{ foo: string }>().then(config => { + service.reloadConfiguration().then(() => { + config = service.getConfiguration<{ foo: string }>(); assert.ok(config); assert.equal(config.foo, 'changed'); @@ -202,12 +203,12 @@ suite('ConfigurationService - Node', () => { testFile((testFile, cleanUp) => { const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); - let res = service.lookup('something.missing'); + let res = service.inspect('something.missing'); assert.strictEqual(res.value, void 0); assert.strictEqual(res.default, void 0); assert.strictEqual(res.user, void 0); - res = service.lookup('lookup.service.testSetting'); + res = service.inspect('lookup.service.testSetting'); assert.strictEqual(res.default, 'isSet'); assert.strictEqual(res.value, 'isSet'); assert.strictEqual(res.user, void 0); @@ -215,7 +216,7 @@ suite('ConfigurationService - Node', () => { fs.writeFileSync(testFile, '{ "lookup.service.testSetting": "bar" }'); return service.reloadConfiguration().then(() => { - res = service.lookup('lookup.service.testSetting'); + res = service.inspect('lookup.service.testSetting'); assert.strictEqual(res.default, 'isSet'); assert.strictEqual(res.user, 'bar'); assert.strictEqual(res.value, 'bar'); @@ -242,7 +243,7 @@ suite('ConfigurationService - Node', () => { testFile((testFile, cleanUp) => { const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); - let res = service.lookup('lookup.service.testNullSetting'); + let res = service.inspect('lookup.service.testNullSetting'); assert.strictEqual(res.default, null); assert.strictEqual(res.value, null); assert.strictEqual(res.user, void 0); @@ -250,7 +251,7 @@ suite('ConfigurationService - Node', () => { fs.writeFileSync(testFile, '{ "lookup.service.testNullSetting": null }'); return service.reloadConfiguration().then(() => { - res = service.lookup('lookup.service.testNullSetting'); + res = service.inspect('lookup.service.testNullSetting'); assert.strictEqual(res.default, null); assert.strictEqual(res.value, null); assert.strictEqual(res.user, null); diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index a910df65983..9ef38db2fa9 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -9,7 +9,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { guessMimeTypes } from 'vs/base/common/mime'; import paths = require('vs/base/common/paths'); import URI from 'vs/base/common/uri'; -import { ConfigurationSource, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService, KeybindingSource } from 'vs/platform/keybinding/common/keybinding'; import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; import { ITelemetryService, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; @@ -186,7 +186,7 @@ const configurationValueWhitelist = [ export function configurationTelemetry(telemetryService: ITelemetryService, configurationService: IConfigurationService): IDisposable { return configurationService.onDidUpdateConfiguration(event => { - if (event.source !== ConfigurationSource.Default) { + if (event.source !== ConfigurationTarget.DEFAULT) { /* __GDPR__ "updateConfiguration" : { "configurationSource" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, @@ -194,7 +194,7 @@ export function configurationTelemetry(telemetryService: ITelemetryService, conf } */ telemetryService.publicLog('updateConfiguration', { - configurationSource: ConfigurationSource[event.source], + configurationSource: ConfigurationTarget[event.source], configurationKeys: flattenKeys(event.sourceConfig) }); /* __GDPR__ @@ -204,7 +204,7 @@ export function configurationTelemetry(telemetryService: ITelemetryService, conf } */ telemetryService.publicLog('updateConfigurationValues', { - configurationSource: ConfigurationSource[event.source], + configurationSource: ConfigurationTarget[event.source], configurationValues: flattenValues(event.sourceConfig, configurationValueWhitelist) }); } diff --git a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts index 494159a5f56..45173045d9a 100644 --- a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts @@ -681,24 +681,24 @@ suite('TelemetryService', () => { enableTelemetry: enableTelemetry } as any; }, - getConfigurationData(): any { + getValue(key) { + return getConfigurationValue(this.getConfiguration(), key); + }, + updateValue() { return null; }, - reloadConfiguration() { - return TPromise.as(this.getConfiguration()); - }, - lookup(key: string) { + inspect(key: string) { return { value: getConfigurationValue(this.getConfiguration(), key), default: getConfigurationValue(this.getConfiguration(), key), user: getConfigurationValue(this.getConfiguration(), key), workspace: null, - folder: null + workspaceFolder: null }; }, - keys() { return { default: [], user: [], workspace: [], folder: [] }; }, - values() { return {}; }, - onDidUpdateConfiguration: emitter.event + keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; }, + onDidUpdateConfiguration: emitter.event, + reloadConfiguration() { return null; } }); assert.equal(service.isOptedIn, false); diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 71f54113cfd..46648b2b1ae 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -29,7 +29,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); this._configurationListener = configurationService.onDidUpdateConfiguration(() => { - proxy.$acceptConfigurationChanged(configurationService.getConfigurationData()); + proxy.$acceptConfigurationChanged(configurationService.getConfiguration()); }); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 777ec4918af..d46aff79813 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -41,7 +41,7 @@ class TrimWhitespaceParticipant implements INamedSaveParticpant { } public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void { - if (this.configurationService.lookup('files.trimTrailingWhitespace', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() }).value) { + if (this.configurationService.getValue('files.trimTrailingWhitespace', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doTrimTrailingWhitespace(model.textEditorModel, env.reason === SaveReason.AUTO); } } @@ -99,7 +99,7 @@ export class FinalNewLineParticipant implements INamedSaveParticpant { } public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void { - if (this.configurationService.lookup('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() }).value) { + if (this.configurationService.getValue('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doInsertFinalNewLine(model.textEditorModel); } } @@ -139,7 +139,7 @@ export class TrimFinalNewLinesParticipant implements INamedSaveParticpant { } public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void { - if (this.configurationService.lookup('files.trimFinalNewlines', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() }).value) { + if (this.configurationService.getValue('files.trimFinalNewlines', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) { this.doTrimFinalNewLines(model.textEditorModel); } } @@ -189,7 +189,7 @@ class FormatOnSaveParticipant implements INamedSaveParticpant { const model = editorModel.textEditorModel; if (env.reason === SaveReason.AUTO - || !this._configurationService.lookup('editor.formatOnSave', { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() }).value) { + || !this._configurationService.getValue('editor.formatOnSave', { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() })) { return undefined; } diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 931b01fc875..9e5101340bf 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -104,7 +104,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { defaultValue: config.default, globalValue: config.user, workspaceValue: config.workspace, - workspaceFolderValue: config.folder + workspaceFolderValue: config.workspaceFolder }; } return undefined; diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 28a91b2db63..ab16b258da8 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -966,7 +966,7 @@ export class ChangeModeAction extends Action { TPromise.timeout(50 /* quick open is sensitive to being opened so soon after another */).done(() => { this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || basename) }).done(language => { if (language) { - const fileAssociationsConfig = this.configurationService.lookup(ChangeModeAction.FILE_ASSOCIATION_KEY); + const fileAssociationsConfig = this.configurationService.inspect(ChangeModeAction.FILE_ASSOCIATION_KEY); let associationKey: string; if (extension && basename[0] !== '.') { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 806c5d7d2c8..bfba7464b3d 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -118,7 +118,7 @@ export class TitlebarPart extends Part implements ITitleService { private onConfigurationChanged(update?: boolean): void { const currentTitleTemplate = this.titleTemplate; - this.titleTemplate = this.configurationService.lookup('window.title').value; + this.titleTemplate = this.configurationService.getValue('window.title'); if (update && currentTitleTemplate !== this.titleTemplate) { this.setTitle(this.getWindowTitle()); diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 67796b9bc2f..70406345142 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -164,7 +164,7 @@ export class ToggleMenuBarAction extends Action { } public run(): TPromise { - let currentVisibilityValue = this.configurationService.lookup(ToggleMenuBarAction.menuBarVisibilityKey).value; + let currentVisibilityValue = this.configurationService.getValue(ToggleMenuBarAction.menuBarVisibilityKey); if (typeof currentVisibilityValue !== 'string') { currentVisibilityValue = 'default'; } @@ -210,7 +210,7 @@ export abstract class BaseZoomAction extends Action { protected setConfiguredZoomLevel(level: number): void { let target = ConfigurationTarget.USER; - if (typeof this.configurationService.lookup(BaseZoomAction.SETTING_KEY).workspace === 'number') { + if (typeof this.configurationService.inspect(BaseZoomAction.SETTING_KEY).workspace === 'number') { target = ConfigurationTarget.WORKSPACE; } diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index f461e27e464..7784777acea 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -17,7 +17,7 @@ import paths = require('vs/base/common/paths'); import uri from 'vs/base/common/uri'; import strings = require('vs/base/common/strings'); import { IWorkspaceContextService, Workspace, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; +import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { realpath } from 'vs/base/node/pfs'; diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index bdf4e7eeef2..d90e9c76efc 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -498,7 +498,7 @@ export class ElectronWindow extends Themable { } private toggleAutoSave(): void { - const setting = this.configurationService.lookup(ElectronWindow.AUTO_SAVE_SETTING); + const setting = this.configurationService.inspect(ElectronWindow.AUTO_SAVE_SETTING); let userAutoSaveConfig = setting.user; if (types.isUndefinedOrNull(userAutoSaveConfig)) { userAutoSaveConfig = setting.default; // use default if setting not defined diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index c565be4c877..59b300fc28b 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -46,7 +46,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService'; import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configuration'; +import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configurationService'; import { IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; @@ -407,7 +407,7 @@ export class Workbench implements IPartService { workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: isDeveloping ? null : KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', localize('file', "File")); // Actions for macOS native tabs management (only when enabled) - const windowConfig = this.configurationService.getConfiguration(); + const windowConfig = this.configurationService.getConfiguration(); if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) { workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousWindowTab, ShowPreviousWindowTab.ID, ShowPreviousWindowTab.LABEL), 'Show Previous Window Tab'); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextWindowTab, ShowNextWindowTab.ID, ShowNextWindowTab.LABEL), 'Show Next Window Tab'); @@ -484,13 +484,13 @@ export class Workbench implements IPartService { } private openUntitledFile() { - const startupEditor = this.configurationService.lookup('workbench.startupEditor'); + const startupEditor = this.configurationService.inspect('workbench.startupEditor'); // Fallback to previous workbench.welcome.enabled setting in case startupEditor is not defined if (!startupEditor.user && !startupEditor.workspace) { - const welcomeEnabled = this.configurationService.lookup('workbench.welcome.enabled'); - if (typeof welcomeEnabled.value === 'boolean') { - return !welcomeEnabled.value; + const welcomeEnabledValue = this.configurationService.getValue('workbench.welcome.enabled'); + if (typeof welcomeEnabledValue === 'boolean') { + return !welcomeEnabledValue; } } @@ -639,19 +639,19 @@ export class Workbench implements IPartService { } // Sidebar position - const sideBarPosition = this.configurationService.lookup(Workbench.sidebarPositionConfigurationKey).value; + const sideBarPosition = this.configurationService.getValue(Workbench.sidebarPositionConfigurationKey); this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT; // Statusbar visibility - const statusBarVisible = this.configurationService.lookup(Workbench.statusbarVisibleConfigurationKey).value; + const statusBarVisible = this.configurationService.getValue(Workbench.statusbarVisibleConfigurationKey); this.statusBarHidden = !statusBarVisible; // Activity bar visibility - const activityBarVisible = this.configurationService.lookup(Workbench.activityBarVisibleConfigurationKey).value; + const activityBarVisible = this.configurationService.getValue(Workbench.activityBarVisibleConfigurationKey); this.activityBarHidden = !activityBarVisible; // Font aliasing - this.fontAliasing = this.configurationService.lookup(Workbench.fontAliasingConfigurationKey).value; + this.fontAliasing = this.configurationService.getValue(Workbench.fontAliasingConfigurationKey); // Zen mode this.zenMode = { @@ -1036,7 +1036,7 @@ export class Workbench implements IPartService { // Overruled by: window has a workspace opened or this window is for extension development // or setting is disabled. Also enabled when running with --wait from the command line. if (visibleEditors === 0 && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && !this.environmentService.isExtensionDevelopment) { - const closeWhenEmpty = this.configurationService.lookup(Workbench.closeWhenEmptyConfigurationKey).value; + const closeWhenEmpty = this.configurationService.getValue(Workbench.closeWhenEmptyConfigurationKey); if (closeWhenEmpty || this.environmentService.args.wait) { this.closeEmptyWindowScheduler.schedule(); } @@ -1068,24 +1068,24 @@ export class Workbench implements IPartService { } private onDidUpdateConfiguration(skipLayout?: boolean): void { - const newSidebarPositionValue = this.configurationService.lookup(Workbench.sidebarPositionConfigurationKey).value; + const newSidebarPositionValue = this.configurationService.getValue(Workbench.sidebarPositionConfigurationKey); const newSidebarPosition = (newSidebarPositionValue === 'right') ? Position.RIGHT : Position.LEFT; if (newSidebarPosition !== this.getSideBarPosition()) { this.setSideBarPosition(newSidebarPosition); } - const fontAliasing = this.configurationService.lookup(Workbench.fontAliasingConfigurationKey).value; + const fontAliasing = this.configurationService.getValue(Workbench.fontAliasingConfigurationKey); if (fontAliasing !== this.fontAliasing) { this.setFontAliasing(fontAliasing); } if (!this.zenMode.active) { - const newStatusbarHiddenValue = !this.configurationService.lookup(Workbench.statusbarVisibleConfigurationKey).value; + const newStatusbarHiddenValue = !this.configurationService.getValue(Workbench.statusbarVisibleConfigurationKey); if (newStatusbarHiddenValue !== this.statusBarHidden) { this.setStatusBarHidden(newStatusbarHiddenValue, skipLayout); } - const newActivityBarHiddenValue = !this.configurationService.lookup(Workbench.activityBarVisibleConfigurationKey).value; + const newActivityBarHiddenValue = !this.configurationService.getValue(Workbench.activityBarVisibleConfigurationKey); if (newActivityBarHiddenValue !== this.activityBarHidden) { this.setActivityBarHidden(newActivityBarHiddenValue, skipLayout); } diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.ts b/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.ts index 83b7176dcbc..e2e99c99949 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.ts @@ -83,7 +83,7 @@ class WordWrapMigrationController extends Disposable implements IEditorContribut } WordWrapMigrationController._checked = true; - let result = this.configurationService.lookup('editor.wrappingColumn'); + let result = this.configurationService.inspect('editor.wrappingColumn'); if (typeof result.value === 'undefined') { // Setting is not used return; diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 346461ba287..18b677b7f61 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -55,7 +55,7 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem { private registerListeners(): void { this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - if (e.sourceConfig.launch) { + if (e.hasSectionChanged('launch')) { this.updateOptions(); } })); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 3ea09044e57..15d1484701b 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -648,7 +648,7 @@ export class DebugService implements debug.IDebugService { public startDebugging(root: IWorkspaceFolder, configOrName?: debug.IConfig | string, noDebug = false, topCompoundName?: string): TPromise { // make sure to save all files and that the configuration is up to date - return this.extensionService.activateByEvent('onDebug').then(() => this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration().then(() => + return this.extensionService.activateByEvent('onDebug').then(() => this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration(root).then(() => this.extensionService.onReady().then(() => { if (this.model.getProcesses().length === 0) { this.removeReplExpressions(); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index d74dd56da46..e3491f2e20a 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -561,8 +561,10 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr range, options: { stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - className: 'findMatch' - } + className: 'findMatch', + + }, + }; } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 5e5597721c6..b8e39c05e11 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -129,6 +129,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic .then(preferencesEditorModel => preferencesEditorModel ? preferencesEditorModel.content : null); } + // vsode://DefaultSettings/1 createPreferencesEditorModel(uri: URI): TPromise> { let promise = this.defaultPreferencesEditorModels.get(uri); if (promise) { @@ -264,6 +265,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource) .then(editableSettingsEditorInput => { if (openDefaultSettings) { + // get a new URI for default settings here const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(configurationTarget)); const preferencesEditorInput = new PreferencesEditorInput(this.getPreferencesEditorInputName(configurationTarget, resource), editableSettingsEditorInput.getDescription(), defaultPreferencesEditorInput, editableSettingsEditorInput); this.lastOpenedSettingsInput = preferencesEditorInput; diff --git a/src/vs/workbench/parts/preferences/common/preferencesModels.ts b/src/vs/workbench/parts/preferences/common/preferencesModels.ts index f17231a589b..26e4c93d348 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesModels.ts @@ -244,7 +244,9 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti constructor(reference: IReference, private _configurationTarget: ConfigurationTarget, @ITextFileService protected textFileService: ITextFileService) { super(); this.settingsModel = reference.object.textEditorModel; - this._register(this.onDispose(() => reference.dispose())); + this._register(this.onDispose(() => { + reference.dispose(); + })); this._register(this.settingsModel.onDidChangeContent(() => { this._settingsGroups = null; })); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index 6507587aa97..a5e20e79b5d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -114,8 +114,8 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { public mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig): void { // Check whether there is a workspace setting const platformKey = platform.isWindows ? 'windows' : platform.isMacintosh ? 'osx' : 'linux'; - const shellConfigValue = this._workspaceConfigurationService.lookup(`terminal.integrated.shell.${platformKey}`); - const shellArgsConfigValue = this._workspaceConfigurationService.lookup(`terminal.integrated.shellArgs.${platformKey}`); + const shellConfigValue = this._workspaceConfigurationService.inspect(`terminal.integrated.shell.${platformKey}`); + const shellArgsConfigValue = this._workspaceConfigurationService.inspect(`terminal.integrated.shellArgs.${platformKey}`); // Check if workspace setting exists and whether it's whitelisted let isWorkspaceShellAllowed = false; diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts index e95533d078f..faa3f2ac009 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -6,7 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import { IConfigurationService, getConfigurationValue, IConfigurationValue, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, getConfigurationValue, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { Platform } from 'vs/base/common/platform'; import { TPromise } from 'vs/base/common/winjs.base'; import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; @@ -17,13 +17,14 @@ class MockConfigurationService implements IConfigurationService { public _serviceBrand: any; public serviceId = IConfigurationService; public constructor(private configuration: any = {}) { } - public reloadConfiguration(section?: string): TPromise { return TPromise.as(this.getConfiguration()); } - public lookup(key: string, overrides?: IConfigurationOverrides): IConfigurationValue { return { value: getConfigurationValue(this.getConfiguration(), key), default: getConfigurationValue(this.getConfiguration(), key), user: getConfigurationValue(this.getConfiguration(), key), workspace: void 0, folder: void 0 }; } - public keys() { return { default: [], user: [], workspace: [], folder: [] }; } - public values() { return {}; } + public inspect(key: string, overrides?: IConfigurationOverrides): any { return { value: getConfigurationValue(this.getConfiguration(), key), default: getConfigurationValue(this.getConfiguration(), key), user: getConfigurationValue(this.getConfiguration(), key), workspace: void 0, workspaceFolder: void 0 }; } + public keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; } public getConfiguration(): any { return this.configuration; } + public getValue(key: string, overrides?: IConfigurationOverrides): T { return getConfigurationValue(this.getConfiguration(), key); } + public updateValue(): TPromise { return null; } public getConfigurationData(): any { return null; } public onDidUpdateConfiguration() { return { dispose() { } }; } + public reloadConfiguration() { return null; } } suite('Workbench - TerminalConfigHelper', () => { diff --git a/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts b/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts index 2c44384ef13..10069d1f991 100644 --- a/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts +++ b/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts @@ -60,7 +60,7 @@ export class SelectColorThemeAction extends Action { } let target = null; if (applyTheme) { - let confValue = this.configurationService.lookup(COLOR_THEME_SETTING); + let confValue = this.configurationService.inspect(COLOR_THEME_SETTING); target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER; } @@ -126,7 +126,7 @@ class SelectIconThemeAction extends Action { } let target = null; if (applyTheme) { - let confValue = this.configurationService.lookup(ICON_THEME_SETTING); + let confValue = this.configurationService.inspect(ICON_THEME_SETTING); target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER; } this.themeService.setFileIconTheme(theme && theme.id, target).done(null, diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 5420ab82b04..21c46e71bdd 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -120,13 +120,13 @@ export class WatermarkContribution implements IWorkbenchContribution { lifecycleService.onShutdown(this.dispose, this); this.partService.joinCreation().then(() => { - this.enabled = this.configurationService.lookup('workbench.tips.enabled').value; + this.enabled = this.configurationService.getValue('workbench.tips.enabled'); if (this.enabled) { this.create(); } }); this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - const enabled = this.configurationService.lookup('workbench.tips.enabled').value; + const enabled = this.configurationService.getValue('workbench.tips.enabled'); if (enabled !== this.enabled) { this.enabled = enabled; if (this.enabled) { diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index 93be1d9e534..c54020a8d3f 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -83,9 +83,9 @@ export class WelcomePageContribution implements IWorkbenchContribution { } function isWelcomePageEnabled(configurationService: IConfigurationService) { - const startupEditor = configurationService.lookup(configurationKey); + const startupEditor = configurationService.inspect(configurationKey); if (!startupEditor.user && !startupEditor.workspace) { - const welcomeEnabled = configurationService.lookup(oldConfigurationKey); + const welcomeEnabled = configurationService.inspect(oldConfigurationKey); if (welcomeEnabled.value !== undefined && welcomeEnabled.value !== null) { return welcomeEnabled.value; } diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts index 3795d6aabd1..173483768ba 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts @@ -285,7 +285,7 @@ export class WalkThroughPart extends BaseEditor { } private getArrowScrollHeight() { - let fontSize = this.configurationService.lookup('editor.fontSize').value; + let fontSize = this.configurationService.getValue('editor.fontSize'); if (typeof fontSize !== 'number' || fontSize < 1) { fontSize = 12; } @@ -510,8 +510,8 @@ export class WalkThroughPart extends BaseEditor { private multiCursorModifier() { const labels = UILabelProvider.modifierLabels[OS]; - const setting = this.configurationService.lookup('editor.multiCursorModifier'); - const modifier = labels[setting.value === 'ctrlCmd' ? (OS === OperatingSystem.Macintosh ? 'metaKey' : 'ctrlKey') : 'altKey']; + const value = this.configurationService.getValue('editor.multiCursorModifier'); + const modifier = labels[value === 'ctrlCmd' ? (OS === OperatingSystem.Macintosh ? 'metaKey' : 'ctrlKey') : 'altKey']; const keys = this.content.querySelectorAll('.multi-cursor-modifier'); Array.prototype.forEach.call(keys, (key: Element) => { while (key.firstChild) { diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index 9dffb9cba33..3d4eb1394b2 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IConfigurationService } from 'vs/platform/configuration/common/configuration2'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const CONFIG_DEFAULT_NAME = 'settings'; @@ -13,14 +13,17 @@ export const WORKSPACE_CONFIG_DEFAULT_PATH = `${WORKSPACE_CONFIG_FOLDER_DEFAULT_ export const IWorkspaceConfigurationService = createDecorator('configurationService'); export interface IWorkspaceConfigurationService extends IConfigurationService { - /** * Returns untrusted configuration keys for the current workspace. */ getUnsupportedWorkspaceKeys(): string[]; - } +export const defaultSettingsSchemaId = 'vscode://schemas/settings/default'; +export const userSettingsSchemaId = 'vscode://schemas/settings/user'; +export const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace'; +export const folderSettingsSchemaId = 'vscode://schemas/settings/folder'; + export const TASKS_CONFIGURATION_KEY = 'tasks'; export const LAUNCH_CONFIGURATION_KEY = 'launch'; diff --git a/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts b/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts new file mode 100644 index 00000000000..7614f64f2e3 --- /dev/null +++ b/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts @@ -0,0 +1,212 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import * as objects from 'vs/base/common/objects'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IJSONSchema } from 'vs/base/common/jsonSchema'; +import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/extensions/common/extensionsRegistry'; +import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; +import { workspaceSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; + +const configurationRegistry = Registry.as(Extensions.Configuration); + +const configurationEntrySchema: IJSONSchema = { + type: 'object', + defaultSnippets: [{ body: { title: '', properties: {} } }], + properties: { + title: { + description: nls.localize('vscode.extension.contributes.configuration.title', 'A summary of the settings. This label will be used in the settings file as separating comment.'), + type: 'string' + }, + properties: { + description: nls.localize('vscode.extension.contributes.configuration.properties', 'Description of the configuration properties.'), + type: 'object', + additionalProperties: { + anyOf: [ + { $ref: 'http://json-schema.org/draft-04/schema#' }, + { + type: 'object', + properties: { + isExecutable: { + type: 'boolean' + }, + scope: { + type: 'string', + enum: ['window', 'resource'], + default: 'window', + enumDescriptions: [ + nls.localize('scope.window.description', "Window specific configuration, which can be configured in the User or Workspace settings."), + nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the User, Workspace or Folder settings.") + ], + description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.") + } + } + } + ] + } + } + } +}; + + +// BEGIN VSCode extension point `configuration` +const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configuration', [], { + description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'), + oneOf: [ + configurationEntrySchema, + { + type: 'array', + items: configurationEntrySchema + } + ] +}); +configurationExtPoint.setHandler(extensions => { + const configurations: IConfigurationNode[] = []; + + function handleConfiguration(node: IConfigurationNode, id: string, collector: ExtensionMessageCollector) { + let configuration = objects.clone(node); + + if (configuration.title && (typeof configuration.title !== 'string')) { + collector.error(nls.localize('invalid.title', "'configuration.title' must be a string")); + } + + validateProperties(configuration, collector); + + configuration.id = id; + configurations.push(configuration); + }; + + for (let extension of extensions) { + const collector = extension.collector; + const value = extension.value; + const id = extension.description.id; + if (!Array.isArray(value)) { + handleConfiguration(value, id, collector); + } else { + value.forEach(v => handleConfiguration(v, id, collector)); + } + } + configurationRegistry.registerConfigurations(configurations, false); +}); +// END VSCode extension point `configuration` + +// BEGIN VSCode extension point `configurationDefaults` +const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configurationDefaults', [], { + description: nls.localize('vscode.extension.contributes.defaultConfiguration', 'Contributes default editor configuration settings by language.'), + type: 'object', + defaultSnippets: [{ body: {} }], + patternProperties: { + '\\[.*\\]$': { + type: 'object', + default: {}, + $ref: editorConfigurationSchemaId, + } + } +}); +defaultConfigurationExtPoint.setHandler(extensions => { + const defaultConfigurations: IDefaultConfigurationExtension[] = extensions.map(extension => { + const id = extension.description.id; + const name = extension.description.name; + const defaults = objects.clone(extension.value); + return { + id, name, defaults + }; + }); + configurationRegistry.registerDefaultConfigurations(defaultConfigurations); +}); +// END VSCode extension point `configurationDefaults` + +function validateProperties(configuration: IConfigurationNode, collector: ExtensionMessageCollector): void { + let properties = configuration.properties; + if (properties) { + if (typeof properties !== 'object') { + collector.error(nls.localize('invalid.properties', "'configuration.properties' must be an object")); + configuration.properties = {}; + } + for (let key in properties) { + const message = validateProperty(key); + const propertyConfiguration = configuration.properties[key]; + propertyConfiguration.scope = propertyConfiguration.scope && propertyConfiguration.scope.toString() === 'resource' ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW; + propertyConfiguration.isFromExtensions = true; + if (message) { + collector.warn(message); + delete properties[key]; + } + } + } + let subNodes = configuration.allOf; + if (subNodes) { + collector.error(nls.localize('invalid.allOf', "'configuration.allOf' is deprecated and should no longer be used. Instead, pass multiple configuration sections as an array to the 'configuration' contribution point.")); + for (let node of subNodes) { + validateProperties(node, collector); + } + } +} + +const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); +jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', { + default: { + folders: [ + { + path: '' + } + ], + settings: { + } + }, + required: ['folders'], + properties: { + 'folders': { + minItems: 0, + uniqueItems: true, + description: nls.localize('workspaceConfig.folders.description', "List of folders to be loaded in the workspace."), + items: { + type: 'object', + default: { path: '' }, + oneOf: [{ + properties: { + path: { + type: 'string', + description: nls.localize('workspaceConfig.path.description', "A file path. e.g. `/root/folderA` or `./folderA` for a relative path that will be resolved against the location of the workspace file.") + }, + name: { + type: 'string', + description: nls.localize('workspaceConfig.name.description', "An optional name for the folder. ") + } + }, + required: ['path'] + }, { + properties: { + uri: { + type: 'string', + description: nls.localize('workspaceConfig.uri.description', "URI of the folder") + }, + name: { + type: 'string', + description: nls.localize('workspaceConfig.name.description', "An optional name for the folder. ") + } + }, + required: ['uri'] + }] + } + }, + 'settings': { + type: 'object', + default: {}, + description: nls.localize('workspaceConfig.settings.description', "Workspace settings"), + $ref: workspaceSettingsSchemaId + }, + 'extensions': { + type: 'object', + default: {}, + description: nls.localize('workspaceConfig.extensions.description', "Workspace extensions"), + $ref: 'vscode://schemas/extensions' + } + }, + additionalProperties: false, + errorMessage: nls.localize('unknownWorkspaceProperty', "Unknown workspace configuration property") +}); \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index dd7f73103ed..b23dc396e7c 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { clone } from 'vs/base/common/objects'; +import { clone, equals } from 'vs/base/common/objects'; import { CustomConfigurationModel, toValuesTree } from 'vs/platform/configuration/common/model'; -import { ConfigurationModel } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationModel, Configuration as BaseConfiguration, compare } from 'vs/platform/configuration/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; import { IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; +import { Workspace } from 'vs/platform/workspace/common/workspace'; +import { StrictResourceMap } from 'vs/base/common/map'; +import URI from 'vs/base/common/uri'; export class WorkspaceConfigurationModel extends CustomConfigurationModel { @@ -178,4 +181,88 @@ export class FolderConfigurationModel extends CustomConfigurationModel { this.workspaceSettingsConfig.reprocess(); this.consolidate(); } +} + +export class Configuration extends BaseConfiguration { + + constructor(defaults: ConfigurationModel, user: ConfigurationModel, workspaceConfiguration: ConfigurationModel, protected folders: StrictResourceMap>, workspace: Workspace) { + super(defaults, user, workspaceConfiguration, folders, workspace); + } + + updateDefaultConfiguration(defaults: ConfigurationModel): void { + this._defaults = defaults; + this.merge(); + } + + updateUserConfiguration(user: ConfigurationModel): string[] { + let changedKeys = []; + const { added, updated, removed } = compare(this._user, user); + changedKeys = [...added, ...updated, ...removed]; + if (changedKeys.length) { + const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._workspace); + + this._user = user; + this.merge(); + + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key), this.getValue2(key))); + return changedKeys; + } + return []; + } + + updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): string[] { + let changedKeys = []; + const { added, updated, removed } = compare(this._workspaceConfiguration, workspaceConfiguration); + changedKeys = [...added, ...updated, ...removed]; + if (changedKeys.length) { + const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._workspace); + + this._workspaceConfiguration = workspaceConfiguration; + this.merge(); + + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key), this.getValue2(key))); + return changedKeys; + } + return []; + } + + updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel): string[] { + const currentFolderConfiguration = this.folders.get(resource); + + if (currentFolderConfiguration) { + let changedKeys = []; + const { added, updated, removed } = compare(currentFolderConfiguration, configuration); + changedKeys = [...added, ...updated, ...removed]; + if (changedKeys.length) { + const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._workspace); + + this.folders.set(resource, configuration); + this.mergeFolder(resource); + + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key, { resource }), this.getValue2(key, { resource }))); + return changedKeys; + } + return []; + } + + this.folders.set(resource, configuration); + this.mergeFolder(resource); + return configuration.keys; + } + + deleteFolderConfiguration(folder: URI): string[] { + if (this._workspace && this._workspace.folders.length > 0 && this._workspace.folders[0].uri.toString() === folder.toString()) { + // Do not remove workspace configuration + return []; + } + + const keys = this.folders.get(folder).keys; + this.folders.delete(folder); + this._foldersConsolidatedConfigurations.delete(folder); + return keys; + } + + getFolderConfigurationModel(folder: URI): FolderConfigurationModel { + return >this.folders.get(folder); + } } \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 9787cfcbc1c..694c6122734 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -27,7 +27,7 @@ import { IConfigurationService, IConfigurationOverrides } from 'vs/platform/conf import { keyFromOverrideIdentifier } from 'vs/platform/configuration/common/model'; import { WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; -import { IConfigurationEditingService, ConfigurationEditingErrorCode, ConfigurationEditingError, ConfigurationTarget, IConfigurationValue, IConfigurationEditingOptions } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { ConfigurationTarget, ConfigurationEditingErrorCode, ConfigurationEditingError, IConfigurationValue, IConfigurationEditingOptions, IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IChoiceService, IMessageService, Severity } from 'vs/platform/message/common/message'; @@ -95,9 +95,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService private writeToBuffer(model: editorCommon.IModel, operation: IConfigurationEditOperation, save: boolean): TPromise { const edit = this.getEdits(model, operation)[0]; if (this.applyEditsToBuffer(edit, model) && save) { - return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }) - // Reload the configuration so that we make sure all parties are updated - .then(() => this.configurationService.reloadConfiguration()); + return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }); } return TPromise.as(null); } diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configurationService.ts similarity index 56% rename from src/vs/workbench/services/configuration/node/configuration.ts rename to src/vs/workbench/services/configuration/node/configurationService.ts index 74556f8b5ab..f5b7cef1e68 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -9,8 +9,8 @@ import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; import Event, { Emitter } from 'vs/base/common/event'; import { StrictResourceMap } from 'vs/base/common/map'; -import * as objects from 'vs/base/common/objects'; import * as errors from 'vs/base/common/errors'; +import { equals } from 'vs/base/common/objects'; import * as collections from 'vs/base/common/collections'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; @@ -23,27 +23,23 @@ import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { CustomConfigurationModel } from 'vs/platform/configuration/common/model'; -import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; -import { IConfigurationServiceEvent, ConfigurationSource, IConfigurationKeys, IConfigurationValue, ConfigurationModel, IConfigurationOverrides, Configuration as BaseConfiguration, IConfigurationValues, IConfigurationData } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; -import { ConfigurationService as GlobalConfigurationService } from 'vs/platform/configuration/node/configurationService'; -import * as nls from 'vs/nls'; +import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration } from 'vs/workbench/services/configuration/common/configurationModels'; +import { IConfigurationChangeEvent, ConfigurationTarget, toConfigurationUpdateEvent, ConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; +import { ConfigurationService as GlobalConfigurationService, isConfigurationOverrides } from 'vs/platform/configuration/node/configurationService'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/extensions/common/extensionsRegistry'; -import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope, settingsSchema, resourceSettingsSchema } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationNode, IConfigurationRegistry, Extensions, ConfigurationScope, settingsSchema, resourceSettingsSchema } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspace } from 'vs/platform/workspaces/common/workspaces'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; - -const defaultSettingsSchemaId = 'vscode://schemas/settings/default'; -const userSettingsSchemaId = 'vscode://schemas/settings/user'; -const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace'; -const folderSettingsSchemaId = 'vscode://schemas/settings/folder'; +import { distinct, flatten } from 'vs/base/common/arrays'; +import { IConfigurationEditingService, ConfigurationTarget as EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; interface IStat { resource: URI; @@ -56,212 +52,6 @@ interface IContent { value: string; } -interface IWorkspaceConfiguration { - workspace: T; - consolidated: any; -} - -type IWorkspaceFoldersConfiguration = { [rootFolder: string]: { folders: string[]; } }; - -const configurationRegistry = Registry.as(Extensions.Configuration); - -const configurationEntrySchema: IJSONSchema = { - type: 'object', - defaultSnippets: [{ body: { title: '', properties: {} } }], - properties: { - title: { - description: nls.localize('vscode.extension.contributes.configuration.title', 'A summary of the settings. This label will be used in the settings file as separating comment.'), - type: 'string' - }, - properties: { - description: nls.localize('vscode.extension.contributes.configuration.properties', 'Description of the configuration properties.'), - type: 'object', - additionalProperties: { - anyOf: [ - { $ref: 'http://json-schema.org/draft-04/schema#' }, - { - type: 'object', - properties: { - isExecutable: { - type: 'boolean' - }, - scope: { - type: 'string', - enum: ['window', 'resource'], - default: 'window', - enumDescriptions: [ - nls.localize('scope.window.description', "Window specific configuration, which can be configured in the User or Workspace settings."), - nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the User, Workspace or Folder settings.") - ], - description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.") - } - } - } - ] - } - } - } -}; - - -// BEGIN VSCode extension point `configuration` -const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configuration', [], { - description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'), - oneOf: [ - configurationEntrySchema, - { - type: 'array', - items: configurationEntrySchema - } - ] -}); -configurationExtPoint.setHandler(extensions => { - const configurations: IConfigurationNode[] = []; - - function handleConfiguration(node: IConfigurationNode, id: string, collector: ExtensionMessageCollector) { - let configuration = objects.clone(node); - - if (configuration.title && (typeof configuration.title !== 'string')) { - collector.error(nls.localize('invalid.title', "'configuration.title' must be a string")); - } - - validateProperties(configuration, collector); - - configuration.id = id; - configurations.push(configuration); - }; - - for (let extension of extensions) { - const collector = extension.collector; - const value = extension.value; - const id = extension.description.id; - if (!Array.isArray(value)) { - handleConfiguration(value, id, collector); - } else { - value.forEach(v => handleConfiguration(v, id, collector)); - } - } - configurationRegistry.registerConfigurations(configurations, false); -}); -// END VSCode extension point `configuration` - -// BEGIN VSCode extension point `configurationDefaults` -const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configurationDefaults', [], { - description: nls.localize('vscode.extension.contributes.defaultConfiguration', 'Contributes default editor configuration settings by language.'), - type: 'object', - defaultSnippets: [{ body: {} }], - patternProperties: { - '\\[.*\\]$': { - type: 'object', - default: {}, - $ref: editorConfigurationSchemaId, - } - } -}); -defaultConfigurationExtPoint.setHandler(extensions => { - const defaultConfigurations: IDefaultConfigurationExtension[] = extensions.map(extension => { - const id = extension.description.id; - const name = extension.description.name; - const defaults = objects.clone(extension.value); - return { - id, name, defaults - }; - }); - configurationRegistry.registerDefaultConfigurations(defaultConfigurations); -}); -// END VSCode extension point `configurationDefaults` - -function validateProperties(configuration: IConfigurationNode, collector: ExtensionMessageCollector): void { - let properties = configuration.properties; - if (properties) { - if (typeof properties !== 'object') { - collector.error(nls.localize('invalid.properties', "'configuration.properties' must be an object")); - configuration.properties = {}; - } - for (let key in properties) { - const message = validateProperty(key); - const propertyConfiguration = configuration.properties[key]; - propertyConfiguration.scope = propertyConfiguration.scope && propertyConfiguration.scope.toString() === 'resource' ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW; - propertyConfiguration.isFromExtensions = true; - if (message) { - collector.warn(message); - delete properties[key]; - } - } - } - let subNodes = configuration.allOf; - if (subNodes) { - collector.error(nls.localize('invalid.allOf', "'configuration.allOf' is deprecated and should no longer be used. Instead, pass multiple configuration sections as an array to the 'configuration' contribution point.")); - for (let node of subNodes) { - validateProperties(node, collector); - } - } -} - -const contributionRegistry = Registry.as(JSONExtensions.JSONContribution); -contributionRegistry.registerSchema('vscode://schemas/workspaceConfig', { - default: { - folders: [ - { - path: '' - } - ], - settings: { - } - }, - required: ['folders'], - properties: { - 'folders': { - minItems: 0, - uniqueItems: true, - description: nls.localize('workspaceConfig.folders.description', "List of folders to be loaded in the workspace."), - items: { - type: 'object', - default: { path: '' }, - oneOf: [{ - properties: { - path: { - type: 'string', - description: nls.localize('workspaceConfig.path.description', "A file path. e.g. `/root/folderA` or `./folderA` for a relative path that will be resolved against the location of the workspace file.") - }, - name: { - type: 'string', - description: nls.localize('workspaceConfig.name.description', "An optional name for the folder. ") - } - }, - required: ['path'] - }, { - properties: { - uri: { - type: 'string', - description: nls.localize('workspaceConfig.uri.description', "URI of the folder") - }, - name: { - type: 'string', - description: nls.localize('workspaceConfig.name.description', "An optional name for the folder. ") - } - }, - required: ['uri'] - }] - } - }, - 'settings': { - type: 'object', - default: {}, - description: nls.localize('workspaceConfig.settings.description', "Workspace settings"), - $ref: workspaceSettingsSchemaId - }, - 'extensions': { - type: 'object', - default: {}, - description: nls.localize('workspaceConfig.extensions.description', "Workspace extensions"), - $ref: 'vscode://schemas/extensions' - } - }, - additionalProperties: false, - errorMessage: nls.localize('unknownWorkspaceProperty', "Unknown workspace configuration property") -}); - export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { public _serviceBrand: any; @@ -272,8 +62,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private workspaceConfiguration: WorkspaceConfiguration; private cachedFolderConfigs: StrictResourceMap>; - protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); - public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); + public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; protected readonly _onDidChangeWorkspaceFolders: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceFolders.event; @@ -284,6 +74,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat protected readonly _onDidChangeWorkbenchState: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkbenchState: Event = this._onDidChangeWorkbenchState.event; + private configurationEditingService: IConfigurationEditingService; + constructor(private environmentService: IEnvironmentService, private workspacesService: IWorkspacesService, private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME) { super(); @@ -292,9 +84,11 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService)); this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); - this._register(configurationRegistry.onDidRegisterConfiguration(e => this.registerConfigurationSchemas())); + this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(e => this.registerConfigurationSchemas())); } + // Workspace Context Service Impl + public getWorkspace(): Workspace { return this.workspace; } @@ -332,64 +126,112 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return false; } - public getConfigurationData(): IConfigurationData { - return this._configuration.toData(); + // Workspace Configuration Service Impl + + getConfiguration(): T + getConfiguration(section: string): T + getConfiguration(overrides: IConfigurationOverrides): T + getConfiguration(section: string, overrides: IConfigurationOverrides): T + getConfiguration(arg1?: any, arg2?: any): any { + const section = typeof arg1 === 'string' ? arg1 : void 0; + const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; + const contents = this._configuration.getValue(section, overrides); + return typeof contents === 'object' ? { toJSON: () => this._configuration.toData(), ...contents } + : contents; } - public getConfiguration(section?: string, overrides?: IConfigurationOverrides): C { - return this._configuration.getValue(section, overrides); + getValue(key: string, overrides?: IConfigurationOverrides): T { + return this._configuration.getValue2(key, overrides); } - public lookup(key: string, overrides?: IConfigurationOverrides): IConfigurationValue { - return this._configuration.lookup(key, overrides); - } + updateValue(key: string, value: any): TPromise + updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise + updateValue(key: string, value: any, target: ConfigurationTarget): TPromise + updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise + updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { + if (this.configurationEditingService) { + const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0; + const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3); - public keys(overrides?: IConfigurationOverrides): IConfigurationKeys { - return this._configuration.keys(overrides); - } - - public values(): IConfigurationValues { - return this._configuration.values(); - } - - public reloadConfiguration(section?: string): TPromise { - const current = this._configuration; - // Reload and reinitialize to ensure we are hitting the disk - return this.baseConfigurationService.reloadConfiguration() - .then(() => { - if (this.workspace.configuration) { - return this.workspaceConfiguration.load(this.workspace.configuration) - .then(() => this.initializeConfiguration(false)); + if (target) { + if (target === ConfigurationTarget.MEMORY) { + return TPromise.as(null); + } else { + return this.writeConfigurationValue(key, value, target, overrides); } - return this.initializeConfiguration(false); - }) - .then(() => { - // Check and trigger - if (!this._configuration.equals(current)) { - this.triggerConfigurationChange(); - } - return this.getConfiguration(section); - }); + } + } + return TPromise.as(null); } - public getUnsupportedWorkspaceKeys(): string[] { + reloadConfiguration(folder?: IWorkspaceFolder, key?: string): TPromise { + if (folder) { + return this.reloadWorkspaceFolderConfiguration(folder, key); + } + return this.loadConfiguration(); + } + + inspect(key: string, overrides?: IConfigurationOverrides): { + default: T, + user: T, + workspace: T, + workspaceFolder: T, + value: T + } { + return this._configuration.lookup(key); + } + + keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + } { + return this._configuration.keys(); + } + + getUnsupportedWorkspaceKeys(): string[] { return this.getWorkbenchState() === WorkbenchState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.folders[0].uri).workspaceSettingsConfig.unsupportedKeys : []; } - public handleWorkspaceFileEvents(event: FileChangesEvent): void { - TPromise.join(this.workspace.folders.map(folder => this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event))) // handle file event for each folder - .then(folderConfigurations => - folderConfigurations.map((configuration, index) => ({ configuration, folder: this.workspace.folders[index] })) - .filter(folderConfiguration => !!folderConfiguration.configuration) // Filter folders which are not impacted by events - .map(folderConfiguration => this.updateFolderConfiguration(folderConfiguration.folder, folderConfiguration.configuration, true)) // Update the configuration of impacted folders - .reduce((result, value) => result || value, false)) // Check if the effective configuration of folder is changed - .then(changed => changed ? this.triggerConfigurationChange() : void 0); // Trigger event if changed + reloadUserConfiguration(key?: string): TPromise { + return this.baseConfigurationService.reloadConfiguration(); } - public initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { + reloadWorkspaceConfiguration(key?: string): TPromise { + const workbenchState = this.getWorkbenchState(); + if (workbenchState === WorkbenchState.FOLDER) { + return this.onWorkspaceFolderConfigurationChanged(this.workspace.folders[0], key); + } + if (workbenchState === WorkbenchState.WORKSPACE) { + return this.onWorkspaceConfigurationChanged(); + } + return TPromise.as(null); + } + + reloadWorkspaceFolderConfiguration(folder: IWorkspaceFolder, key?: string): TPromise { + return this.onWorkspaceFolderConfigurationChanged(folder, key); + } + + initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { return this.createWorkspace(arg) .then(workspace => this.setWorkspace(workspace)) - .then(() => this.initializeConfiguration(true)); + .then(() => this.initializeConfiguration()); + } + + aquireDelayedServices(instantiationService: IInstantiationService): void { + this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService); + } + + handleWorkspaceFileEvents(event: FileChangesEvent): void { + switch (this.getWorkbenchState()) { + case WorkbenchState.FOLDER: + this.onSingleFolderFileChanges(event); + return; + case WorkbenchState.WORKSPACE: + this.onWorkspaceFileChanges(event); + return; + } } private createWorkspace(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { @@ -470,137 +312,232 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return result; } - private initializeConfiguration(trigger: boolean = true): TPromise { + private initializeConfiguration(): TPromise { this.registerConfigurationSchemas(); - this.resetCaches(); - return this.updateConfiguration() - .then(() => { - if (trigger) { - this.triggerConfigurationChange(); - } + return this.loadConfiguration(); + } + + private loadConfiguration(): TPromise { + // reset caches + this.cachedFolderConfigs = new StrictResourceMap>(); + + const folders = this.workspace.folders; + return this.loadFolderConfigurations(folders) + .then((folderConfigurations) => { + + let workspaceConfiguration = this.getWorkspaceConfigurationModel(folderConfigurations); + const folderConfigurationModels = new StrictResourceMap>(); + folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration)); + + this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null + // TODO: compare with old values?? + + const keys = this._configuration.keys(); + this.triggerConfigurationChange([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE); }); } - private resetCaches(): void { - this.cachedFolderConfigs = new StrictResourceMap>(); - this._configuration = new Configuration(this.baseConfigurationService.configuration(), new ConfigurationModel(), new StrictResourceMap>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null - this.initCachesForFolders(this.workspace.folders); - } - - private initCachesForFolders(folders: IWorkspaceFolder[]): void { - for (const folder of folders) { - this.cachedFolderConfigs.set(folder.uri, this._register(new FolderConfiguration(folder.uri, this.workspaceSettingsRootFolder, this.getWorkbenchState() === WorkbenchState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW))); - this.updateFolderConfiguration(folder, new FolderConfigurationModel(new FolderSettingsModel(null), [], ConfigurationScope.RESOURCE), false); + private getWorkspaceConfigurationModel(folderConfigurations: FolderConfigurationModel[]): ConfigurationModel { + switch (this.getWorkbenchState()) { + case WorkbenchState.FOLDER: + return folderConfigurations[0]; + case WorkbenchState.WORKSPACE: + return this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration; + default: + return new ConfigurationModel(); } } - private updateConfiguration(folders: IWorkspaceFolder[] = this.workspace.folders): TPromise { - return TPromise.join([...folders.map(folder => this.cachedFolderConfigs.get(folder.uri).loadConfiguration() - .then(configuration => this.updateFolderConfiguration(folder, configuration, true)))]) - .then(changed => changed.reduce((result, value) => result || value, false)) - .then(changed => this.updateWorkspaceConfiguration(true) || changed); - } - private registerConfigurationSchemas(): void { if (this.workspace) { - - contributionRegistry.registerSchema(defaultSettingsSchemaId, settingsSchema); - contributionRegistry.registerSchema(userSettingsSchemaId, settingsSchema); + const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); + jsonRegistry.registerSchema(defaultSettingsSchemaId, settingsSchema); + jsonRegistry.registerSchema(userSettingsSchemaId, settingsSchema); if (WorkbenchState.WORKSPACE === this.getWorkbenchState()) { - contributionRegistry.registerSchema(workspaceSettingsSchemaId, settingsSchema); - contributionRegistry.registerSchema(folderSettingsSchemaId, resourceSettingsSchema); + jsonRegistry.registerSchema(workspaceSettingsSchemaId, settingsSchema); + jsonRegistry.registerSchema(folderSettingsSchemaId, resourceSettingsSchema); } else { - contributionRegistry.registerSchema(workspaceSettingsSchemaId, settingsSchema); - contributionRegistry.registerSchema(folderSettingsSchemaId, settingsSchema); + jsonRegistry.registerSchema(workspaceSettingsSchemaId, settingsSchema); + jsonRegistry.registerSchema(folderSettingsSchemaId, settingsSchema); } } } - private onBaseConfigurationChanged({ source, sourceConfig }: IConfigurationServiceEvent): void { - if (this.workspace) { - if (source === ConfigurationSource.Default) { + private onBaseConfigurationChanged(e: IConfigurationChangeEvent): void { + if (this.workspace && this._configuration) { + if (e.source === ConfigurationTarget.DEFAULT) { this.workspace.folders.forEach(folder => this._configuration.getFolderConfigurationModel(folder.uri).update()); - } - if (this._configuration.updateBaseConfiguration(this.baseConfigurationService.configuration())) { - this._onDidUpdateConfiguration.fire({ source, sourceConfig }); + this._configuration.updateDefaultConfiguration(this.baseConfigurationService.configuration.defaults); + this._onDidUpdateConfiguration.fire(e); + } else { + let keys = this._configuration.updateUserConfiguration(this.baseConfigurationService.configuration.user); + this.triggerConfigurationChange(keys, e.source); } } } - private onWorkspaceConfigurationChanged(): void { - if (this.workspace && this.workspace.configuration) { + private onWorkspaceConfigurationChanged(): TPromise { + if (this.workspace && this.workspace.configuration && this._configuration) { + const changedWorkspaceKeys = this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration); let configuredFolders = toWorkspaceFolders(this.workspaceConfiguration.workspaceConfigurationModel.folders, URI.file(paths.dirname(this.workspace.configuration.fsPath))); const changes = this.compareFolders(this.workspace.folders, configuredFolders); - if (changes.added.length || changes.removed.length || changes.changed.length) { // TODO@Sandeep be smarter here about detecting changes + if (changes.added.length || changes.removed.length || changes.changed.length) { this.workspace.folders = configuredFolders; - this.onFoldersChanged() - .then(configurationChanged => { - if (configurationChanged) { - this.triggerConfigurationChange(); - } + return this.onFoldersChanged() + .then(changedFolderKeys => { + this.triggerConfigurationChange([...changedFolderKeys, ...changedWorkspaceKeys], ConfigurationTarget.WORKSPACE_FOLDER); this._onDidChangeWorkspaceFolders.fire(changes); }); } else { - const configurationChanged = this.updateWorkspaceConfiguration(true); - if (configurationChanged) { - this.triggerConfigurationChange(); - } + this.triggerConfigurationChange(changedWorkspaceKeys, ConfigurationTarget.WORKSPACE); } } + return TPromise.as(null); } - private onFoldersChanged(): TPromise { - let configurationChangedOnRemoval = false; + private onWorkspaceFileChanges(event: FileChangesEvent): TPromise { + return TPromise.join(this.workspace.folders.map(folder => + // handle file event for each folder + this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event) + // Update folder configuration if handled + .then(folderConfiguration => folderConfiguration ? this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration) : [])) + ).then(changedKeys => this.triggerConfigurationChange(flatten(changedKeys), ConfigurationTarget.WORKSPACE_FOLDER)); + } + + private onSingleFolderFileChanges(event: FileChangesEvent): TPromise { + const folder = this.workspace.folders[0]; + return this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event) + .then(folderConfiguration => { + if (folderConfiguration) { + // File change handled + this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration); + const workspaceChangedKeys = this._configuration.updateWorkspaceConfiguration(folderConfiguration); + this.triggerConfigurationChange(workspaceChangedKeys, ConfigurationTarget.WORKSPACE); + } + }); + } + + private onWorkspaceFolderConfigurationChanged(folder: IWorkspaceFolder, key?: string): TPromise { + this.disposeFolderConfiguration(folder); + return this.loadFolderConfigurations([folder]) + .then(([folderConfiguration]) => { + const folderChangedKeys = this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration); + if (this.getWorkbenchState() === WorkbenchState.FOLDER) { + const workspaceChangedKeys = this._configuration.updateWorkspaceConfiguration(folderConfiguration); + this.triggerConfigurationChange(workspaceChangedKeys, ConfigurationTarget.WORKSPACE); + } else { + this.triggerConfigurationChange(folderChangedKeys, ConfigurationTarget.WORKSPACE_FOLDER); + } + }); + } + + private onFoldersChanged(): TPromise { + let changedKeys = []; // Remove the configurations of deleted folders for (const key of this.cachedFolderConfigs.keys()) { if (!this.workspace.folders.filter(folder => folder.uri.toString() === key.toString())[0]) { this.cachedFolderConfigs.delete(key); - if (this._configuration.deleteFolderConfiguration(key)) { - configurationChangedOnRemoval = true; - } + changedKeys.push(...this._configuration.deleteFolderConfiguration(key)); } } - // Initialize the newly added folders const toInitialize = this.workspace.folders.filter(folder => !this.cachedFolderConfigs.has(folder.uri)); if (toInitialize.length) { - this.initCachesForFolders(toInitialize); - return this.updateConfiguration(toInitialize) - .then(changed => configurationChangedOnRemoval || changed); - } else if (configurationChangedOnRemoval) { - this.updateWorkspaceConfiguration(false); - return TPromise.as(true); + return this.loadFolderConfigurations(toInitialize) + .then(folderConfigurations => { + folderConfigurations.forEach((folderConfiguration, index) => { + changedKeys.push(...this._configuration.updateFolderConfiguration(toInitialize[index].uri, folderConfiguration)); + }); + return changedKeys; + }); } - return TPromise.as(false); + return TPromise.as(changedKeys); } - private updateFolderConfiguration(folder: IWorkspaceFolder, folderConfiguration: FolderConfigurationModel, compare: boolean): boolean { - let configurationChanged = this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration, compare); - if (this.getWorkbenchState() === WorkbenchState.FOLDER) { - // Workspace configuration changed - configurationChanged = this.updateWorkspaceConfiguration(compare) || configurationChanged; - } - return configurationChanged; + private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise[]> { + return TPromise.join([...folders.map(folder => { + const folderConfiguration = new FolderConfiguration(folder.uri, this.workspaceSettingsRootFolder, this.getWorkbenchState() === WorkbenchState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW); + this.cachedFolderConfigs.set(folder.uri, this._register(folderConfiguration)); + return folderConfiguration.loadConfiguration(); + })]); } - private updateWorkspaceConfiguration(compare: boolean): boolean { - const workbennchState = this.getWorkbenchState(); - if (workbennchState === WorkbenchState.EMPTY) { - return false; - } - - const workspaceConfiguration = workbennchState === WorkbenchState.WORKSPACE ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.folders[0].uri); - return this._configuration.updateWorkspaceConfiguration(workspaceConfiguration, compare); + private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides): TPromise { + return this.configurationEditingService.writeConfiguration(this.toEditableConfigurationTarget(target), { key, value }, { scopes: overrides }) + .then(() => { + switch (target) { + case ConfigurationTarget.USER: + return this.reloadUserConfiguration(); + case ConfigurationTarget.WORKSPACE: + return this.reloadWorkspaceConfiguration(); + case ConfigurationTarget.WORKSPACE_FOLDER: + const workspaceFolder = overrides && overrides.resource ? this.workspace.getFolder(overrides.resource) : null; + if (workspaceFolder) { + return this.reloadWorkspaceFolderConfiguration(this.workspace.getFolder(overrides.resource), key); + } + } + return null; + }); } - private triggerConfigurationChange(): void { - if (this.getWorkbenchState() === WorkbenchState.EMPTY) { - this._onDidUpdateConfiguration.fire({ source: ConfigurationSource.User, sourceConfig: this._configuration.user.contents }); - } else { - this._onDidUpdateConfiguration.fire({ source: ConfigurationSource.Workspace, sourceConfig: this.workspace.folders.length ? this._configuration.getFolderConfigurationModel(this.workspace.folders[0].uri).contents : void 0 }); // TODO@Sandeep debt? + private deriveConfigurationTarget(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): ConfigurationTarget { + if (target) { + return target; } + + if (value === void 0) { + // Ignore. But expected is to remove the value from all targets + return void 0; + } + + const inspect = this.inspect(key, overrides); + if (equals(value, inspect.value)) { + // No change. So ignore. + return void 0; + } + + if (inspect.workspaceFolder !== void 0) { + return ConfigurationTarget.WORKSPACE_FOLDER; + } + + if (inspect.workspace !== void 0) { + return ConfigurationTarget.WORKSPACE; + } + + return ConfigurationTarget.USER; + } + + private toEditableConfigurationTarget(target: ConfigurationTarget): EditableConfigurationTarget { + switch (target) { + case ConfigurationTarget.USER: + return EditableConfigurationTarget.USER; + case ConfigurationTarget.WORKSPACE: + return EditableConfigurationTarget.WORKSPACE; + case ConfigurationTarget.WORKSPACE_FOLDER: + return EditableConfigurationTarget.FOLDER; + default: + return EditableConfigurationTarget.WORKSPACE; + } + } + + private triggerConfigurationChange(keys: string[], target: ConfigurationTarget): void { + if (keys.length) { + this._onDidUpdateConfiguration.fire(toConfigurationUpdateEvent(distinct(keys), target, this.getTargetConfiguration(target))); + } + } + + private getTargetConfiguration(target: ConfigurationTarget): any { + switch (target) { + case ConfigurationTarget.DEFAULT: + return this._configuration.defaults.contents; + case ConfigurationTarget.USER: + return this._configuration.user.contents; + case ConfigurationTarget.WORKSPACE: + return this._configuration.workspace.contents; + } + return {}; } private pathEquals(path1: string, path2: string): boolean { @@ -611,6 +548,13 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return path1 === path2; } + + private disposeFolderConfiguration(folder: IWorkspaceFolder): void { + const folderConfiguration = this.cachedFolderConfigs.get(folder.uri); + if (folderConfiguration) { + folderConfiguration.dispose(); + } + } } class WorkspaceConfiguration extends Disposable { @@ -622,7 +566,6 @@ class WorkspaceConfiguration extends Disposable { private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; - load(workspaceConfigPath: URI): TPromise { if (this._workspaceConfigPath && this._workspaceConfigPath.fsPath === workspaceConfigPath.fsPath) { return this._reload(); @@ -852,80 +795,6 @@ function resolveStat(resource: URI): TPromise { }); } -export class Configuration extends BaseConfiguration { - - constructor(private _baseConfiguration: BaseConfiguration, workspaceConfiguration: ConfigurationModel, protected folders: StrictResourceMap>, workspace: Workspace) { - super(_baseConfiguration.defaults, _baseConfiguration.user, workspaceConfiguration, folders, workspace); - } - - updateBaseConfiguration(baseConfiguration: BaseConfiguration): boolean { - const current = new Configuration(this._baseConfiguration, this._workspaceConfiguration, this.folders, this._workspace); - - this._baseConfiguration = baseConfiguration; - this._defaults = this._baseConfiguration.defaults; - this._user = this._baseConfiguration.user; - this.merge(); - - return !this.equals(current); - } - - updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel, compare: boolean = true): boolean { - const current = new Configuration(this._baseConfiguration, this._workspaceConfiguration, this.folders, this._workspace); - - this._workspaceConfiguration = workspaceConfiguration; - this.merge(); - - return compare && !this.equals(current); - } - - updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel, compare: boolean): boolean { - const current = this.getValue(null, { resource }); - - this.folders.set(resource, configuration); - this.mergeFolder(resource); - - return compare && !objects.equals(current, this.getValue(null, { resource })); - } - - deleteFolderConfiguration(folder: URI): boolean { - if (this._workspace && this._workspace.folders.length > 0 && this._workspace.folders[0].uri.toString() === folder.toString()) { - // Do not remove workspace configuration - return false; - } - - const changed = this.folders.get(folder).keys.length > 0; - this.folders.delete(folder); - this._foldersConsolidatedConfigurations.delete(folder); - return changed; - } - - getFolderConfigurationModel(folder: URI): FolderConfigurationModel { - return >this.folders.get(folder); - } - - equals(other: any): boolean { - if (!other || !(other instanceof Configuration)) { - return false; - } - - if (!objects.equals(this.getValue(), other.getValue())) { - return false; - } - - if (this._foldersConsolidatedConfigurations.size !== other._foldersConsolidatedConfigurations.size) { - return false; - } - - for (const resource of this._foldersConsolidatedConfigurations.keys()) { - if (!objects.equals(this.getValue(null, { resource }), other.getValue(null, { resource }))) { - return false; - } - } - - return true; - } -} - interface IExportedConfigurationNode { name: string; description: string; @@ -1019,4 +888,4 @@ function versionStringToNumber(versionStr: string): number { } return parseInt(match[1], 10) * 10000 + parseInt(match[2], 10) * 100 + parseInt(match[3], 10); -} +} \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index 268e832f7db..b486834f14e 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -21,7 +21,7 @@ import extfs = require('vs/base/node/extfs'); import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices'; import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; +import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { FileService } from 'vs/workbench/services/files/node/fileService'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { ConfigurationTarget, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditing'; @@ -228,7 +228,7 @@ suite('ConfigurationEditingService', () => { const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); const parsed = json.parse(contents); assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); - assert.equal(instantiationService.get(IConfigurationService).lookup('configurationEditing.service.testSetting').value, 'value'); + assert.equal(instantiationService.get(IConfigurationService).getValue('configurationEditing.service.testSetting'), 'value'); }); }); @@ -242,8 +242,8 @@ suite('ConfigurationEditingService', () => { assert.equal(parsed['my.super.setting'], 'my.super.value'); const configurationService = instantiationService.get(IConfigurationService); - assert.equal(configurationService.lookup('configurationEditing.service.testSetting').value, 'value'); - assert.equal(configurationService.lookup('my.super.setting').value, 'my.super.value'); + assert.equal(configurationService.getValue('configurationEditing.service.testSetting'), 'value'); + assert.equal(configurationService.getValue('my.super.setting'), 'my.super.value'); }); }); @@ -255,7 +255,7 @@ suite('ConfigurationEditingService', () => { const parsed = json.parse(contents); assert.equal(parsed['service.testSetting'], 'value'); const configurationService = instantiationService.get(IConfigurationService); - assert.equal(configurationService.lookup('tasks.service.testSetting').value, 'value'); + assert.equal(configurationService.getValue('tasks.service.testSetting'), 'value'); }); }); @@ -270,8 +270,8 @@ suite('ConfigurationEditingService', () => { assert.equal(parsed['my.super.setting'], 'my.super.value'); const configurationService = instantiationService.get(IConfigurationService); - assert.equal(configurationService.lookup('launch.service.testSetting').value, 'value'); - assert.equal(configurationService.lookup('launch.my.super.setting').value, 'my.super.value'); + assert.equal(configurationService.getValue('launch.service.testSetting'), 'value'); + assert.equal(configurationService.getValue('launch.my.super.setting'), 'my.super.value'); }); }); diff --git a/src/vs/workbench/services/configuration/test/node/configuration.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts similarity index 90% rename from src/vs/workbench/services/configuration/test/node/configuration.test.ts rename to src/vs/workbench/services/configuration/test/node/configurationService.test.ts index 8073bb82a98..c6fb36f60c9 100644 --- a/src/vs/workbench/services/configuration/test/node/configuration.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -19,7 +19,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv'; import extfs = require('vs/base/node/extfs'); import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; +import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; @@ -167,7 +167,7 @@ suite('WorkspaceConfigurationService - Node', () => { return createService(workspaceDir, globalSettingsFile).then(service => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); - service.reloadConfiguration().then(() => { + service.reloadConfiguration(service.getWorkspace().folders[0]).then(() => { const config = service.getConfiguration<{ testworkbench: { editor: { tabs: boolean } } }>(); assert.equal(config.testworkbench.editor.tabs, true); @@ -197,7 +197,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": false }'); // this has to trigger the event since the config changes - service.reloadConfiguration().done(); + service.reloadUserConfiguration().done(); }); }); @@ -229,7 +229,7 @@ suite('WorkspaceConfigurationService - Node', () => { return createService(workspaceDir, globalSettingsFile).then(service => { fs.writeFileSync(globalSettingsFile, '{ "workspace.service.testSetting": "isChanged" }'); - service.reloadConfiguration().then(() => { + service.reloadUserConfiguration().then(() => { const config = service.getConfiguration(); assert.equal(config.workspace.service.testSetting, 'isChanged'); @@ -246,7 +246,7 @@ suite('WorkspaceConfigurationService - Node', () => { return createService(workspaceDir, globalSettingsFile).then(service => { fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); - service.reloadConfiguration().then(() => { + service.reloadWorkspaceConfiguration().then(() => { const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean } } }>(); assert.equal(config.testworkbench.editor.icons, true); @@ -264,7 +264,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.icons": false, "testworkbench.other.setting": true }'); fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); - service.reloadConfiguration().then(() => { + service.reloadWorkspaceConfiguration().then(() => { const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean }, other: { setting: string } } }>(); assert.equal(config.testworkbench.editor.icons, true); assert.equal(config.testworkbench.other.setting, true); @@ -310,7 +310,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": false }'); - service.reloadConfiguration().done(() => { + service.reloadWorkspaceConfiguration().done(() => { assert.ok(target.calledOnce); service.dispose(); @@ -326,11 +326,11 @@ suite('WorkspaceConfigurationService - Node', () => { const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": true }'); - service.reloadConfiguration().done(() => { + service.reloadWorkspaceConfiguration().done(() => { const target = sinon.stub(); service.onDidUpdateConfiguration(event => target()); - service.reloadConfiguration().done(() => { + service.reloadWorkspaceConfiguration().done(() => { assert.ok(!target.called); service.dispose(); @@ -346,7 +346,7 @@ suite('WorkspaceConfigurationService - Node', () => { return createService(workspaceDir, globalSettingsFile).then(service => { const target = sinon.stub(); service.onDidUpdateConfiguration(event => target()); - service.reloadConfiguration().done(() => { + service.reloadUserConfiguration().done(() => { assert.ok(!target.called); service.dispose(); cleanUp(done); @@ -371,13 +371,13 @@ suite('WorkspaceConfigurationService - Node', () => { createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { return createService(workspaceDir, globalSettingsFile).then(service => { - let res = service.lookup('something.missing'); + let res = service.inspect('something.missing'); assert.ok(!res.default); assert.ok(!res.user); assert.ok(!res.workspace); assert.ok(!res.value); - res = service.lookup('workspaceLookup.service.testSetting'); + res = service.inspect('workspaceLookup.service.testSetting'); assert.equal(res.default, 'isSet'); assert.equal(res.value, 'isSet'); assert.ok(!res.user); @@ -385,8 +385,8 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(globalSettingsFile, '{ "workspaceLookup.service.testSetting": true }'); - return service.reloadConfiguration().then(() => { - res = service.lookup('workspaceLookup.service.testSetting'); + return service.reloadUserConfiguration().then(() => { + res = service.inspect('workspaceLookup.service.testSetting'); assert.equal(res.default, 'isSet'); assert.equal(res.user, true); assert.equal(res.value, true); @@ -395,8 +395,8 @@ suite('WorkspaceConfigurationService - Node', () => { const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.testSetting": 55 }'); - return service.reloadConfiguration().then(() => { - res = service.lookup('workspaceLookup.service.testSetting'); + return service.reloadWorkspaceConfiguration().then(() => { + res = service.inspect('workspaceLookup.service.testSetting'); assert.equal(res.default, 'isSet'); assert.equal(res.user, true); assert.equal(res.workspace, 55); @@ -444,7 +444,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(globalSettingsFile, '{ "workspaceLookup.service.testSetting": true }'); - return service.reloadConfiguration().then(() => { + return service.reloadUserConfiguration().then(() => { keys = service.keys(); assert.ok(contains(keys.default, 'workspaceLookup.service.testSetting')); @@ -454,7 +454,7 @@ suite('WorkspaceConfigurationService - Node', () => { const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.testSetting": 55 }'); - return service.reloadConfiguration().then(() => { + return service.reloadWorkspaceConfiguration().then(() => { keys = service.keys(); assert.ok(contains(keys.default, 'workspaceLookup.service.testSetting')); @@ -464,7 +464,7 @@ suite('WorkspaceConfigurationService - Node', () => { const settingsFile = path.join(workspaceDir, '.vscode', 'tasks.json'); fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.taskTestSetting": 55 }'); - return service.reloadConfiguration().then(() => { + return service.reloadWorkspaceConfiguration().then(() => { keys = service.keys(); assert.ok(!contains(keys.default, 'tasks.workspaceLookup.service.taskTestSetting')); @@ -496,31 +496,31 @@ suite('WorkspaceConfigurationService - Node', () => { createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { return createService(workspaceDir, globalSettingsFile).then(service => { - let values = service.values(); - let value = values['workspaceLookup.service.testSetting']; + let values = service.inspect('workspaceLookup.service.testSetting'); + let value = values.value; assert.ok(value); - assert.equal(value.default, 'isSet'); + assert.equal(values.default, 'isSet'); fs.writeFileSync(globalSettingsFile, '{ "workspaceLookup.service.testSetting": true }'); - return service.reloadConfiguration().then(() => { - values = service.values(); - value = values['workspaceLookup.service.testSetting']; + return service.reloadUserConfiguration().then(() => { + values = service.inspect('workspaceLookup.service.testSetting'); + value = values.value; assert.ok(value); - assert.equal(value.user, true); + assert.equal(values.user, true); const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.testSetting": 55 }'); - return service.reloadConfiguration().then(() => { - values = service.values(); - value = values['workspaceLookup.service.testSetting']; + return service.reloadWorkspaceConfiguration().then(() => { + values = service.inspect('workspaceLookup.service.testSetting'); + value = values.value; assert.ok(value); - assert.equal(value.user, true); - assert.equal(value.workspace, 55); + assert.equal(values.user, true); + assert.equal(values.workspace, 55); done(); }); diff --git a/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts index 7841abf9606..2360f632988 100644 --- a/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts @@ -7,7 +7,7 @@ import assert = require('assert'); import uri from 'vs/base/common/uri'; import platform = require('vs/base/common/platform'); import { TPromise } from 'vs/base/common/winjs.base'; -import { IConfigurationService, getConfigurationValue, IConfigurationOverrides, IConfigurationValue } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, getConfigurationValue, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/node/configurationResolverService'; @@ -348,13 +348,14 @@ class MockConfigurationService implements IConfigurationService { public _serviceBrand: any; public serviceId = IConfigurationService; public constructor(private configuration: any = {}) { } - public reloadConfiguration(section?: string): TPromise { return TPromise.as(this.getConfiguration()); } - public lookup(key: string, overrides?: IConfigurationOverrides): IConfigurationValue { return { value: getConfigurationValue(this.getConfiguration(), key), default: getConfigurationValue(this.getConfiguration(), key), user: getConfigurationValue(this.getConfiguration(), key), workspace: void 0, folder: void 0 }; } - public keys() { return { default: [], user: [], workspace: [], folder: [] }; } - public values() { return {}; } + public inspect(key: string, overrides?: IConfigurationOverrides): any { return { value: getConfigurationValue(this.getConfiguration(), key), default: getConfigurationValue(this.getConfiguration(), key), user: getConfigurationValue(this.getConfiguration(), key), workspaceFolder: void 0, folder: void 0 }; } + public keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; } public getConfiguration(): any { return this.configuration; } + public getValue(key: string): any { return getConfigurationValue(this.getConfiguration(), key); } + public updateValue(): TPromise { return null; } public getConfigurationData(): any { return null; } public onDidUpdateConfiguration() { return { dispose() { } }; } + public reloadConfiguration() { return null; } } class MockCommandService implements ICommandService { diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index d4b17a7fbc3..553e69ad627 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -360,7 +360,7 @@ export class ExtensionHostProcessWorker { }, workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace(), extensions: extensionDescriptions, - configuration: this._configurationService.getConfigurationData(), + configuration: this._configurationService.getConfiguration(), telemetryInfo }; return r; diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 7fb9b9a90c8..7d1e3e4382f 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -344,8 +344,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.updateColorCustomizations(false); - let colorThemeSetting = this.configurationService.lookup(COLOR_THEME_SETTING).value; - let iconThemeSetting = this.configurationService.lookup(ICON_THEME_SETTING).value || ''; + let colorThemeSetting = this.configurationService.getValue(COLOR_THEME_SETTING); + let iconThemeSetting = this.configurationService.getValue(ICON_THEME_SETTING) || ''; return Promise.join([ this.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID).then(theme => { @@ -359,7 +359,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { private installConfigurationListener() { this.configurationService.onDidUpdateConfiguration(e => { - let colorThemeSetting = this.configurationService.lookup(COLOR_THEME_SETTING).value; + let colorThemeSetting = this.configurationService.getValue(COLOR_THEME_SETTING); if (colorThemeSetting !== this.currentColorTheme.settingsId) { this.findThemeDataBySettingsId(colorThemeSetting, null).then(theme => { if (theme) { @@ -368,7 +368,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { }); } - let iconThemeSetting = this.configurationService.lookup(ICON_THEME_SETTING).value || ''; + let iconThemeSetting = this.configurationService.getValue(ICON_THEME_SETTING) || ''; if (iconThemeSetting !== this.currentIconTheme.settingsId) { this.findIconThemeBySettingsId(iconThemeSetting).then(theme => { this.setFileIconTheme(theme && theme.id, null); @@ -530,14 +530,14 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } private updateColorCustomizations(notify = true): void { - let newColorCustomizations = this.configurationService.lookup(CUSTOM_WORKBENCH_COLORS_SETTING).value || {}; + let newColorCustomizations = this.configurationService.getValue(CUSTOM_WORKBENCH_COLORS_SETTING) || {}; let newColorIds = Object.keys(newColorCustomizations); if (newColorIds.length === 0) { - newColorCustomizations = this.configurationService.lookup(DEPRECATED_CUSTOM_COLORS_SETTING).value || {}; + newColorCustomizations = this.configurationService.getValue(DEPRECATED_CUSTOM_COLORS_SETTING) || {}; newColorIds = Object.keys(newColorCustomizations); } - let newTokenColorCustomizations = this.configurationService.lookup(CUSTOM_EDITOR_COLORS_SETTING).value || {}; + let newTokenColorCustomizations = this.configurationService.getValue(CUSTOM_EDITOR_COLORS_SETTING) || {}; if (this.hasCustomizationChanged(newColorCustomizations, newColorIds, newTokenColorCustomizations)) { this.colorCustomizations = newColorCustomizations; @@ -962,7 +962,7 @@ class ConfigurationWriter { } public writeConfiguration(key: string, value: any, settingsTarget: ConfigurationTarget): TPromise { - let settings = this.configurationService.lookup(key); + let settings = this.configurationService.inspect(key); if (settingsTarget === ConfigurationTarget.USER) { if (value === settings.user) { return TPromise.as(null); // nothing to do diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index aa99ca9f75a..ea53130e9cb 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -17,7 +17,7 @@ import { dirname } from 'path'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces'; import { isLinux } from 'vs/base/common/platform'; -import { WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; +import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { migrateStorageToMultiRootWorkspace } from 'vs/platform/storage/common/migration'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { StorageService } from 'vs/platform/storage/common/storageService'; @@ -187,7 +187,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { const targetWorkspaceConfiguration = {}; for (const key of this.workspaceConfigurationService.keys().workspace) { if (configurationProperties[key] && !configurationProperties[key].isFromExtensions && configurationProperties[key].scope === ConfigurationScope.WINDOW) { - targetWorkspaceConfiguration[key] = this.workspaceConfigurationService.lookup(key).workspace; + targetWorkspaceConfiguration[key] = this.workspaceConfigurationService.inspect(key).workspace; } } diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index b162fb6a023..4844c81d0aa 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -9,6 +9,9 @@ import 'vs/base/common/strings'; import 'vs/base/common/errors'; +// Configuration +import 'vs/workbench/services/configuration/common/configurationExtensionPoint'; + // Editor import 'vs/editor/editor.all'; From 74e07a6f1cd24cd9a342056096b2d3d7d2a648e1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 5 Oct 2017 23:22:55 +0200 Subject: [PATCH 017/394] Populate register configuration event correctly --- src/vs/platform/configuration/common/configurationRegistry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 83d78eda6da..11f9f2cd686 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -114,9 +114,9 @@ class ConfigurationRegistry implements IConfigurationRegistry { } public registerConfigurations(configurations: IConfigurationNode[], validate: boolean = true): void { - const properties = []; + const properties: string[] = []; configurations.forEach(configuration => { - properties.push(this.validateAndRegisterProperties(configuration, validate)); // fills in defaults + properties.push(...this.validateAndRegisterProperties(configuration, validate)); // fills in defaults this.configurationContributors.push(configuration); this.registerJSONConfiguration(configuration); this.updateSchemaForOverrideSettingsConfiguration(configuration); From e1c29b6188971db4d294b05a71984c645f4d759c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 5 Oct 2017 23:30:34 +0200 Subject: [PATCH 018/394] Populate override identifer keys in the event correctly --- src/vs/platform/configuration/common/configuration.ts | 10 +++++++++- src/vs/platform/configuration/common/model.ts | 10 +--------- .../parts/preferences/browser/preferencesRenderers.ts | 2 +- .../configuration/node/configurationEditingService.ts | 3 +-- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 20f1b668201..19bcce38e70 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -78,12 +78,20 @@ export interface IConfigurationService { }; } +export function overrideIdentifierFromKey(key: string): string { + return key.substring(1, key.length - 1); +} + +export function keyFromOverrideIdentifier(overrideIdentifier: string): string { + return `[${overrideIdentifier}]`; +} + export function toConfigurationUpdateEvent(udpated: string[], source: ConfigurationTarget, sourceConfig: any): IConfigurationChangeEvent { const overrideIdentifiers = []; const keys: string[] = []; for (const key of udpated) { if (OVERRIDE_PROPERTY_PATTERN.test(key)) { - overrideIdentifiers.push(key); + overrideIdentifiers.push(overrideIdentifierFromKey(key).trim()); } else { keys.push(key); } diff --git a/src/vs/platform/configuration/common/model.ts b/src/vs/platform/configuration/common/model.ts index 53b122efd0e..2eca51661ff 100644 --- a/src/vs/platform/configuration/common/model.ts +++ b/src/vs/platform/configuration/common/model.ts @@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import * as json from 'vs/base/common/json'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { ConfigurationModel, IOverrides } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationModel, IOverrides, overrideIdentifierFromKey } from 'vs/platform/configuration/common/configuration'; export function getDefaultValues(): any { const valueTreeRoot: any = Object.create(null); @@ -191,12 +191,4 @@ export class CustomConfigurationModel extends ConfigurationModel { this._contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)); this._keys = Object.keys(raw); } -} - -export function overrideIdentifierFromKey(key: string): string { - return key.substring(1, key.length - 1); -} - -export function keyFromOverrideIdentifier(overrideIdentifier: string): string { - return `[${overrideIdentifier}]`; } \ No newline at end of file diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index e3491f2e20a..98996425277 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -24,7 +24,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RangeHighlightDecorations } from 'vs/workbench/common/editor/rangeDecorations'; import { IConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { overrideIdentifierFromKey } from 'vs/platform/configuration/common/model'; import { IMarkerService, IMarkerData } from 'vs/platform/markers/common/markers'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IMessageService, Severity } from 'vs/platform/message/common/message'; @@ -33,6 +32,7 @@ import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorE import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { MarkdownString } from 'vs/base/common/htmlContent'; +import { overrideIdentifierFromKey } from 'vs/platform/configuration/common/configuration'; export interface IPreferencesRenderer extends IDisposable { preferencesModel: IPreferencesEditorModel; diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 694c6122734..b264dbd9662 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -23,8 +23,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { IConfigurationService, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; -import { keyFromOverrideIdentifier } from 'vs/platform/configuration/common/model'; +import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier } from 'vs/platform/configuration/common/configuration'; import { WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; import { ConfigurationTarget, ConfigurationEditingErrorCode, ConfigurationEditingError, IConfigurationValue, IConfigurationEditingOptions, IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; From 2a8be527e5a773d3bd01ce1c274cdb2cf5138fc4 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 5 Oct 2017 23:41:20 +0200 Subject: [PATCH 019/394] :lipstick: --- src/vs/platform/configuration/common/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 19bcce38e70..43da9ac3cfb 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -60,7 +60,7 @@ export interface IConfigurationService { updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise; reloadConfiguration(): TPromise; - reloadConfiguration(folder?: IWorkspaceFolder): TPromise; + reloadConfiguration(folder: IWorkspaceFolder): TPromise; inspect(key: string): { default: T, From 7f89b24319054ae22758d046ef33f0b78c5650cc Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 5 Oct 2017 23:50:44 +0200 Subject: [PATCH 020/394] Fix usage of getConfiguration --- src/vs/editor/common/services/modelServiceImpl.ts | 2 +- .../workbench/api/electron-browser/mainThreadWorkspace.ts | 2 +- src/vs/workbench/parts/files/browser/views/explorerView.ts | 2 +- .../workbench/parts/files/browser/views/explorerViewer.ts | 2 +- src/vs/workbench/parts/search/common/queryBuilder.ts | 6 +++--- .../services/files/node/watcher/nsfw/watcherService.ts | 2 +- src/vs/workbench/services/history/browser/history.ts | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 7eb325a6761..fe046a165d5 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -272,7 +272,7 @@ export class ModelServiceImpl implements IModelService { public getCreationOptions(language: string, resource: URI): editorCommon.ITextModelCreationOptions { let creationOptions = this._modelCreationOptionsByLanguageAndResource[language + resource]; if (!creationOptions) { - creationOptions = ModelServiceImpl._readModelOptions(this._configurationService.getConfiguration(null, { overrideIdentifier: language, resource })); + creationOptions = ModelServiceImpl._readModelOptions(this._configurationService.getConfiguration({ overrideIdentifier: language, resource })); this._modelCreationOptionsByLanguageAndResource[language + resource] = creationOptions; } return creationOptions; diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 69d00f909db..69e09705743 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -68,7 +68,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { } const useRipgrep = folderQueries.every(folderQuery => { - const folderConfig = this._configurationService.getConfiguration(undefined, { resource: folderQuery.folder }); + const folderConfig = this._configurationService.getConfiguration({ resource: folderQuery.folder }); return folderConfig.search.useRipgrep; }); diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 1a84751abf2..9db721ab8b4 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -120,7 +120,7 @@ export class ExplorerView extends ViewsViewletPanel { private getFileEventsExcludes(root?: URI): glob.IExpression { const scope = root ? { resource: root } : void 0; - const configuration = this.configurationService.getConfiguration(undefined, scope); + const configuration = this.configurationService.getConfiguration(scope); return (configuration && configuration.files && configuration.files.exclude) || Object.create(null); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index c088be1988d..329a15b0bf9 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -687,7 +687,7 @@ export class FileFilter implements IFilter { public updateConfiguration(): boolean { let needsRefresh = false; this.contextService.getWorkspace().folders.forEach(folder => { - const configuration = this.configurationService.getConfiguration(undefined, { resource: folder.uri }); + const configuration = this.configurationService.getConfiguration({ resource: folder.uri }); const excludesConfig = (configuration && configuration.files && configuration.files.exclude) || Object.create(null); needsRefresh = needsRefresh || !objects.equals(this.hiddenExpressionPerRoot.get(folder.uri.toString()), excludesConfig); this.hiddenExpressionPerRoot.set(folder.uri.toString(), objects.clone(excludesConfig)); // do not keep the config, as it gets mutated under our hoods diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index 9b3120dcdc6..cf614eeaeb0 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -56,7 +56,7 @@ export class QueryBuilder { } const useRipgrep = !folderResources || folderResources.every(folder => { - const folderConfig = this.configurationService.getConfiguration(undefined, { resource: folder }); + const folderConfig = this.configurationService.getConfiguration({ resource: folder }); return folderConfig.search.useRipgrep; }); @@ -244,7 +244,7 @@ export class QueryBuilder { private getFolderQueryForSearchPath(searchPath: ISearchPathPattern): IFolderQuery { const folder = searchPath.searchPath; - const folderConfig = this.configurationService.getConfiguration(undefined, { resource: folder }); + const folderConfig = this.configurationService.getConfiguration({ resource: folder }); return { folder, includePattern: searchPath.pattern && patternListToIExpression([searchPath.pattern]), @@ -253,7 +253,7 @@ export class QueryBuilder { } private getFolderQueryForRoot(folder: uri, options?: IQueryOptions): IFolderQuery { - const folderConfig = this.configurationService.getConfiguration(undefined, { resource: folder }); + const folderConfig = this.configurationService.getConfiguration({ resource: folder }); return { folder, excludePattern: this.getExcludesForFolder(folderConfig, options), diff --git a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts index 9e3744b2638..05a68b0cb7a 100644 --- a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts @@ -95,7 +95,7 @@ export class FileWatcher { this.service.setRoots(this.contextService.getWorkspace().folders.map(folder => { // Fetch the root's watcherExclude setting and return it - const configuration = this.configurationService.getConfiguration(undefined, { + const configuration = this.configurationService.getConfiguration({ resource: folder.uri }); let ignored: string[] = []; diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index f9fafed499d..1a0c498f2dc 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -224,7 +224,7 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic private getExcludes(root?: URI): IExpression { const scope = root ? { resource: root } : void 0; - return getExcludes(this.configurationService.getConfiguration(void 0, scope)); + return getExcludes(this.configurationService.getConfiguration(scope)); } private registerListeners(): void { From 878233682f1f2798ac42a349fc0f194e2fe4678c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 00:36:54 +0200 Subject: [PATCH 021/394] Watermark: Adopt to new configuration update event. Check if key has changed. --- .../watermark/electron-browser/watermark.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 21c46e71bdd..effbdb62019 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -100,6 +100,7 @@ const folderEntries = [ ]; const UNBOUND = nls.localize('watermark.unboundCommand', "unbound"); +const WORKBENCH_TIPS_ENABLED_KEY = 'workbench.tips.enabled'; export class WatermarkContribution implements IWorkbenchContribution { @@ -120,19 +121,21 @@ export class WatermarkContribution implements IWorkbenchContribution { lifecycleService.onShutdown(this.dispose, this); this.partService.joinCreation().then(() => { - this.enabled = this.configurationService.getValue('workbench.tips.enabled'); + this.enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); if (this.enabled) { this.create(); } }); this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - const enabled = this.configurationService.getValue('workbench.tips.enabled'); - if (enabled !== this.enabled) { - this.enabled = enabled; - if (this.enabled) { - this.create(); - } else { - this.destroy(); + if (e.hasKeyChanged(WORKBENCH_TIPS_ENABLED_KEY)) { + const enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); + if (enabled !== this.enabled) { + this.enabled = enabled; + if (this.enabled) { + this.create(); + } else { + this.destroy(); + } } } })); From 3a399200f285370b363c003904bb7d26bdad57f7 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 6 Oct 2017 09:58:38 +0200 Subject: [PATCH 022/394] smoke: simplify screenshots, artifacts --- build/tfs/darwin/build.sh | 8 ++--- build/tfs/linux/build.sh | 17 ++++------- build/tfs/win32/1_build.ps1 | 9 ++---- build/tfs/win32/build_unsigned.ps1 | 9 ++---- test/smoke/src/areas/css/css.test.ts | 1 - test/smoke/src/areas/debug/debug.test.ts | 1 - test/smoke/src/areas/editor/editor.test.ts | 1 - .../smoke/src/areas/explorer/explorer.test.ts | 1 - .../src/areas/extensions/extensions.test.ts | 1 - test/smoke/src/areas/git/git.test.ts | 1 - .../src/areas/multiroot/multiroot.test.ts | 4 +-- .../src/areas/preferences/preferences.test.ts | 1 - test/smoke/src/areas/search/search.test.ts | 1 - .../src/areas/statusbar/statusbar.test.ts | 1 - .../smoke/src/areas/terminal/terminal.test.ts | 1 - test/smoke/src/areas/window.ts | 18 ------------ .../src/areas/workbench/data-loss.test.ts | 1 - .../areas/workbench/data-migration.test.ts | 6 ---- .../src/areas/workbench/localization.test.ts | 1 - test/smoke/src/helpers/screenshot.ts | 20 +++++-------- test/smoke/src/helpers/utilities.ts | 4 +++ test/smoke/src/main.ts | 8 ++--- test/smoke/src/spectron/application.ts | 29 +++++++++++++------ 23 files changed, 49 insertions(+), 95 deletions(-) delete mode 100644 test/smoke/src/areas/window.ts diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index 2d84a8be12a..bc4eb2aca16 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -38,12 +38,10 @@ step "Run integration tests" \ ./scripts/test-integration.sh function smoketest { - SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" - LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" - rm -rf $SCREENSHOTS $LOGS - mkdir -p $SCREENSHOTS $LOGS + ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" + rm -rf $ARTIFACTS - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS --logs $LOGS + npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --debug $ARTIFACTS } step "Run smoke test" \ diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 8118c2a2d2f..426baf55915 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -40,21 +40,16 @@ step "Run unit tests" \ ./scripts/test.sh --build --reporter dot function smoketest { - SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" - rm -rf $SCREENSHOTS - mkdir -p $SCREENSHOTS - - LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" - rm -rf $LOGS - mkdir -p $LOGS - id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' - chown -R testuser $SCREENSHOTS - chown -R testuser $LOGS + + ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" + rm -rf $ARTIFACTS + mkdir -p $ARTIFACTS + chown -R testuser $ARTIFACTS ps -o pid= -u testuser | xargs sudo kill -9 - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --screenshots $SCREENSHOTS --logs $LOGS" + DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --debug $ARTIFACTS" # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32" } diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1 index 9c913f7446a..aa7a77d6f93 100644 --- a/build/tfs/win32/1_build.ps1 +++ b/build/tfs/win32/1_build.ps1 @@ -53,13 +53,10 @@ step "Run unit tests" { # } step "Run smoke test" { - $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" - Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots + $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts" + Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts - $Logs = "$env:AGENT_BUILDDIRECTORY\smoketest-logs" - Remove-Item -Recurse -Force -ErrorAction Ignore $Logs - - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" --logs "$Logs" } + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --debug "$Artifacts" } } done diff --git a/build/tfs/win32/build_unsigned.ps1 b/build/tfs/win32/build_unsigned.ps1 index 68c0acd3183..9d980ea304a 100644 --- a/build/tfs/win32/build_unsigned.ps1 +++ b/build/tfs/win32/build_unsigned.ps1 @@ -48,13 +48,10 @@ step "Run unit tests" { } step "Run smoke test" { - $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" - Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots + $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts" + Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts - $Logs = "$env:AGENT_BUILDDIRECTORY\smoketest-logs" - Remove-Item -Recurse -Force -ErrorAction Ignore $Logs - - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" --logs "$Logs" } + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --debug "$Artifacts" } } step "Create archive and setup package" { diff --git a/test/smoke/src/areas/css/css.test.ts b/test/smoke/src/areas/css/css.test.ts index e49b90b9551..7b064431e0a 100644 --- a/test/smoke/src/areas/css/css.test.ts +++ b/test/smoke/src/areas/css/css.test.ts @@ -11,7 +11,6 @@ describe('CSS', () => { let app: SpectronApplication; before(function () { app = new SpectronApplication(); return app.start('CSS'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('verifies quick outline', async () => { await app.workbench.quickopen.openFile('style.css'); diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 379bb46df85..5c7a759eb40 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -42,7 +42,6 @@ describe('Debug', () => { // otherwise concurrent test runs will clash on those ports before(async () => await app.start('Debug', [], { PORT: String(await findFreePort()), ...process.env })); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('configure launch json', async function () { await app.workbench.debug.openDebugViewlet(); diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index 896884c044d..38634bb5a92 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -11,7 +11,6 @@ describe('Editor', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Editor'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('shows correct quick outline', async function () { await app.workbench.quickopen.openFile('www'); diff --git a/test/smoke/src/areas/explorer/explorer.test.ts b/test/smoke/src/areas/explorer/explorer.test.ts index 665b525a9f2..658be5959b7 100644 --- a/test/smoke/src/areas/explorer/explorer.test.ts +++ b/test/smoke/src/areas/explorer/explorer.test.ts @@ -9,7 +9,6 @@ describe('Explorer', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Explorer'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('quick open search produces correct result', async function () { const expectedNames = [ diff --git a/test/smoke/src/areas/extensions/extensions.test.ts b/test/smoke/src/areas/extensions/extensions.test.ts index 11b11538fff..316d0a2a72c 100644 --- a/test/smoke/src/areas/extensions/extensions.test.ts +++ b/test/smoke/src/areas/extensions/extensions.test.ts @@ -10,7 +10,6 @@ describe('Extensions', () => { let app: SpectronApplication = new SpectronApplication(); before(() => app.start('Extensions')); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); if (app.build !== VSCODE_BUILD.DEV) { it(`install and activate vscode-smoketest-check extension`, async function () { diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index 1bf9f78b609..73d5d99f5e2 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -14,7 +14,6 @@ describe('Git', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Git'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('reflects working tree changes', async function () { await app.workbench.scm.openSCMViewlet(); diff --git a/test/smoke/src/areas/multiroot/multiroot.test.ts b/test/smoke/src/areas/multiroot/multiroot.test.ts index 839e2848d42..92c50c070e7 100644 --- a/test/smoke/src/areas/multiroot/multiroot.test.ts +++ b/test/smoke/src/areas/multiroot/multiroot.test.ts @@ -5,7 +5,6 @@ import * as assert from 'assert'; import { SpectronApplication, CODE_WORKSPACE_PATH, VSCODE_BUILD } from '../../spectron/application'; -import { Window } from '../window'; describe('Multiroot', () => { let app: SpectronApplication = new SpectronApplication(void 0, CODE_WORKSPACE_PATH); @@ -15,7 +14,6 @@ describe('Multiroot', () => { before(() => app.start('Multi Root')); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('shows results from all folders', async function () { await app.workbench.quickopen.openQuickOpen(); @@ -26,7 +24,7 @@ describe('Multiroot', () => { }); it('shows workspace name in title', async function () { - const title = await new Window(app).getTitle(); + const title = await app.client.getTitle(); await app.screenCapturer.capture('window title'); assert.ok(title.indexOf('smoketest (Workspace)') >= 0); }); diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index 5239518928d..3074be7fd47 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -12,7 +12,6 @@ describe('Preferences', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Preferences'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('turns off editor line numbers and verifies the live change', async function () { await app.workbench.explorer.openFile('app.js'); diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index 83adb28fd08..5c0a7f46cd3 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -9,7 +9,6 @@ describe('Search', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Search'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('searches for body & checks for correct result number', async function () { await app.workbench.search.openSearchViewlet(); diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 0d141465514..70d91d1557f 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -13,7 +13,6 @@ describe('Statusbar', () => { let app: SpectronApplication = new SpectronApplication(); before(() => app.start('Statusbar')); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it('verifies presence of all default status bar elements', async function () { await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.BRANCH_STATUS); diff --git a/test/smoke/src/areas/terminal/terminal.test.ts b/test/smoke/src/areas/terminal/terminal.test.ts index 70fa2f3f4b3..de81c0dbed2 100644 --- a/test/smoke/src/areas/terminal/terminal.test.ts +++ b/test/smoke/src/areas/terminal/terminal.test.ts @@ -9,7 +9,6 @@ describe('Terminal', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Terminal'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it(`opens terminal, runs 'echo' and verifies the output`, async function () { const expected = new Date().getTime().toString(); diff --git a/test/smoke/src/areas/window.ts b/test/smoke/src/areas/window.ts deleted file mode 100644 index 69182b4e537..00000000000 --- a/test/smoke/src/areas/window.ts +++ /dev/null @@ -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. - *--------------------------------------------------------------------------------------------*/ - -import { SpectronApplication } from '../spectron/application'; - -export class Window { - - constructor(private spectron: SpectronApplication) { - - } - - public async getTitle(): Promise { - return this.spectron.client.getTitle(); - } - -} diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index d270deaeef7..68d7dd1b377 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -9,7 +9,6 @@ describe('Dataloss', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Dataloss'); }); after(() => app.stop()); - beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); it(`verifies that 'hot exit' works for dirty files`, async function () { await app.workbench.newUntitledFile(); diff --git a/test/smoke/src/areas/workbench/data-migration.test.ts b/test/smoke/src/areas/workbench/data-migration.test.ts index 8bb19bbd53d..cb217fc46be 100644 --- a/test/smoke/src/areas/workbench/data-migration.test.ts +++ b/test/smoke/src/areas/workbench/data-migration.test.ts @@ -23,7 +23,6 @@ describe('Data Migration', () => { // Setting up stable version let app = new SpectronApplication(STABLE_PATH); await app.start('Data Migration'); - app.screenCapturer.testName = 'Untitled is restorted'; await app.workbench.newUntitledFile(); await app.workbench.editor.waitForTypeInEditor('Untitled-1', textToType); @@ -34,7 +33,6 @@ describe('Data Migration', () => { app = new SpectronApplication(LATEST_PATH); await app.start('Data Migration'); - app.screenCapturer.testName = 'Untitled is restorted'; assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`); @@ -50,7 +48,6 @@ describe('Data Migration', () => { let app = new SpectronApplication(STABLE_PATH, fileName); await Util.removeFile(`${fileName}`); await app.start('Data Migration'); - app.screenCapturer.testName = 'Newly created dirty file is restorted'; await app.workbench.waitForActiveTab(fileName); await app.client.type(firstTextPart); @@ -63,7 +60,6 @@ describe('Data Migration', () => { // Checking latest version for the restored state app = new SpectronApplication(LATEST_PATH); await app.start('Data Migration'); - app.screenCapturer.testName = 'Newly created dirty file is restorted'; const filename = fileName.split('/')[1]; assert.ok(await app.workbench.waitForActiveTab(filename), `Untitled-1 tab is not present after migration.`); @@ -76,7 +72,6 @@ describe('Data Migration', () => { const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md'; let app = new SpectronApplication(STABLE_PATH); await app.start('Data Migration'); - app.screenCapturer.testName = 'Opened tabs are restored'; await app.workbench.quickopen.openFile(fileName1); await app.workbench.quickopen.openFile(fileName2); @@ -85,7 +80,6 @@ describe('Data Migration', () => { app = new SpectronApplication(LATEST_PATH); await app.start('Data Migration'); - app.screenCapturer.testName = 'Opened tabs are restored'; assert.ok(await app.workbench.waitForTab(fileName1), `${fileName1} tab was not restored after migration.`); assert.ok(await app.workbench.waitForTab(fileName2), `${fileName2} tab was not restored after migration.`); diff --git a/test/smoke/src/areas/workbench/localization.test.ts b/test/smoke/src/areas/workbench/localization.test.ts index ebed884c5ed..059eb5415de 100644 --- a/test/smoke/src/areas/workbench/localization.test.ts +++ b/test/smoke/src/areas/workbench/localization.test.ts @@ -17,7 +17,6 @@ describe('Localization', () => { it(`starts with 'DE' locale and verifies title and viewlets text is in German`, async function () { await app.start('Localization', ['--locale=DE']); - app.screenCapturer.testName = 'DE locale test'; let text = await app.workbench.explorer.getOpenEditorsViewTitle(); await app.screenCapturer.capture('Open editors title'); diff --git a/test/smoke/src/helpers/screenshot.ts b/test/smoke/src/helpers/screenshot.ts index 289e600b728..4a398321c82 100644 --- a/test/smoke/src/helpers/screenshot.ts +++ b/test/smoke/src/helpers/screenshot.ts @@ -5,35 +5,29 @@ import * as path from 'path'; import * as fs from 'fs'; -import * as mkdirp from 'mkdirp'; import { Application } from 'spectron'; -import { SCREENSHOTS_DIR } from '../spectron/application'; - -function sanitize(name: string): string { - return name.replace(/[&*:\/]/g, ''); -} +import { sanitize } from './utilities'; export class ScreenCapturer { private static counter = 0; - testName: string = 'default'; - constructor(private application: Application, private suiteName: string) { } + constructor( + private application: Application, + private screenshotsDirPath: string | undefined + ) { } async capture(name: string): Promise { - if (!SCREENSHOTS_DIR) { + if (!this.screenshotsDirPath) { return; } const screenshotPath = path.join( - SCREENSHOTS_DIR, - sanitize(this.suiteName), - sanitize(this.testName), + this.screenshotsDirPath, `${ScreenCapturer.counter++}-${sanitize(name)}.png` ); const image = await this.application.browserWindow.capturePage(); - await new Promise((c, e) => mkdirp(path.dirname(screenshotPath), err => err ? e(err) : c())); await new Promise((c, e) => fs.writeFile(screenshotPath, image, err => err ? e(err) : c())); } } diff --git a/test/smoke/src/helpers/utilities.ts b/test/smoke/src/helpers/utilities.ts index 2ba4141ee3e..bde4dde38b7 100644 --- a/test/smoke/src/helpers/utilities.ts +++ b/test/smoke/src/helpers/utilities.ts @@ -75,4 +75,8 @@ export async function mkdirp(path: string, mode?: number): Promise { } return true; +} + +export function sanitize(name: string): string { + return name.replace(/[&*:\/]/g, ''); } \ No newline at end of file diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index b3c81458aee..ae69afd02b5 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -21,14 +21,12 @@ const opts = minimist(args, { string: [ 'build', 'stable-build', - 'screenshots', - 'logs', + 'debug', 'wait-time' ] }); -opts.screenshots = opts.screenshots === '' ? path.join(testDataPath, 'screenshots') : opts.screenshots; -opts.logs = opts.logs === '' ? path.join(testDataPath, 'logs') : opts.logs; +process.env.ARTIFACTS_DIR = opts.debug || ''; const workspacePath = path.join(testDataPath, 'smoketest.code-workspace'); const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express'; @@ -107,8 +105,6 @@ process.env.VSCODE_EXTENSIONS_DIR = extensionsPath; process.env.SMOKETEST_REPO = testRepoLocalDir; process.env.VSCODE_WORKSPACE_PATH = workspacePath; process.env.VSCODE_KEYBINDINGS_PATH = keybindingsPath; -process.env.SCREENSHOTS_DIR = opts.screenshots || ''; -process.env.LOGS_DIR = opts.logs || ''; process.env.WAIT_TIME = opts['wait-time'] || '20'; if (process.env.VSCODE_DEV === '1') { diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index e382b92156a..23e4667152f 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -12,6 +12,7 @@ import * as fs from 'fs'; import * as cp from 'child_process'; import * as path from 'path'; import * as mkdirp from 'mkdirp'; +import { sanitize } from '../helpers/utilities'; export const LATEST_PATH = process.env.VSCODE_PATH as string; export const STABLE_PATH = process.env.VSCODE_STABLE_PATH || ''; @@ -20,8 +21,7 @@ export const CODE_WORKSPACE_PATH = process.env.VSCODE_WORKSPACE_PATH as string; export const USER_DIR = process.env.VSCODE_USER_DIR as string; export const EXTENSIONS_DIR = process.env.VSCODE_EXTENSIONS_DIR as string; export const VSCODE_EDITION = process.env.VSCODE_EDITION as string; -export const SCREENSHOTS_DIR = process.env.SCREENSHOTS_DIR as string; -export const LOGS_DIR = process.env.LOGS_DIR as string; +export const ARTIFACTS_DIR = process.env.ARTIFACTS_DIR as string; export const WAIT_TIME = parseInt(process.env.WAIT_TIME as string); export enum VSCODE_BUILD { @@ -158,19 +158,30 @@ export class SpectronApplication { requireName: 'nodeRequire' }; - if (LOGS_DIR) { - const dir = path.join(LOGS_DIR, id); - opts.chromeDriverLogPath = path.join(dir, 'chromedriver.log'); - mkdirp.sync(dir); + let screenshotsDirPath: string | undefined = undefined; - opts.webdriverLogPath = path.join(dir, 'webdriver'); - mkdirp.sync(opts.webdriverLogPath); + if (ARTIFACTS_DIR) { + const testsuiteRootPath = path.join(ARTIFACTS_DIR, sanitize(testSuiteName)); + mkdirp.sync(testsuiteRootPath); + + // Collect screenshots + screenshotsDirPath = path.join(testsuiteRootPath, 'screenshots'); + mkdirp.sync(screenshotsDirPath); + + // Collect chromedriver logs + const chromedriverLogPath = path.join(testsuiteRootPath, 'chromedriver.log'); + opts.chromeDriverLogPath = chromedriverLogPath; + + // Collect webdriver logs + const webdriverLogsPath = path.join(testsuiteRootPath, 'webdriver'); + mkdirp.sync(webdriverLogsPath); + opts.webdriverLogPath = webdriverLogsPath; } this.spectron = new Application(opts); await this.spectron.start(); - this._screenCapturer = new ScreenCapturer(this.spectron, testSuiteName); + this._screenCapturer = new ScreenCapturer(this.spectron, screenshotsDirPath); this._client = new SpectronClient(this.spectron, this); this._workbench = new Workbench(this); } From 4756d8d980763b457d0e8dd0ca3880f2b6b87098 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 6 Oct 2017 11:06:49 +0200 Subject: [PATCH 023/394] smoke: log main and renderer processes --- build/tfs/darwin/build.sh | 2 +- build/tfs/linux/build.sh | 2 +- build/tfs/win32/1_build.ps1 | 2 +- build/tfs/win32/build_unsigned.ps1 | 2 +- test/smoke/src/main.ts | 4 +- test/smoke/src/spectron/application.ts | 72 ++++++++++++++++++++------ 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index bc4eb2aca16..adbbc89b9b4 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -41,7 +41,7 @@ function smoketest { ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" rm -rf $ARTIFACTS - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --debug $ARTIFACTS + npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --log $ARTIFACTS } step "Run smoke test" \ diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 426baf55915..cee7821823d 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -49,7 +49,7 @@ function smoketest { chown -R testuser $ARTIFACTS ps -o pid= -u testuser | xargs sudo kill -9 - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --debug $ARTIFACTS" + DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --log $ARTIFACTS" # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32" } diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1 index aa7a77d6f93..0d87c5276c0 100644 --- a/build/tfs/win32/1_build.ps1 +++ b/build/tfs/win32/1_build.ps1 @@ -56,7 +56,7 @@ step "Run smoke test" { $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts" Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --debug "$Artifacts" } + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --log "$Artifacts" } } done diff --git a/build/tfs/win32/build_unsigned.ps1 b/build/tfs/win32/build_unsigned.ps1 index 9d980ea304a..207f633999c 100644 --- a/build/tfs/win32/build_unsigned.ps1 +++ b/build/tfs/win32/build_unsigned.ps1 @@ -51,7 +51,7 @@ step "Run smoke test" { $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts" Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --debug "$Artifacts" } + exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --log "$Artifacts" } } step "Create archive and setup package" { diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index ae69afd02b5..d78cc255a2c 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -21,12 +21,12 @@ const opts = minimist(args, { string: [ 'build', 'stable-build', - 'debug', + 'log', 'wait-time' ] }); -process.env.ARTIFACTS_DIR = opts.debug || ''; +process.env.ARTIFACTS_DIR = opts.log || ''; const workspacePath = path.join(testDataPath, 'smoketest.code-workspace'); const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express'; diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 23e4667152f..01be7f3f6f2 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -54,12 +54,15 @@ export class SpectronApplication { private _workbench: Workbench; private _screenCapturer: ScreenCapturer; private spectron: Application; - private keybindings: any[]; + private keybindings: any[]; private stopLogCollection: (() => Promise) | undefined; - constructor(private _electronPath: string = LATEST_PATH, private _workspace: string = WORKSPACE_PATH, private _userDir: string = USER_DIR) { - } + constructor( + private _electronPath: string = LATEST_PATH, + private _workspace: string = WORKSPACE_PATH, + private _userDir: string = USER_DIR + ) { } - public get build(): VSCODE_BUILD { + get build(): VSCODE_BUILD { switch (VSCODE_EDITION) { case 'dev': return VSCODE_BUILD.DEV; @@ -69,27 +72,27 @@ export class SpectronApplication { return VSCODE_BUILD.STABLE; } - public get app(): Application { + get app(): Application { return this.spectron; } - public get client(): SpectronClient { + get client(): SpectronClient { return this._client; } - public get webclient(): WebClient { + get webclient(): WebClient { return this.spectron.client; } - public get screenCapturer(): ScreenCapturer { + get screenCapturer(): ScreenCapturer { return this._screenCapturer; } - public get workbench(): Workbench { + get workbench(): Workbench { return this._workbench; } - public async start(testSuiteName: string, codeArgs: string[] = [], env = process.env): Promise { + async start(testSuiteName: string, codeArgs: string[] = [], env = process.env): Promise { await this.retrieveKeybindings(); cp.execSync('git checkout .', { cwd: WORKSPACE_PATH }); await this.startApplication(testSuiteName, codeArgs, env); @@ -98,17 +101,22 @@ export class SpectronApplication { await this.screenCapturer.capture('Application started'); } - public async reload(): Promise { + async reload(): Promise { await this.workbench.quickopen.runCommand('Reload Window'); // TODO @sandy: Find a proper condition to wait for reload await new Promise(c => setTimeout(c, 500)); await this.checkWindowReady(); } - public async stop(): Promise { + async stop(): Promise { + if (this.stopLogCollection) { + await this.stopLogCollection(); + this.stopLogCollection = undefined; + } + if (this.spectron && this.spectron.isRunning()) { await this.screenCapturer.capture('Stopping application'); - return await this.spectron.stop(); + await this.spectron.stop(); } } @@ -158,10 +166,11 @@ export class SpectronApplication { requireName: 'nodeRequire' }; + let testsuiteRootPath: string | undefined = undefined; let screenshotsDirPath: string | undefined = undefined; if (ARTIFACTS_DIR) { - const testsuiteRootPath = path.join(ARTIFACTS_DIR, sanitize(testSuiteName)); + testsuiteRootPath = path.join(ARTIFACTS_DIR, sanitize(testSuiteName)); mkdirp.sync(testsuiteRootPath); // Collect screenshots @@ -181,6 +190,39 @@ export class SpectronApplication { this.spectron = new Application(opts); await this.spectron.start(); + if (testsuiteRootPath) { + // Collect logs + const mainProcessLogPath = path.join(testsuiteRootPath, 'main.log'); + const rendererProcessLogPath = path.join(testsuiteRootPath, 'renderer.log'); + + const flush = async () => { + const mainLogs = await this.spectron.client.getMainProcessLogs(); + await new Promise((c, e) => fs.appendFile(mainProcessLogPath, mainLogs.join('\n'), { encoding: 'utf8' }, err => err ? e(err) : c())); + + const rendererLogs = (await this.spectron.client.getRenderProcessLogs()).map(m => `${m.timestamp} - ${m.level} - ${m.message}`); + await new Promise((c, e) => fs.appendFile(rendererProcessLogPath, rendererLogs.join('\n'), { encoding: 'utf8' }, err => err ? e(err) : c())); + }; + + let running = true; + const loopFlush = async () => { + while (true) { + await flush(); + + if (!running) { + return; + } + + await new Promise(c => setTimeout(c, 1000)); + } + }; + + const loopPromise = loopFlush(); + this.stopLogCollection = () => { + running = false; + return loopPromise; + }; + } + this._screenCapturer = new ScreenCapturer(this.spectron, screenshotsDirPath); this._client = new SpectronClient(this.spectron, this); this._workbench = new Workbench(this); @@ -220,7 +262,7 @@ export class SpectronApplication { * Retrieves the command from keybindings file and executes it with WebdriverIO client API * @param command command (e.g. 'workbench.action.files.newUntitledFile') */ - public command(command: string, capture?: boolean): Promise { + command(command: string, capture?: boolean): Promise { const binding = this.keybindings.find(x => x['command'] === command); if (!binding) { return this.workbench.quickopen.runCommand(command); From 3151c10d70814f7346c7a236d0ec74f610b876b3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 11:38:58 +0200 Subject: [PATCH 024/394] - Ability to write configuration into memory - CLean up: Separate models and interfaces --- .../standalone/browser/simpleServices.ts | 4 +- .../configuration/common/configuration.ts | 339 ++++----------- .../common/configurationModels.ts | 405 ++++++++++++++++++ src/vs/platform/configuration/common/model.ts | 194 --------- .../node/configurationService.ts | 4 +- .../test/common/configuration.model.test.ts | 2 +- ...del.test.ts => configurationModel.test.ts} | 2 +- .../test/common/testConfigurationService.ts | 3 +- .../api/node/extHostConfiguration.ts | 3 +- .../common/configurationModels.ts | 21 +- .../node/configurationService.ts | 46 +- .../api/extHostConfiguration.test.ts | 2 +- 12 files changed, 560 insertions(+), 465 deletions(-) create mode 100644 src/vs/platform/configuration/common/configurationModels.ts delete mode 100644 src/vs/platform/configuration/common/model.ts rename src/vs/platform/configuration/test/common/{model.test.ts => configurationModel.test.ts} (98%) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 75aaa4492f9..a9b23d8d74f 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -8,7 +8,7 @@ import { Schemas } from 'vs/base/common/network'; import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IConfigurationService, IConfigurationChangeEvent, Configuration, ConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IEditor, IEditorInput, IEditorOptions, IEditorService, IResourceInput, Position } from 'vs/platform/editor/common/editor'; import { ICommandService, ICommand, ICommandEvent, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -23,7 +23,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { Selection } from 'vs/editor/common/core/selection'; import Event, { Emitter } from 'vs/base/common/event'; -import { DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; +import { Configuration, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 43da9ac3cfb..74fba9962fd 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -5,14 +5,14 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as arrays from 'vs/base/common/arrays'; -import * as types from 'vs/base/common/types'; import * as objects from 'vs/base/common/objects'; +import * as types from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; -import { StrictResourceMap } from 'vs/base/common/map'; -import { Workspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import Event from 'vs/base/common/event'; -import { OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; export const IConfigurationService = createDecorator('configurationService'); @@ -66,7 +66,8 @@ export interface IConfigurationService { default: T, user: T, workspace: T, - workspaceFolder: T + workspaceFolder: T, + memory?: T, value: T, }; @@ -75,15 +76,42 @@ export interface IConfigurationService { user: string[]; workspace: string[]; workspaceFolder: string[]; + memory?: string[]; }; } -export function overrideIdentifierFromKey(key: string): string { - return key.substring(1, key.length - 1); +export interface IConfiguraionModel { + contents: T; + keys: string[]; + overrides: IOverrides[]; } -export function keyFromOverrideIdentifier(overrideIdentifier: string): string { - return `[${overrideIdentifier}]`; +export interface IOverrides { + contents: T; + identifiers: string[]; +} + +export interface IConfigurationData { + defaults: IConfiguraionModel; + user: IConfiguraionModel; + workspace: IConfiguraionModel; + folders: { [folder: string]: IConfiguraionModel }; +} + +export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { added: string[], removed: string[], updated: string[] } { + const added = to.keys.filter(key => from.keys.indexOf(key) === -1); + const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); + const updated = []; + + for (const key of from.keys) { + const value1 = getConfigurationValue(from.contents, key); + const value2 = getConfigurationValue(to.contents, key); + if (!objects.equals(value1, value2)) { + updated.push(key); + } + } + + return { added, removed, updated }; } export function toConfigurationUpdateEvent(udpated: string[], source: ConfigurationTarget, sourceConfig: any): IConfigurationChangeEvent { @@ -102,6 +130,45 @@ export function toConfigurationUpdateEvent(udpated: string[], source: Configurat return { keys, sections, overrideIdentifiers, source, sourceConfig, hasSectionChanged, hasKeyChanged }; } + +export function toValuesTree(properties: { [qualifiedKey: string]: any }, conflictReporter: (message: string) => void): any { + const root = Object.create(null); + + for (let key in properties) { + addToValueTree(root, key, properties[key], conflictReporter); + } + + return root; +} + +export function addToValueTree(settingsTreeRoot: any, key: string, value: any, conflictReporter: (message: string) => void): void { + const segments = key.split('.'); + const last = segments.pop(); + + let curr = settingsTreeRoot; + for (let i = 0; i < segments.length; i++) { + let s = segments[i]; + let obj = curr[s]; + switch (typeof obj) { + case 'undefined': + obj = curr[s] = Object.create(null); + break; + case 'object': + break; + default: + conflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is ${JSON.stringify(obj)}`); + return; + } + curr = obj; + }; + + if (typeof curr === 'object') { + curr[last] = value; // workaround https://github.com/Microsoft/vscode/issues/13606 + } else { + conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`); + } +} + /** * A helper function to get the configuration value with a specific settings path (e.g. config.some.setting) */ @@ -137,245 +204,27 @@ export function merge(base: any, add: any, overwrite: boolean): void { }); } -export interface IConfiguraionModel { - contents: T; - keys: string[]; - overrides: IOverrides[]; +export function getConfigurationKeys(): string[] { + const properties = Registry.as(Extensions.Configuration).getConfigurationProperties(); + return Object.keys(properties); } -export interface IOverrides { - contents: T; - identifiers: string[]; +export function getDefaultValues(): any { + const valueTreeRoot: any = Object.create(null); + const properties = Registry.as(Extensions.Configuration).getConfigurationProperties(); + + for (let key in properties) { + let value = properties[key].default; + addToValueTree(valueTreeRoot, key, value, message => console.error(`Conflict in default settings: ${message}`)); + } + + return valueTreeRoot; } -export class ConfigurationModel implements IConfiguraionModel { - - constructor(protected _contents: T = {}, protected _keys: string[] = [], protected _overrides: IOverrides[] = []) { - } - - public get contents(): T { - return this._contents; - } - - public get overrides(): IOverrides[] { - return this._overrides; - } - - public get keys(): string[] { - return this._keys; - } - - public getContentsFor(section: string): V { - return objects.clone(this.contents[section]); - } - - public override(identifier: string): ConfigurationModel { - const result = new ConfigurationModel(); - const contents = objects.clone(this.contents); - if (this._overrides) { - for (const override of this._overrides) { - if (override.identifiers.indexOf(identifier) !== -1) { - merge(contents, override.contents, true); - } - } - } - result._contents = contents; - return result; - } - - public merge(other: ConfigurationModel, overwrite: boolean = true): ConfigurationModel { - const mergedModel = new ConfigurationModel(); - this.doMerge(mergedModel, this, overwrite); - this.doMerge(mergedModel, other, overwrite); - return mergedModel; - } - - protected doMerge(source: ConfigurationModel, target: ConfigurationModel, overwrite: boolean = true) { - merge(source.contents, objects.clone(target.contents), overwrite); - const overrides = objects.clone(source._overrides); - for (const override of target._overrides) { - const [sourceOverride] = overrides.filter(o => arrays.equals(o.identifiers, override.identifiers)); - if (sourceOverride) { - merge(sourceOverride.contents, override.contents, overwrite); - } else { - overrides.push(override); - } - } - source._overrides = overrides; - } +export function overrideIdentifierFromKey(key: string): string { + return key.substring(1, key.length - 1); } -export function compare(from: ConfigurationModel, to: ConfigurationModel): { added: string[], removed: string[], updated: string[] } { - const added = to.keys.filter(key => from.keys.indexOf(key) === -1); - const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); - const updated = []; - - for (const key of from.keys) { - const value1 = getConfigurationValue(from.contents, key); - const value2 = getConfigurationValue(to.contents, key); - if (!objects.equals(value1, value2)) { - updated.push(key); - } - } - - return { added, removed, updated }; -} - -export interface IConfigurationData { - defaults: IConfiguraionModel; - user: IConfiguraionModel; - workspace: IConfiguraionModel; - folders: { [folder: string]: IConfiguraionModel }; -} - -export class Configuration { - - private _globalConfiguration: ConfigurationModel; - private _workspaceConsolidatedConfiguration: ConfigurationModel; - protected _foldersConsolidatedConfigurations: StrictResourceMap>; - - constructor(protected _defaults: ConfigurationModel, protected _user: ConfigurationModel, protected _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(), protected folders: StrictResourceMap> = new StrictResourceMap>(), protected _workspace?: Workspace) { - this.merge(); - } - - get defaults(): ConfigurationModel { - return this._defaults; - } - - get user(): ConfigurationModel { - return this._user; - } - - get workspace(): ConfigurationModel { - return this._workspaceConfiguration; - } - - protected merge(): void { - this._globalConfiguration = new ConfigurationModel().merge(this._defaults).merge(this._user); - this._workspaceConsolidatedConfiguration = new ConfigurationModel().merge(this._globalConfiguration).merge(this._workspaceConfiguration); - this._foldersConsolidatedConfigurations = new StrictResourceMap>(); - for (const folder of this.folders.keys()) { - this.mergeFolder(folder); - } - } - - protected mergeFolder(folder: URI) { - this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); - } - - getValue(section: string = '', overrides: IConfigurationOverrides = {}): C { - const configModel = this.getConsolidateConfigurationModel(overrides); - return section ? configModel.getContentsFor(section) : configModel.contents; - } - - getValue2(key: string, overrides: IConfigurationOverrides = {}): any { - // make sure to clone the configuration so that the receiver does not tamper with the values - const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); - return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); - } - - lookup(key: string, overrides: IConfigurationOverrides = {}): { - default: C, - user: C, - workspace: C, - workspaceFolder: C - value: C, - } { - // make sure to clone the configuration so that the receiver does not tamper with the values - const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); - const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); - return { - default: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key)), - user: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key)), - workspace: objects.clone(this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0), //Check on workspace exists or not because _workspaceConfiguration is never null - workspaceFolder: objects.clone(folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0), - value: objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)) - }; - } - - keys(): { - default: string[]; - user: string[]; - workspace: string[]; - workspaceFolder: string[]; - } { - const folderConfigurationModel = this.getFolderConfigurationModelForResource(); - return { - default: this._defaults.keys, - user: this._user.keys, - workspace: this._workspaceConfiguration.keys, - workspaceFolder: folderConfigurationModel ? folderConfigurationModel.keys : [] - }; - } - - private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { - let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides); - return overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel; - } - - private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides): ConfigurationModel { - if (!this._workspace) { - return this._globalConfiguration; - } - - if (!resource) { - return this._workspaceConsolidatedConfiguration; - } - - const root = this._workspace.getFolder(resource); - if (!root) { - return this._workspaceConsolidatedConfiguration; - } - - return this._foldersConsolidatedConfigurations.get(root.uri) || this._workspaceConsolidatedConfiguration; - } - - private getFolderConfigurationModelForResource(resource?: URI): ConfigurationModel { - if (!this._workspace || !resource) { - return null; - } - - const root = this._workspace.getFolder(resource); - return root ? this.folders.get(root.uri) : null; - } - - public toData(): IConfigurationData { - return { - defaults: { - contents: this._defaults.contents, - overrides: this._defaults.overrides, - keys: this._defaults.keys - }, - user: { - contents: this._user.contents, - overrides: this._user.overrides, - keys: this._user.keys - }, - workspace: { - contents: this._workspaceConfiguration.contents, - overrides: this._workspaceConfiguration.overrides, - keys: this._workspaceConfiguration.keys - }, - folders: this.folders.keys().reduce((result, folder) => { - const { contents, overrides, keys } = this.folders.get(folder); - result[folder.toString()] = { contents, overrides, keys }; - return result; - }, Object.create({})) - }; - } - - public static parse(data: IConfigurationData, workspace: Workspace): Configuration { - const defaultConfiguration = Configuration.parseConfigurationModel(data.defaults); - const userConfiguration = Configuration.parseConfigurationModel(data.user); - const workspaceConfiguration = Configuration.parseConfigurationModel(data.workspace); - const folders: StrictResourceMap> = Object.keys(data.folders).reduce((result, key) => { - result.set(URI.parse(key), Configuration.parseConfigurationModel(data.folders[key])); - return result; - }, new StrictResourceMap>()); - return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, workspace); - } - - private static parseConfigurationModel(model: IConfiguraionModel): ConfigurationModel { - return new ConfigurationModel(model.contents, model.keys, model.overrides); - } +export function keyFromOverrideIdentifier(overrideIdentifier: string): string { + return `[${overrideIdentifier}]`; } \ No newline at end of file diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts new file mode 100644 index 00000000000..4d619fbc13b --- /dev/null +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -0,0 +1,405 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as json from 'vs/base/common/json'; +import { StrictResourceMap } from 'vs/base/common/map'; +import * as arrays from 'vs/base/common/arrays'; +import * as objects from 'vs/base/common/objects'; +import URI from 'vs/base/common/uri'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; +import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys } from 'vs/platform/configuration/common/configuration'; +import { Workspace } from 'vs/platform/workspace/common/workspace'; + +export class ConfigurationModel implements IConfiguraionModel { + + constructor(protected _contents: T = {}, protected _keys: string[] = [], protected _overrides: IOverrides[] = []) { + } + + public get contents(): T { + return this._contents; + } + + public get overrides(): IOverrides[] { + return this._overrides; + } + + public get keys(): string[] { + return this._keys; + } + + public getContentsFor(section: string): V { + return objects.clone(this.contents[section]); + } + + public override(identifier: string): ConfigurationModel { + const result = new ConfigurationModel(); + const contents = objects.clone(this.contents); + if (this._overrides) { + for (const override of this._overrides) { + if (override.identifiers.indexOf(identifier) !== -1) { + merge(contents, override.contents, true); + } + } + } + result._contents = contents; + return result; + } + + public setValue(key: string, value: any) { + addToValueTree(this._contents, key, value, e => { throw new Error(e); }); + if (this._keys.indexOf(key) === -1) { + this._keys.push(key); + } + } + + public removeValue(key: string) { + // Remove key from the value tree + const index = this._keys.indexOf(key); + if (index !== -1) { + this._keys.splice(index, 1); + } + } + + public merge(other: ConfigurationModel, overwrite: boolean = true): ConfigurationModel { + const mergedModel = new ConfigurationModel(); + this.doMerge(mergedModel, this, overwrite); + this.doMerge(mergedModel, other, overwrite); + return mergedModel; + } + + protected doMerge(source: ConfigurationModel, target: ConfigurationModel, overwrite: boolean = true) { + merge(source.contents, objects.clone(target.contents), overwrite); + const overrides = objects.clone(source._overrides); + for (const override of target._overrides) { + const [sourceOverride] = overrides.filter(o => arrays.equals(o.identifiers, override.identifiers)); + if (sourceOverride) { + merge(sourceOverride.contents, override.contents, overwrite); + } else { + overrides.push(override); + } + } + source._overrides = overrides; + } +} + +export class DefaultConfigurationModel extends ConfigurationModel { + + constructor() { + super(getDefaultValues()); + this._keys = getConfigurationKeys(); + this._overrides = Object.keys(this._contents) + .filter(key => OVERRIDE_PROPERTY_PATTERN.test(key)) + .map(key => { + return >{ + identifiers: [overrideIdentifierFromKey(key).trim()], + contents: toValuesTree(this._contents[key], message => console.error(`Conflict in default settings file: ${message}`)) + }; + }); + } + + public get keys(): string[] { + return this._keys; + } +} + +interface Overrides extends IOverrides { + raw: any; +} + +export class CustomConfigurationModel extends ConfigurationModel { + + protected _parseErrors: any[] = []; + + constructor(content: string = '', private name: string = '') { + super(); + if (content) { + this.update(content); + } + } + + public get errors(): any[] { + return this._parseErrors; + } + + public update(content: string): void { + let parsed: T = {}; + let overrides: Overrides[] = []; + let currentProperty: string = null; + let currentParent: any = []; + let previousParents: any[] = []; + let parseErrors: json.ParseError[] = []; + + function onValue(value: any) { + if (Array.isArray(currentParent)) { + (currentParent).push(value); + } else if (currentProperty) { + currentParent[currentProperty] = value; + } + if (OVERRIDE_PROPERTY_PATTERN.test(currentProperty)) { + onOverrideSettingsValue(currentProperty, value); + } + } + + function onOverrideSettingsValue(property: string, value: any): void { + overrides.push({ + identifiers: [overrideIdentifierFromKey(property).trim()], + raw: value, + contents: null + }); + } + + let visitor: json.JSONVisitor = { + onObjectBegin: () => { + let object = {}; + onValue(object); + previousParents.push(currentParent); + currentParent = object; + currentProperty = null; + }, + onObjectProperty: (name: string) => { + currentProperty = name; + }, + onObjectEnd: () => { + currentParent = previousParents.pop(); + }, + onArrayBegin: () => { + let array: any[] = []; + onValue(array); + previousParents.push(currentParent); + currentParent = array; + currentProperty = null; + }, + onArrayEnd: () => { + currentParent = previousParents.pop(); + }, + onLiteralValue: onValue, + onError: (error: json.ParseErrorCode) => { + parseErrors.push({ error: error }); + } + }; + if (content) { + try { + json.visit(content, visitor); + parsed = currentParent[0] || {}; + } catch (e) { + console.error(`Error while parsing settings file ${this.name}: ${e}`); + this._parseErrors = [e]; + } + } + this.processRaw(parsed); + + const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); + this._overrides = overrides.map>(override => { + // Filter unknown and non-overridable properties + const raw = {}; + for (const key in override.raw) { + if (configurationProperties[key] && configurationProperties[key].overridable) { + raw[key] = override.raw[key]; + } + } + return { + identifiers: override.identifiers, + contents: toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)) + }; + }); + } + + protected processRaw(raw: T): void { + this._contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)); + this._keys = Object.keys(raw); + } +} + +export class Configuration { + + private _globalConfiguration: ConfigurationModel; + private _workspaceConsolidatedConfiguration: ConfigurationModel; + protected _foldersConsolidatedConfigurations: StrictResourceMap>; + protected _memoryConsolidatedConfigurations: StrictResourceMap>; + + constructor(protected _defaults: ConfigurationModel, + protected _user: ConfigurationModel, + protected _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(), + protected folders: StrictResourceMap> = new StrictResourceMap>(), + protected _memoryConfiguration: ConfigurationModel = new ConfigurationModel(), + protected _memoryConfigurationByResource: StrictResourceMap> = new StrictResourceMap>(), + protected _workspace?: Workspace) { + this.merge(); + } + + get defaults(): ConfigurationModel { + return this._defaults; + } + + get user(): ConfigurationModel { + return this._user; + } + + get workspace(): ConfigurationModel { + return this._workspaceConfiguration; + } + + protected merge(): void { + this._globalConfiguration = new ConfigurationModel().merge(this._defaults).merge(this._user); + this._workspaceConsolidatedConfiguration = new ConfigurationModel().merge(this._globalConfiguration).merge(this._workspaceConfiguration); + this._foldersConsolidatedConfigurations = new StrictResourceMap>(); + for (const folder of this.folders.keys()) { + this.mergeFolder(folder); + } + } + + protected mergeFolder(folder: URI) { + this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); + } + + protected mergeMemory(folder: URI) { + this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); + } + + getValue(section: string = '', overrides: IConfigurationOverrides = {}): C { + const configModel = this.getConsolidateConfigurationModel(overrides); + return section ? configModel.getContentsFor(section) : configModel.contents; + } + + getValue2(key: string, overrides: IConfigurationOverrides = {}): any { + // make sure to clone the configuration so that the receiver does not tamper with the values + const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); + return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); + } + + updateValue(key: string, value: any, overrides: IConfigurationOverrides = {}): void { + let memoryConfiguration: ConfigurationModel; + if (overrides.resource) { + let memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource); + if (!memoryConfiguration) { + memoryConfiguration = new ConfigurationModel(); + this._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration); + } + } else { + memoryConfiguration = this._memoryConfiguration; + } + if (value === void 0) { + memoryConfiguration.removeValue(key); + } else { + memoryConfiguration.setValue(key, value); + } + } + + lookup(key: string, overrides: IConfigurationOverrides = {}): { + default: C, + user: C, + workspace: C, + workspaceFolder: C + memory?: C + value: C, + } { + // make sure to clone the configuration so that the receiver does not tamper with the values + const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); + const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); + const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration; + return { + default: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key)), + user: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key)), + workspace: objects.clone(this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0), //Check on workspace exists or not because _workspaceConfiguration is never null + workspaceFolder: objects.clone(folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0), + memory: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).contents : memoryConfigurationModel.contents, key)), + value: objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)) + }; + } + + keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + } { + const folderConfigurationModel = this.getFolderConfigurationModelForResource(); + return { + default: this._defaults.keys, + user: this._user.keys, + workspace: this._workspaceConfiguration.keys, + workspaceFolder: folderConfigurationModel ? folderConfigurationModel.keys : [] + }; + } + + private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { + let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides); + return overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel; + } + + private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides): ConfigurationModel { + if (!this._workspace) { + return this._globalConfiguration; + } + + if (!resource) { + return this._workspaceConsolidatedConfiguration.merge(this._memoryConfiguration); + } + + let consolidateConfiguration = this._workspaceConsolidatedConfiguration; + const root = this._workspace.getFolder(resource); + if (root) { + consolidateConfiguration = this._foldersConsolidatedConfigurations.get(root.uri) || this._workspaceConsolidatedConfiguration; + } + + const memoryConfigurationForResource = this._memoryConfigurationByResource.get(resource); + if (memoryConfigurationForResource) { + consolidateConfiguration = consolidateConfiguration.merge(memoryConfigurationForResource); + } + + return consolidateConfiguration; + } + + private getFolderConfigurationModelForResource(resource?: URI): ConfigurationModel { + if (!this._workspace || !resource) { + return null; + } + + const root = this._workspace.getFolder(resource); + return root ? this.folders.get(root.uri) : null; + } + + public toData(): IConfigurationData { + return { + defaults: { + contents: this._defaults.contents, + overrides: this._defaults.overrides, + keys: this._defaults.keys + }, + user: { + contents: this._user.contents, + overrides: this._user.overrides, + keys: this._user.keys + }, + workspace: { + contents: this._workspaceConfiguration.contents, + overrides: this._workspaceConfiguration.overrides, + keys: this._workspaceConfiguration.keys + }, + folders: this.folders.keys().reduce((result, folder) => { + const { contents, overrides, keys } = this.folders.get(folder); + result[folder.toString()] = { contents, overrides, keys }; + return result; + }, Object.create({})) + }; + } + + public static parse(data: IConfigurationData, workspace: Workspace): Configuration { + const defaultConfiguration = Configuration.parseConfigurationModel(data.defaults); + const userConfiguration = Configuration.parseConfigurationModel(data.user); + const workspaceConfiguration = Configuration.parseConfigurationModel(data.workspace); + const folders: StrictResourceMap> = Object.keys(data.folders).reduce((result, key) => { + result.set(URI.parse(key), Configuration.parseConfigurationModel(data.folders[key])); + return result; + }, new StrictResourceMap>()); + return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap>(), workspace); + } + + private static parseConfigurationModel(model: IConfiguraionModel): ConfigurationModel { + return new ConfigurationModel(model.contents, model.keys, model.overrides); + } +} \ No newline at end of file diff --git a/src/vs/platform/configuration/common/model.ts b/src/vs/platform/configuration/common/model.ts deleted file mode 100644 index 2eca51661ff..00000000000 --- a/src/vs/platform/configuration/common/model.ts +++ /dev/null @@ -1,194 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { Registry } from 'vs/platform/registry/common/platform'; -import * as json from 'vs/base/common/json'; -import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { ConfigurationModel, IOverrides, overrideIdentifierFromKey } from 'vs/platform/configuration/common/configuration'; - -export function getDefaultValues(): any { - const valueTreeRoot: any = Object.create(null); - const properties = Registry.as(Extensions.Configuration).getConfigurationProperties(); - - for (let key in properties) { - let value = properties[key].default; - addToValueTree(valueTreeRoot, key, value, message => console.error(`Conflict in default settings: ${message}`)); - } - - return valueTreeRoot; -} - -export function toValuesTree(properties: { [qualifiedKey: string]: any }, conflictReporter: (message: string) => void): any { - const root = Object.create(null); - - for (let key in properties) { - addToValueTree(root, key, properties[key], conflictReporter); - } - - return root; -} - -function addToValueTree(settingsTreeRoot: any, key: string, value: any, conflictReporter: (message: string) => void): void { - const segments = key.split('.'); - const last = segments.pop(); - - let curr = settingsTreeRoot; - for (let i = 0; i < segments.length; i++) { - let s = segments[i]; - let obj = curr[s]; - switch (typeof obj) { - case 'undefined': - obj = curr[s] = Object.create(null); - break; - case 'object': - break; - default: - conflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is ${JSON.stringify(obj)}`); - return; - } - curr = obj; - }; - - if (typeof curr === 'object') { - curr[last] = value; // workaround https://github.com/Microsoft/vscode/issues/13606 - } else { - conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`); - } -} - -export function getConfigurationKeys(): string[] { - const properties = Registry.as(Extensions.Configuration).getConfigurationProperties(); - - return Object.keys(properties); -} - -export class DefaultConfigurationModel extends ConfigurationModel { - - constructor() { - super(getDefaultValues()); - this._keys = getConfigurationKeys(); - this._overrides = Object.keys(this._contents) - .filter(key => OVERRIDE_PROPERTY_PATTERN.test(key)) - .map(key => { - return >{ - identifiers: [overrideIdentifierFromKey(key).trim()], - contents: toValuesTree(this._contents[key], message => console.error(`Conflict in default settings file: ${message}`)) - }; - }); - } - - public get keys(): string[] { - return this._keys; - } -} - -interface Overrides extends IOverrides { - raw: any; -} - -export class CustomConfigurationModel extends ConfigurationModel { - - protected _parseErrors: any[] = []; - - constructor(content: string = '', private name: string = '') { - super(); - if (content) { - this.update(content); - } - } - - public get errors(): any[] { - return this._parseErrors; - } - - public update(content: string): void { - let parsed: T = {}; - let overrides: Overrides[] = []; - let currentProperty: string = null; - let currentParent: any = []; - let previousParents: any[] = []; - let parseErrors: json.ParseError[] = []; - - function onValue(value: any) { - if (Array.isArray(currentParent)) { - (currentParent).push(value); - } else if (currentProperty) { - currentParent[currentProperty] = value; - } - if (OVERRIDE_PROPERTY_PATTERN.test(currentProperty)) { - onOverrideSettingsValue(currentProperty, value); - } - } - - function onOverrideSettingsValue(property: string, value: any): void { - overrides.push({ - identifiers: [overrideIdentifierFromKey(property).trim()], - raw: value, - contents: null - }); - } - - let visitor: json.JSONVisitor = { - onObjectBegin: () => { - let object = {}; - onValue(object); - previousParents.push(currentParent); - currentParent = object; - currentProperty = null; - }, - onObjectProperty: (name: string) => { - currentProperty = name; - }, - onObjectEnd: () => { - currentParent = previousParents.pop(); - }, - onArrayBegin: () => { - let array: any[] = []; - onValue(array); - previousParents.push(currentParent); - currentParent = array; - currentProperty = null; - }, - onArrayEnd: () => { - currentParent = previousParents.pop(); - }, - onLiteralValue: onValue, - onError: (error: json.ParseErrorCode) => { - parseErrors.push({ error: error }); - } - }; - if (content) { - try { - json.visit(content, visitor); - parsed = currentParent[0] || {}; - } catch (e) { - console.error(`Error while parsing settings file ${this.name}: ${e}`); - this._parseErrors = [e]; - } - } - this.processRaw(parsed); - - const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); - this._overrides = overrides.map>(override => { - // Filter unknown and non-overridable properties - const raw = {}; - for (const key in override.raw) { - if (configurationProperties[key] && configurationProperties[key].overridable) { - raw[key] = override.raw[key]; - } - } - return { - identifiers: override.identifiers, - contents: toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)) - }; - }); - } - - protected processRaw(raw: T): void { - this._contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)); - this._keys = Object.keys(raw); - } -} \ No newline at end of file diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 0d97199766b..6cfa5d53fb7 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -8,8 +8,8 @@ import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, toConfigurationUpdateEvent, ConfigurationModel, Configuration, compare } from 'vs/platform/configuration/common/configuration'; -import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; +import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, toConfigurationUpdateEvent, compare } from 'vs/platform/configuration/common/configuration'; +import { CustomConfigurationModel, DefaultConfigurationModel, ConfigurationModel, Configuration } from 'vs/platform/configuration/common/configurationModels'; import Event, { Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { onUnexpectedError } from 'vs/base/common/errors'; diff --git a/src/vs/platform/configuration/test/common/configuration.model.test.ts b/src/vs/platform/configuration/test/common/configuration.model.test.ts index 42b52919b33..4b4ff1e3ed1 100644 --- a/src/vs/platform/configuration/test/common/configuration.model.test.ts +++ b/src/vs/platform/configuration/test/common/configuration.model.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { ConfigurationModel } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; diff --git a/src/vs/platform/configuration/test/common/model.test.ts b/src/vs/platform/configuration/test/common/configurationModel.test.ts similarity index 98% rename from src/vs/platform/configuration/test/common/model.test.ts rename to src/vs/platform/configuration/test/common/configurationModel.test.ts index aa9597b6702..3cc4f519bc2 100644 --- a/src/vs/platform/configuration/test/common/model.test.ts +++ b/src/vs/platform/configuration/test/common/configurationModel.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; +import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; diff --git a/src/vs/platform/configuration/test/common/testConfigurationService.ts b/src/vs/platform/configuration/test/common/testConfigurationService.ts index 5653f211b14..2410406e261 100644 --- a/src/vs/platform/configuration/test/common/testConfigurationService.ts +++ b/src/vs/platform/configuration/test/common/testConfigurationService.ts @@ -9,8 +9,7 @@ import { TernarySearchTree } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { EventEmitter } from 'vs/base/common/eventEmitter'; -import { getConfigurationKeys } from 'vs/platform/configuration/common/model'; -import { IConfigurationOverrides, IConfigurationService, getConfigurationValue } from 'vs/platform/configuration/common/configuration'; +import { getConfigurationKeys, IConfigurationOverrides, IConfigurationService, getConfigurationValue } from 'vs/platform/configuration/common/configuration'; export class TestConfigurationService extends EventEmitter implements IConfigurationService { public _serviceBrand: any; diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 9e5101340bf..1647e1736ac 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -11,7 +11,8 @@ import { WorkspaceConfiguration } from 'vscode'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol'; import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes'; -import { IConfigurationData, Configuration } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData } from 'vs/platform/configuration/common/configuration'; +import { Configuration } from 'vs/platform/configuration/common/configurationModels'; import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; function lookUp(tree: any, key: string) { diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index b23dc396e7c..85afabd93a7 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,8 +5,8 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { CustomConfigurationModel, toValuesTree } from 'vs/platform/configuration/common/model'; -import { ConfigurationModel, Configuration as BaseConfiguration, compare } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; @@ -185,8 +185,15 @@ export class FolderConfigurationModel extends CustomConfigurationModel { export class Configuration extends BaseConfiguration { - constructor(defaults: ConfigurationModel, user: ConfigurationModel, workspaceConfiguration: ConfigurationModel, protected folders: StrictResourceMap>, workspace: Workspace) { - super(defaults, user, workspaceConfiguration, folders, workspace); + constructor( + defaults: ConfigurationModel, + user: ConfigurationModel, + workspaceConfiguration: ConfigurationModel, + protected folders: StrictResourceMap>, + memoryConfiguration: ConfigurationModel, + memoryConfigurationByResource: StrictResourceMap>, + workspace: Workspace) { + super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource, workspace); } updateDefaultConfiguration(defaults: ConfigurationModel): void { @@ -199,7 +206,7 @@ export class Configuration extends BaseConfiguration { const { added, updated, removed } = compare(this._user, user); changedKeys = [...added, ...updated, ...removed]; if (changedKeys.length) { - const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._workspace); + const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace); this._user = user; this.merge(); @@ -215,7 +222,7 @@ export class Configuration extends BaseConfiguration { const { added, updated, removed } = compare(this._workspaceConfiguration, workspaceConfiguration); changedKeys = [...added, ...updated, ...removed]; if (changedKeys.length) { - const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._workspace); + const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace); this._workspaceConfiguration = workspaceConfiguration; this.merge(); @@ -234,7 +241,7 @@ export class Configuration extends BaseConfiguration { const { added, updated, removed } = compare(currentFolderConfiguration, configuration); changedKeys = [...added, ...updated, ...removed]; if (changedKeys.length) { - const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._workspace); + const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace); this.folders.set(resource, configuration); this.mergeFolder(resource); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index f5b7cef1e68..4e4b99992ee 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -22,9 +22,9 @@ import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CustomConfigurationModel } from 'vs/platform/configuration/common/model'; +import { CustomConfigurationModel, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; +import { IConfigurationChangeEvent, ConfigurationTarget, toConfigurationUpdateEvent, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration } from 'vs/workbench/services/configuration/common/configurationModels'; -import { IConfigurationChangeEvent, ConfigurationTarget, toConfigurationUpdateEvent, ConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { ConfigurationService as GlobalConfigurationService, isConfigurationOverrides } from 'vs/platform/configuration/node/configurationService'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -152,13 +152,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat if (this.configurationEditingService) { const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0; const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3); - if (target) { - if (target === ConfigurationTarget.MEMORY) { - return TPromise.as(null); - } else { - return this.writeConfigurationValue(key, value, target, overrides); - } + return this.writeConfigurationValue(key, value, target, overrides); } } return TPromise.as(null); @@ -176,6 +171,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat user: T, workspace: T, workspaceFolder: T, + memory?: T, value: T } { return this._configuration.lookup(key); @@ -329,7 +325,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat const folderConfigurationModels = new StrictResourceMap>(); folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration)); - this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null + this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null // TODO: compare with old values?? const keys = this._configuration.keys(); @@ -465,6 +461,21 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides): TPromise { + if (target === ConfigurationTarget.DEFAULT) { + return TPromise.wrapError(new Error('Invalid configuration target')); + } + + let currentTargetValue = this.getTargetValue(key, target, overrides); + if (equals(currentTargetValue, value)) { + return TPromise.as(null); + } + + if (target === ConfigurationTarget.MEMORY) { + this._configuration.updateValue(key, value, overrides); + this.triggerConfigurationChange([key], target); + return TPromise.as(null); + } + return this.configurationEditingService.writeConfiguration(this.toEditableConfigurationTarget(target), { key, value }, { scopes: overrides }) .then(() => { switch (target) { @@ -528,6 +539,23 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } } + private getTargetValue(key: string, target: ConfigurationTarget, overrides?: IConfigurationOverrides): any { + const inspect = this.inspect(key, overrides); + switch (target) { + case ConfigurationTarget.DEFAULT: + return inspect.default; + case ConfigurationTarget.USER: + return inspect.user; + case ConfigurationTarget.WORKSPACE: + return inspect.workspace; + case ConfigurationTarget.WORKSPACE_FOLDER: + return inspect.workspaceFolder; + case ConfigurationTarget.MEMORY: + return inspect.memory; + } + return void 0; + } + private getTargetConfiguration(target: ConfigurationTarget): any { switch (target) { case ConfigurationTarget.DEFAULT: diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index a935f3c9eed..54fa31a10d4 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -12,7 +12,7 @@ import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration import { MainThreadConfigurationShape } from 'vs/workbench/api/node/extHost.protocol'; import { TPromise } from 'vs/base/common/winjs.base'; import { ConfigurationTarget, ConfigurationEditingErrorCode, ConfigurationEditingError } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { ConfigurationModel } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { TestThreadService } from './testThreadService'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; From 38f2f142b01dae11ddc56e28b720ad717c4fa836 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 11:48:02 +0200 Subject: [PATCH 025/394] Remove unnecessary generics in configuration area --- src/vs/code/electron-main/app.ts | 2 +- .../standalone/browser/simpleServices.ts | 4 +- .../configuration/common/configuration.ts | 22 ++--- .../common/configurationModels.ts | 96 +++++++++---------- .../node/configurationService.ts | 14 +-- .../test/common/configuration.model.test.ts | 20 ++-- src/vs/workbench/api/node/extHost.protocol.ts | 4 +- .../api/node/extHostConfiguration.ts | 6 +- .../common/configurationModels.ts | 76 +++++++-------- .../node/configurationService.ts | 50 +++++----- 10 files changed, 147 insertions(+), 147 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 789da519ee2..2efd0e0d351 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -76,7 +76,7 @@ export class CodeApplication { @ILogService private logService: ILogService, @IEnvironmentService private environmentService: IEnvironmentService, @ILifecycleService private lifecycleService: ILifecycleService, - @IConfigurationService private configurationService: ConfigurationService, + @IConfigurationService private configurationService: ConfigurationService, @IStorageService private storageService: IStorageService, @IHistoryMainService private historyService: IHistoryMainService ) { diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index a9b23d8d74f..3d84c45b5eb 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -442,13 +442,13 @@ export class SimpleConfigurationService implements IConfigurationService { private _onDidUpdateConfiguration = new Emitter(); public onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; - private _configuration: Configuration; + private _configuration: Configuration; constructor() { this._configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel()); } - private configuration(): Configuration { + private configuration(): Configuration { return this._configuration; } diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 74fba9962fd..b9cbfb0a599 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -80,25 +80,25 @@ export interface IConfigurationService { }; } -export interface IConfiguraionModel { - contents: T; +export interface IConfiguraionModel { + contents: any; keys: string[]; - overrides: IOverrides[]; + overrides: IOverrides[]; } -export interface IOverrides { - contents: T; +export interface IOverrides { + contents: any; identifiers: string[]; } -export interface IConfigurationData { - defaults: IConfiguraionModel; - user: IConfiguraionModel; - workspace: IConfiguraionModel; - folders: { [folder: string]: IConfiguraionModel }; +export interface IConfigurationData { + defaults: IConfiguraionModel; + user: IConfiguraionModel; + workspace: IConfiguraionModel; + folders: { [folder: string]: IConfiguraionModel }; } -export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { added: string[], removed: string[], updated: string[] } { +export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { added: string[], removed: string[], updated: string[] } { const added = to.keys.filter(key => from.keys.indexOf(key) === -1); const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); const updated = []; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 4d619fbc13b..8a207935c4a 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -14,16 +14,16 @@ import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'v import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys } from 'vs/platform/configuration/common/configuration'; import { Workspace } from 'vs/platform/workspace/common/workspace'; -export class ConfigurationModel implements IConfiguraionModel { +export class ConfigurationModel implements IConfiguraionModel { - constructor(protected _contents: T = {}, protected _keys: string[] = [], protected _overrides: IOverrides[] = []) { + constructor(protected _contents: any = {}, protected _keys: string[] = [], protected _overrides: IOverrides[] = []) { } - public get contents(): T { + public get contents(): any { return this._contents; } - public get overrides(): IOverrides[] { + public get overrides(): IOverrides[] { return this._overrides; } @@ -35,8 +35,8 @@ export class ConfigurationModel implements IConfiguraionModel { return objects.clone(this.contents[section]); } - public override(identifier: string): ConfigurationModel { - const result = new ConfigurationModel(); + public override(identifier: string): ConfigurationModel { + const result = new ConfigurationModel(); const contents = objects.clone(this.contents); if (this._overrides) { for (const override of this._overrides) { @@ -64,14 +64,14 @@ export class ConfigurationModel implements IConfiguraionModel { } } - public merge(other: ConfigurationModel, overwrite: boolean = true): ConfigurationModel { - const mergedModel = new ConfigurationModel(); + public merge(other: ConfigurationModel, overwrite: boolean = true): ConfigurationModel { + const mergedModel = new ConfigurationModel(); this.doMerge(mergedModel, this, overwrite); this.doMerge(mergedModel, other, overwrite); return mergedModel; } - protected doMerge(source: ConfigurationModel, target: ConfigurationModel, overwrite: boolean = true) { + protected doMerge(source: ConfigurationModel, target: ConfigurationModel, overwrite: boolean = true) { merge(source.contents, objects.clone(target.contents), overwrite); const overrides = objects.clone(source._overrides); for (const override of target._overrides) { @@ -86,7 +86,7 @@ export class ConfigurationModel implements IConfiguraionModel { } } -export class DefaultConfigurationModel extends ConfigurationModel { +export class DefaultConfigurationModel extends ConfigurationModel { constructor() { super(getDefaultValues()); @@ -94,7 +94,7 @@ export class DefaultConfigurationModel extends ConfigurationModel { this._overrides = Object.keys(this._contents) .filter(key => OVERRIDE_PROPERTY_PATTERN.test(key)) .map(key => { - return >{ + return { identifiers: [overrideIdentifierFromKey(key).trim()], contents: toValuesTree(this._contents[key], message => console.error(`Conflict in default settings file: ${message}`)) }; @@ -106,11 +106,11 @@ export class DefaultConfigurationModel extends ConfigurationModel { } } -interface Overrides extends IOverrides { +interface Overrides extends IOverrides { raw: any; } -export class CustomConfigurationModel extends ConfigurationModel { +export class CustomConfigurationModel extends ConfigurationModel { protected _parseErrors: any[] = []; @@ -126,8 +126,8 @@ export class CustomConfigurationModel extends ConfigurationModel { } public update(content: string): void { - let parsed: T = {}; - let overrides: Overrides[] = []; + let parsed: any = {}; + let overrides: Overrides[] = []; let currentProperty: string = null; let currentParent: any = []; let previousParents: any[] = []; @@ -193,7 +193,7 @@ export class CustomConfigurationModel extends ConfigurationModel { this.processRaw(parsed); const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); - this._overrides = overrides.map>(override => { + this._overrides = overrides.map(override => { // Filter unknown and non-overridable properties const raw = {}; for (const key in override.raw) { @@ -203,61 +203,61 @@ export class CustomConfigurationModel extends ConfigurationModel { } return { identifiers: override.identifiers, - contents: toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)) + contents: toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)) }; }); } - protected processRaw(raw: T): void { + protected processRaw(raw: any): void { this._contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`)); this._keys = Object.keys(raw); } } -export class Configuration { +export class Configuration { - private _globalConfiguration: ConfigurationModel; - private _workspaceConsolidatedConfiguration: ConfigurationModel; - protected _foldersConsolidatedConfigurations: StrictResourceMap>; - protected _memoryConsolidatedConfigurations: StrictResourceMap>; + private _globalConfiguration: ConfigurationModel; + private _workspaceConsolidatedConfiguration: ConfigurationModel; + protected _foldersConsolidatedConfigurations: StrictResourceMap; + protected _memoryConsolidatedConfigurations: StrictResourceMap; - constructor(protected _defaults: ConfigurationModel, - protected _user: ConfigurationModel, - protected _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(), - protected folders: StrictResourceMap> = new StrictResourceMap>(), - protected _memoryConfiguration: ConfigurationModel = new ConfigurationModel(), - protected _memoryConfigurationByResource: StrictResourceMap> = new StrictResourceMap>(), + constructor(protected _defaults: ConfigurationModel, + protected _user: ConfigurationModel, + protected _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(), + protected folders: StrictResourceMap = new StrictResourceMap(), + protected _memoryConfiguration: ConfigurationModel = new ConfigurationModel(), + protected _memoryConfigurationByResource: StrictResourceMap = new StrictResourceMap(), protected _workspace?: Workspace) { this.merge(); } - get defaults(): ConfigurationModel { + get defaults(): ConfigurationModel { return this._defaults; } - get user(): ConfigurationModel { + get user(): ConfigurationModel { return this._user; } - get workspace(): ConfigurationModel { + get workspace(): ConfigurationModel { return this._workspaceConfiguration; } protected merge(): void { - this._globalConfiguration = new ConfigurationModel().merge(this._defaults).merge(this._user); - this._workspaceConsolidatedConfiguration = new ConfigurationModel().merge(this._globalConfiguration).merge(this._workspaceConfiguration); - this._foldersConsolidatedConfigurations = new StrictResourceMap>(); + this._globalConfiguration = new ConfigurationModel().merge(this._defaults).merge(this._user); + this._workspaceConsolidatedConfiguration = new ConfigurationModel().merge(this._globalConfiguration).merge(this._workspaceConfiguration); + this._foldersConsolidatedConfigurations = new StrictResourceMap(); for (const folder of this.folders.keys()) { this.mergeFolder(folder); } } protected mergeFolder(folder: URI) { - this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); + this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); } protected mergeMemory(folder: URI) { - this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); + this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); } getValue(section: string = '', overrides: IConfigurationOverrides = {}): C { @@ -272,7 +272,7 @@ export class Configuration { } updateValue(key: string, value: any, overrides: IConfigurationOverrides = {}): void { - let memoryConfiguration: ConfigurationModel; + let memoryConfiguration: ConfigurationModel; if (overrides.resource) { let memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource); if (!memoryConfiguration) { @@ -326,12 +326,12 @@ export class Configuration { }; } - private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { + private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides); - return overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel; + return overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel; } - private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides): ConfigurationModel { + private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides): ConfigurationModel { if (!this._workspace) { return this._globalConfiguration; } @@ -354,7 +354,7 @@ export class Configuration { return consolidateConfiguration; } - private getFolderConfigurationModelForResource(resource?: URI): ConfigurationModel { + private getFolderConfigurationModelForResource(resource?: URI): ConfigurationModel { if (!this._workspace || !resource) { return null; } @@ -363,7 +363,7 @@ export class Configuration { return root ? this.folders.get(root.uri) : null; } - public toData(): IConfigurationData { + public toData(): IConfigurationData { return { defaults: { contents: this._defaults.contents, @@ -388,18 +388,18 @@ export class Configuration { }; } - public static parse(data: IConfigurationData, workspace: Workspace): Configuration { + public static parse(data: IConfigurationData, workspace: Workspace): Configuration { const defaultConfiguration = Configuration.parseConfigurationModel(data.defaults); const userConfiguration = Configuration.parseConfigurationModel(data.user); const workspaceConfiguration = Configuration.parseConfigurationModel(data.workspace); - const folders: StrictResourceMap> = Object.keys(data.folders).reduce((result, key) => { + const folders: StrictResourceMap = Object.keys(data.folders).reduce((result, key) => { result.set(URI.parse(key), Configuration.parseConfigurationModel(data.folders[key])); return result; - }, new StrictResourceMap>()); - return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap>(), workspace); + }, new StrictResourceMap()); + return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap(), workspace); } - private static parseConfigurationModel(model: IConfiguraionModel): ConfigurationModel { + private static parseConfigurationModel(model: IConfiguraionModel): ConfigurationModel { return new ConfigurationModel(model.contents, model.keys, model.overrides); } } \ No newline at end of file diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 6cfa5d53fb7..d7b5f65f730 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -25,12 +25,12 @@ export function isConfigurationOverrides(thing: any): thing is IConfigurationOve && (!thing.resource || thing.resource instanceof URI); } -export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable { +export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable { _serviceBrand: any; - private _configuration: Configuration; - private userConfigModelWatcher: ConfigWatcher>; + private _configuration: Configuration; + private userConfigModelWatcher: ConfigWatcher; private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; @@ -41,8 +41,8 @@ export class ConfigurationService extends Disposable implements IConfiguratio super(); this.userConfigModelWatcher = new ConfigWatcher(environmentService.appSettingsPath, { - changeBufferDelay: 300, onError: error => onUnexpectedError(error), defaultConfig: new CustomConfigurationModel(null, environmentService.appSettingsPath), parse: (content: string, parseErrors: any[]) => { - const userConfigModel = new CustomConfigurationModel(content, environmentService.appSettingsPath); + changeBufferDelay: 300, onError: error => onUnexpectedError(error), defaultConfig: new CustomConfigurationModel(null, environmentService.appSettingsPath), parse: (content: string, parseErrors: any[]) => { + const userConfigModel = new CustomConfigurationModel(content, environmentService.appSettingsPath); parseErrors = [...userConfigModel.errors]; return userConfigModel; } @@ -56,7 +56,7 @@ export class ConfigurationService extends Disposable implements IConfiguratio this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(configurationProperties => this.onDidRegisterConfiguration(configurationProperties))); } - get configuration(): Configuration { + get configuration(): Configuration { return this._configuration; } @@ -126,7 +126,7 @@ export class ConfigurationService extends Disposable implements IConfiguratio } private reset(): void { - const defaults = new DefaultConfigurationModel(); + const defaults = new DefaultConfigurationModel(); const user = this.userConfigModelWatcher.getConfig(); this._configuration = new Configuration(defaults, user); } diff --git a/src/vs/platform/configuration/test/common/configuration.model.test.ts b/src/vs/platform/configuration/test/common/configuration.model.test.ts index 4b4ff1e3ed1..65555f8e9f2 100644 --- a/src/vs/platform/configuration/test/common/configuration.model.test.ts +++ b/src/vs/platform/configuration/test/common/configuration.model.test.ts @@ -29,8 +29,8 @@ suite('Configuration', () => { }); test('simple merge', () => { - let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); - let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); + let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); + let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 }); }); @@ -43,24 +43,24 @@ suite('Configuration', () => { }); test('simple merge overrides', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': 2 } }]); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'b': 2 } }]); + let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': 2 } }]); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'b': 2 } }]); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': 2, 'b': 2 } }]); }); test('recursive merge overrides', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]); + let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': { 'd': 1, 'e': 2 } } }]); }); test('merge ignore keys', () => { - let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); - let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); + let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); + let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); let result = base.merge(add); assert.deepEqual(result.keys, []); }); @@ -69,7 +69,7 @@ suite('Configuration', () => { let testObject = new ConfigurationModel({ 'a': 1 }); assert.deepEqual(testObject.getContentsFor('a'), 1); - testObject = new ConfigurationModel({ 'a': { 'b': 1 } }); + testObject = new ConfigurationModel({ 'a': { 'b': 1 } }); assert.deepEqual(testObject.getContentsFor('a'), { 'b': 1 }); }); @@ -80,7 +80,7 @@ suite('Configuration', () => { }); test('Test override gives all content merged with overrides', () => { - const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, [], [{ identifiers: ['b'], contents: { 'a': 2 } }]); + const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, [], [{ identifiers: ['b'], contents: { 'a': 2 } }]); assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1 }); }); diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 4016299feed..16f681bddca 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -74,7 +74,7 @@ export interface IInitData { environment: IEnvironment; workspace: IWorkspaceData; extensions: IExtensionDescription[]; - configuration: IConfigurationData; + configuration: IConfigurationData; telemetryInfo: ITelemetryInfo; } @@ -412,7 +412,7 @@ export interface ExtHostCommandsShape { } export interface ExtHostConfigurationShape { - $acceptConfigurationChanged(data: IConfigurationData): void; + $acceptConfigurationChanged(data: IConfigurationData): void; } export interface ExtHostDiagnosticsShape { diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 1647e1736ac..031763f0ff4 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -39,9 +39,9 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { private readonly _onDidChangeConfiguration = new Emitter(); private readonly _proxy: MainThreadConfigurationShape; private readonly _extHostWorkspace: ExtHostWorkspace; - private _configuration: Configuration; + private _configuration: Configuration; - constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationData) { + constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationData) { this._proxy = proxy; this._extHostWorkspace = extHostWorkspace; this._configuration = Configuration.parse(data, extHostWorkspace.workspace); @@ -51,7 +51,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event; } - $acceptConfigurationChanged(data: IConfigurationData) { + $acceptConfigurationChanged(data: IConfigurationData) { this._configuration = Configuration.parse(data, this._extHostWorkspace.workspace); this._onDidChangeConfiguration.fire(undefined); } diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 85afabd93a7..df0c1b196ee 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -15,14 +15,14 @@ import { Workspace } from 'vs/platform/workspace/common/workspace'; import { StrictResourceMap } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; -export class WorkspaceConfigurationModel extends CustomConfigurationModel { +export class WorkspaceConfigurationModel extends CustomConfigurationModel { - private _raw: T; + private _raw: any; private _folders: IStoredWorkspaceFolder[]; - private _worksapaceSettings: ConfigurationModel; - private _tasksConfiguration: ConfigurationModel; - private _launchConfiguration: ConfigurationModel; - private _workspaceConfiguration: ConfigurationModel; + private _worksapaceSettings: ConfigurationModel; + private _tasksConfiguration: ConfigurationModel; + private _launchConfiguration: ConfigurationModel; + private _workspaceConfiguration: ConfigurationModel; public update(content: string): void { super.update(content); @@ -34,11 +34,11 @@ export class WorkspaceConfigurationModel extends CustomConfigurationModel return this._folders; } - get workspaceConfiguration(): ConfigurationModel { + get workspaceConfiguration(): ConfigurationModel { return this._workspaceConfiguration; } - protected processRaw(raw: T): void { + protected processRaw(raw: any): void { this._raw = raw; this._folders = (this._raw['folders'] || []) as IStoredWorkspaceFolder[]; @@ -49,27 +49,27 @@ export class WorkspaceConfigurationModel extends CustomConfigurationModel super.processRaw(raw); } - private parseConfigurationModel(section: string): ConfigurationModel { + private parseConfigurationModel(section: string): ConfigurationModel { const rawSection = this._raw[section] || {}; const contents = toValuesTree(rawSection, message => console.error(`Conflict in section '${section}' of workspace configuration file ${message}`)); - return new ConfigurationModel(contents, Object.keys(rawSection)); + return new ConfigurationModel(contents, Object.keys(rawSection)); } - private consolidate(): ConfigurationModel { + private consolidate(): ConfigurationModel { const keys: string[] = [...this._worksapaceSettings.keys, ...this._tasksConfiguration.keys.map(key => `tasks.${key}`), ...this._launchConfiguration.keys.map(key => `launch.${key}`)]; - const mergedContents = new ConfigurationModel({}, keys) + const mergedContents = new ConfigurationModel({}, keys) .merge(this._worksapaceSettings) .merge(this._tasksConfiguration) .merge(this._launchConfiguration); - return new ConfigurationModel(mergedContents.contents, keys, mergedContents.overrides); + return new ConfigurationModel(mergedContents.contents, keys, mergedContents.overrides); } } -export class ScopedConfigurationModel extends CustomConfigurationModel { +export class ScopedConfigurationModel extends CustomConfigurationModel { constructor(content: string, name: string, public readonly scope: string) { super(null, name); @@ -85,14 +85,14 @@ export class ScopedConfigurationModel extends CustomConfigurationModel { } -export class FolderSettingsModel extends CustomConfigurationModel { +export class FolderSettingsModel extends CustomConfigurationModel { - private _raw: T; + private _raw: any; private _unsupportedKeys: string[]; - protected processRaw(raw: T): void { + protected processRaw(raw: any): void { this._raw = raw; - const processedRaw = {}; + const processedRaw = {}; this._unsupportedKeys = []; const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); for (let key in raw) { @@ -121,16 +121,16 @@ export class FolderSettingsModel extends CustomConfigurationModel { return !propertySchema.isExecutable; } - public createWorkspaceConfigurationModel(): ConfigurationModel { + public createWorkspaceConfigurationModel(): ConfigurationModel { return this.createScopedConfigurationModel(ConfigurationScope.WINDOW); } - public createFolderScopedConfigurationModel(): ConfigurationModel { + public createFolderScopedConfigurationModel(): ConfigurationModel { return this.createScopedConfigurationModel(ConfigurationScope.RESOURCE); } - private createScopedConfigurationModel(scope: ConfigurationScope): ConfigurationModel { - const workspaceRaw = {}; + private createScopedConfigurationModel(scope: ConfigurationScope): ConfigurationModel { + const workspaceRaw = {}; const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); for (let key in this._raw) { if (this.getScope(key, configurationProperties) === scope) { @@ -148,15 +148,15 @@ export class FolderSettingsModel extends CustomConfigurationModel { } } -export class FolderConfigurationModel extends CustomConfigurationModel { +export class FolderConfigurationModel extends CustomConfigurationModel { - constructor(public readonly workspaceSettingsConfig: FolderSettingsModel, private scopedConfigs: ScopedConfigurationModel[], private scope: ConfigurationScope) { + constructor(public readonly workspaceSettingsConfig: FolderSettingsModel, private scopedConfigs: ScopedConfigurationModel[], private scope: ConfigurationScope) { super(); this.consolidate(); } private consolidate(): void { - this._contents = {}; + this._contents = {}; this._overrides = []; this.doMerge(this, ConfigurationScope.WINDOW === this.scope ? this.workspaceSettingsConfig : this.workspaceSettingsConfig.createFolderScopedConfigurationModel()); @@ -183,25 +183,25 @@ export class FolderConfigurationModel extends CustomConfigurationModel { } } -export class Configuration extends BaseConfiguration { +export class Configuration extends BaseConfiguration { constructor( - defaults: ConfigurationModel, - user: ConfigurationModel, - workspaceConfiguration: ConfigurationModel, - protected folders: StrictResourceMap>, - memoryConfiguration: ConfigurationModel, - memoryConfigurationByResource: StrictResourceMap>, + defaults: ConfigurationModel, + user: ConfigurationModel, + workspaceConfiguration: ConfigurationModel, + protected folders: StrictResourceMap, + memoryConfiguration: ConfigurationModel, + memoryConfigurationByResource: StrictResourceMap, workspace: Workspace) { super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource, workspace); } - updateDefaultConfiguration(defaults: ConfigurationModel): void { + updateDefaultConfiguration(defaults: ConfigurationModel): void { this._defaults = defaults; this.merge(); } - updateUserConfiguration(user: ConfigurationModel): string[] { + updateUserConfiguration(user: ConfigurationModel): string[] { let changedKeys = []; const { added, updated, removed } = compare(this._user, user); changedKeys = [...added, ...updated, ...removed]; @@ -217,7 +217,7 @@ export class Configuration extends BaseConfiguration { return []; } - updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): string[] { + updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): string[] { let changedKeys = []; const { added, updated, removed } = compare(this._workspaceConfiguration, workspaceConfiguration); changedKeys = [...added, ...updated, ...removed]; @@ -233,7 +233,7 @@ export class Configuration extends BaseConfiguration { return []; } - updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel): string[] { + updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel): string[] { const currentFolderConfiguration = this.folders.get(resource); if (currentFolderConfiguration) { @@ -269,7 +269,7 @@ export class Configuration extends BaseConfiguration { return keys; } - getFolderConfigurationModel(folder: URI): FolderConfigurationModel { - return >this.folders.get(folder); + getFolderConfigurationModel(folder: URI): FolderConfigurationModel { + return this.folders.get(folder); } } \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 4e4b99992ee..7e8884d88e7 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -57,10 +57,10 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat public _serviceBrand: any; private workspace: Workspace; - private _configuration: Configuration; - private baseConfigurationService: GlobalConfigurationService; + private _configuration: Configuration; + private baseConfigurationService: GlobalConfigurationService; private workspaceConfiguration: WorkspaceConfiguration; - private cachedFolderConfigs: StrictResourceMap>; + private cachedFolderConfigs: StrictResourceMap; protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; @@ -315,17 +315,17 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private loadConfiguration(): TPromise { // reset caches - this.cachedFolderConfigs = new StrictResourceMap>(); + this.cachedFolderConfigs = new StrictResourceMap(); const folders = this.workspace.folders; return this.loadFolderConfigurations(folders) .then((folderConfigurations) => { let workspaceConfiguration = this.getWorkspaceConfigurationModel(folderConfigurations); - const folderConfigurationModels = new StrictResourceMap>(); + const folderConfigurationModels = new StrictResourceMap(); folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration)); - this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null + this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null // TODO: compare with old values?? const keys = this._configuration.keys(); @@ -333,14 +333,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat }); } - private getWorkspaceConfigurationModel(folderConfigurations: FolderConfigurationModel[]): ConfigurationModel { + private getWorkspaceConfigurationModel(folderConfigurations: FolderConfigurationModel[]): ConfigurationModel { switch (this.getWorkbenchState()) { case WorkbenchState.FOLDER: return folderConfigurations[0]; case WorkbenchState.WORKSPACE: return this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration; default: - return new ConfigurationModel(); + return new ConfigurationModel(); } } @@ -452,7 +452,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return TPromise.as(changedKeys); } - private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise[]> { + private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise { return TPromise.join([...folders.map(folder => { const folderConfiguration = new FolderConfiguration(folder.uri, this.workspaceSettingsRootFolder, this.getWorkbenchState() === WorkbenchState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW); this.cachedFolderConfigs.set(folder.uri, this._register(folderConfiguration)); @@ -588,7 +588,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat class WorkspaceConfiguration extends Disposable { private _workspaceConfigPath: URI; - private _workspaceConfigurationWatcher: ConfigWatcher>; + private _workspaceConfigurationWatcher: ConfigWatcher; private _workspaceConfigurationWatcherDisposables: IDisposable[] = []; private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); @@ -618,7 +618,7 @@ class WorkspaceConfiguration extends Disposable { }); } - get workspaceConfigurationModel(): WorkspaceConfigurationModel { + get workspaceConfigurationModel(): WorkspaceConfigurationModel { return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModel(); } @@ -632,15 +632,15 @@ class WorkspaceConfiguration extends Disposable { } } -class FolderConfiguration extends Disposable { +class FolderConfiguration extends Disposable { private static RELOAD_CONFIGURATION_DELAY = 50; - private bulkFetchFromWorkspacePromise: TPromise; - private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise> }; + private bulkFetchFromWorkspacePromise: TPromise; + private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise }; private reloadConfigurationScheduler: RunOnceScheduler; - private reloadConfigurationEventEmitter: Emitter> = new Emitter>(); + private reloadConfigurationEventEmitter: Emitter = new Emitter(); constructor(private folder: URI, private configFolderRelativePath: string, private scope: ConfigurationScope) { super(); @@ -649,17 +649,17 @@ class FolderConfiguration extends Disposable { this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.loadConfiguration().then(configuration => this.reloadConfigurationEventEmitter.fire(configuration), errors.onUnexpectedError), FolderConfiguration.RELOAD_CONFIGURATION_DELAY)); } - loadConfiguration(): TPromise> { + loadConfiguration(): TPromise { // Load workspace locals return this.loadWorkspaceConfigFiles().then(workspaceConfigFiles => { // Consolidate (support *.json files in the workspace settings folder) - const workspaceSettingsConfig = >workspaceConfigFiles[WORKSPACE_CONFIG_DEFAULT_PATH] || new FolderSettingsModel(null); - const otherConfigModels = Object.keys(workspaceConfigFiles).filter(key => key !== WORKSPACE_CONFIG_DEFAULT_PATH).map(key => >workspaceConfigFiles[key]); - return new FolderConfigurationModel(workspaceSettingsConfig, otherConfigModels, this.scope); + const workspaceSettingsConfig = workspaceConfigFiles[WORKSPACE_CONFIG_DEFAULT_PATH] || new FolderSettingsModel(null); + const otherConfigModels = Object.keys(workspaceConfigFiles).filter(key => key !== WORKSPACE_CONFIG_DEFAULT_PATH).map(key => workspaceConfigFiles[key]); + return new FolderConfigurationModel(workspaceSettingsConfig, otherConfigModels, this.scope); }); } - private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModel }> { + private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModel }> { // once: when invoked for the first time we fetch json files that contribute settings if (!this.bulkFetchFromWorkspacePromise) { this.bulkFetchFromWorkspacePromise = resolveStat(this.toResource(this.configFolderRelativePath)).then(stat => { @@ -686,7 +686,7 @@ class FolderConfiguration extends Disposable { return this.bulkFetchFromWorkspacePromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration)); } - public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise> { + public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { const events = event.changes; let affectedByChanges = false; @@ -744,18 +744,18 @@ class FolderConfiguration extends Disposable { }); } - private createConfigModel(content: IContent): ConfigurationModel { + private createConfigModel(content: IContent): ConfigurationModel { const path = this.toFolderRelativePath(content.resource); if (path === WORKSPACE_CONFIG_DEFAULT_PATH) { - return new FolderSettingsModel(content.value, content.resource.toString()); + return new FolderSettingsModel(content.value, content.resource.toString()); } else { const matches = /\/([^\.]*)*\.json/.exec(path); if (matches && matches[1]) { - return new ScopedConfigurationModel(content.value, content.resource.toString(), matches[1]); + return new ScopedConfigurationModel(content.value, content.resource.toString(), matches[1]); } } - return new CustomConfigurationModel(null); + return new CustomConfigurationModel(null); } private isWorkspaceConfigurationFile(folderRelativePath: string): boolean { From 60688ac08ee7f6e198a39c1a896bd1bf6800b032 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 11:55:21 +0200 Subject: [PATCH 026/394] Do not create a new empty model for merging --- .../platform/configuration/common/configurationModels.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 8a207935c4a..428b3a499a9 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -244,8 +244,8 @@ export class Configuration { } protected merge(): void { - this._globalConfiguration = new ConfigurationModel().merge(this._defaults).merge(this._user); - this._workspaceConsolidatedConfiguration = new ConfigurationModel().merge(this._globalConfiguration).merge(this._workspaceConfiguration); + this._globalConfiguration = this._defaults.merge(this._user); + this._workspaceConsolidatedConfiguration = this._globalConfiguration.merge(this._workspaceConfiguration); this._foldersConsolidatedConfigurations = new StrictResourceMap(); for (const folder of this.folders.keys()) { this.mergeFolder(folder); @@ -253,11 +253,11 @@ export class Configuration { } protected mergeFolder(folder: URI) { - this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); + this._foldersConsolidatedConfigurations.set(folder, this._workspaceConsolidatedConfiguration.merge(this.folders.get(folder))); } protected mergeMemory(folder: URI) { - this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder))); + this._foldersConsolidatedConfigurations.set(folder, this._workspaceConsolidatedConfiguration.merge(this.folders.get(folder))); } getValue(section: string = '', overrides: IConfigurationOverrides = {}): C { From 4765a8ab173c79d3117217eaa72b199be05ffcb3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 11:57:21 +0200 Subject: [PATCH 027/394] Configuration: Use proper names for getting sections and values --- src/vs/editor/standalone/browser/simpleServices.ts | 4 ++-- src/vs/platform/configuration/common/configurationModels.ts | 4 ++-- src/vs/platform/configuration/node/configurationService.ts | 6 +++--- src/vs/workbench/api/node/extHostConfiguration.ts | 4 ++-- .../services/configuration/common/configurationModels.ts | 6 +++--- .../services/configuration/node/configurationService.ts | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 3d84c45b5eb..91440df58d0 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -459,11 +459,11 @@ export class SimpleConfigurationService implements IConfigurationService { getConfiguration(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : void 0; const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; - return this.configuration().getValue(section, overrides); + return this.configuration().getSection(section, overrides); } public getValue(key: string, options?: IConfigurationOverrides): C { - return this.configuration().getValue2(key, options); + return this.configuration().getValue(key, options); } public updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 428b3a499a9..a469c8d7571 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -260,12 +260,12 @@ export class Configuration { this._foldersConsolidatedConfigurations.set(folder, this._workspaceConsolidatedConfiguration.merge(this.folders.get(folder))); } - getValue(section: string = '', overrides: IConfigurationOverrides = {}): C { + getSection(section: string = '', overrides: IConfigurationOverrides = {}): C { const configModel = this.getConsolidateConfigurationModel(overrides); return section ? configModel.getContentsFor(section) : configModel.contents; } - getValue2(key: string, overrides: IConfigurationOverrides = {}): any { + getValue(key: string, overrides: IConfigurationOverrides = {}): any { // make sure to clone the configuration so that the receiver does not tamper with the values const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index d7b5f65f730..893af01e558 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -67,11 +67,11 @@ export class ConfigurationService extends Disposable implements IConfigurationSe getConfiguration(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : void 0; const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; - return this.configuration.getValue(section, overrides); + return this.configuration.getSection(section, overrides); } getValue(key: string, overrides: IConfigurationOverrides): any { - return this.configuration.getValue2(key, overrides); + return this.configuration.getValue(key, overrides); } updateValue(key: string, value: any): TPromise @@ -113,7 +113,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe if (changedKeys.length) { const oldConfiguartion = this._configuration; this.reset(); - changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key), this._configuration.getValue2(key))); + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this._configuration.getValue(key))); if (changedKeys.length) { this.trigger(changedKeys, ConfigurationTarget.USER); } diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 031763f0ff4..6d3aee7186e 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -58,8 +58,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { getConfiguration(section?: string, resource?: URI): WorkspaceConfiguration { const config = section - ? lookUp(this._configuration.getValue(null, { resource }), section) - : this._configuration.getValue(null, { resource }); + ? lookUp(this._configuration.getSection(null, { resource }), section) + : this._configuration.getSection(null, { resource }); function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget { if (arg === void 0 || arg === null) { diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index df0c1b196ee..1223ae638a7 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -211,7 +211,7 @@ export class Configuration extends BaseConfiguration { this._user = user; this.merge(); - changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key), this.getValue2(key))); + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this.getValue(key))); return changedKeys; } return []; @@ -227,7 +227,7 @@ export class Configuration extends BaseConfiguration { this._workspaceConfiguration = workspaceConfiguration; this.merge(); - changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key), this.getValue2(key))); + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this.getValue(key))); return changedKeys; } return []; @@ -246,7 +246,7 @@ export class Configuration extends BaseConfiguration { this.folders.set(resource, configuration); this.mergeFolder(resource); - changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue2(key, { resource }), this.getValue2(key, { resource }))); + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key, { resource }), this.getValue(key, { resource }))); return changedKeys; } return []; diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 7e8884d88e7..9a1c04fb4be 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -135,13 +135,13 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat getConfiguration(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : void 0; const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; - const contents = this._configuration.getValue(section, overrides); + const contents = this._configuration.getSection(section, overrides); return typeof contents === 'object' ? { toJSON: () => this._configuration.toData(), ...contents } : contents; } getValue(key: string, overrides?: IConfigurationOverrides): T { - return this._configuration.getValue2(key, overrides); + return this._configuration.getValue(key, overrides); } updateValue(key: string, value: any): TPromise From cd4ef9fbacbb696a8e3589f0a8d210c906901ac4 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 12:04:48 +0200 Subject: [PATCH 028/394] Use freeze instead of clone to prevent users to tamper data --- .../common/configurationModels.ts | 54 +++++++++---------- .../test/common/configuration.model.test.ts | 6 +-- .../test/common/configurationModel.test.ts | 12 ++--- .../test/common/configurationModels.test.ts | 2 +- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index a469c8d7571..fcc05810bdb 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -31,22 +31,8 @@ export class ConfigurationModel implements IConfiguraionModel { return this._keys; } - public getContentsFor(section: string): V { - return objects.clone(this.contents[section]); - } - - public override(identifier: string): ConfigurationModel { - const result = new ConfigurationModel(); - const contents = objects.clone(this.contents); - if (this._overrides) { - for (const override of this._overrides) { - if (override.identifiers.indexOf(identifier) !== -1) { - merge(contents, override.contents, true); - } - } - } - result._contents = contents; - return result; + public getSectionContents(section: string): V { + return this.contents[section]; } public setValue(key: string, value: any) { @@ -64,6 +50,20 @@ export class ConfigurationModel implements IConfiguraionModel { } } + public override(identifier: string): ConfigurationModel { + const result = new ConfigurationModel(); + const contents = objects.clone(this.contents); + if (this._overrides) { + for (const override of this._overrides) { + if (override.identifiers.indexOf(identifier) !== -1) { + merge(contents, override.contents, true); + } + } + } + result._contents = contents; + return result; + } + public merge(other: ConfigurationModel, overwrite: boolean = true): ConfigurationModel { const mergedModel = new ConfigurationModel(); this.doMerge(mergedModel, this, overwrite); @@ -262,13 +262,12 @@ export class Configuration { getSection(section: string = '', overrides: IConfigurationOverrides = {}): C { const configModel = this.getConsolidateConfigurationModel(overrides); - return section ? configModel.getContentsFor(section) : configModel.contents; + return Object.freeze(section ? configModel.getSectionContents(section) : configModel.contents); } getValue(key: string, overrides: IConfigurationOverrides = {}): any { - // make sure to clone the configuration so that the receiver does not tamper with the values const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); - return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); + return Object.freeze(getConfigurationValue(consolidateConfigurationModel.contents, key)); } updateValue(key: string, value: any, overrides: IConfigurationOverrides = {}): void { @@ -297,18 +296,17 @@ export class Configuration { memory?: C value: C, } { - // make sure to clone the configuration so that the receiver does not tamper with the values const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration; - return { - default: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key)), - user: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key)), - workspace: objects.clone(this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0), //Check on workspace exists or not because _workspaceConfiguration is never null - workspaceFolder: objects.clone(folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0), - memory: objects.clone(getConfigurationValue(overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).contents : memoryConfigurationModel.contents, key)), - value: objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)) - }; + return Object.freeze({ + default: getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key), + user: getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key), + workspace: this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0, //Check on workspace exists or not because _workspaceConfiguration is never null + workspaceFolder: folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0, + memory: getConfigurationValue(overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).contents : memoryConfigurationModel.contents, key), + value: getConfigurationValue(consolidateConfigurationModel.contents, key) + }); } keys(): { diff --git a/src/vs/platform/configuration/test/common/configuration.model.test.ts b/src/vs/platform/configuration/test/common/configuration.model.test.ts index 65555f8e9f2..ea0266bd500 100644 --- a/src/vs/platform/configuration/test/common/configuration.model.test.ts +++ b/src/vs/platform/configuration/test/common/configuration.model.test.ts @@ -67,16 +67,16 @@ suite('Configuration', () => { test('Test contents while getting an existing property', () => { let testObject = new ConfigurationModel({ 'a': 1 }); - assert.deepEqual(testObject.getContentsFor('a'), 1); + assert.deepEqual(testObject.getSectionContents('a'), 1); testObject = new ConfigurationModel({ 'a': { 'b': 1 } }); - assert.deepEqual(testObject.getContentsFor('a'), { 'b': 1 }); + assert.deepEqual(testObject.getSectionContents('a'), { 'b': 1 }); }); test('Test contents are undefined for non existing properties', () => { const testObject = new ConfigurationModel({ awesome: true }); - assert.deepEqual(testObject.getContentsFor('unknownproperty'), undefined); + assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); }); test('Test override gives all content merged with overrides', () => { diff --git a/src/vs/platform/configuration/test/common/configurationModel.test.ts b/src/vs/platform/configuration/test/common/configurationModel.test.ts index 3cc4f519bc2..b79b8cbadcf 100644 --- a/src/vs/platform/configuration/test/common/configurationModel.test.ts +++ b/src/vs/platform/configuration/test/common/configurationModel.test.ts @@ -61,10 +61,10 @@ suite('Configuration', () => { test('Test contents while getting an existing property', () => { let testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1 })); - assert.deepEqual(testObject.getContentsFor('a'), 1); + assert.deepEqual(testObject.getSectionContents('a'), 1); testObject = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } })); - assert.deepEqual(testObject.getContentsFor('a'), { 'b': 1 }); + assert.deepEqual(testObject.getSectionContents('a'), { 'b': 1 }); }); test('Test contents are undefined for non existing properties', () => { @@ -72,13 +72,13 @@ suite('Configuration', () => { awesome: true })); - assert.deepEqual(testObject.getContentsFor('unknownproperty'), undefined); + assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); }); test('Test contents are undefined for undefined config', () => { const testObject = new CustomConfigurationModel(null); - assert.deepEqual(testObject.getContentsFor('unknownproperty'), undefined); + assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); }); test('Test configWithOverrides gives all content merged with overrides', () => { @@ -125,7 +125,7 @@ suite('Configuration', () => { } } }); - assert.equal(true, new DefaultConfigurationModel().getContentsFor('a')); + assert.equal(true, new DefaultConfigurationModel().getSectionContents('a')); }); test('Test registering the language property', () => { @@ -142,7 +142,7 @@ suite('Configuration', () => { } } }); - assert.equal(undefined, new DefaultConfigurationModel().getContentsFor('[a]')); + assert.equal(undefined, new DefaultConfigurationModel().getSectionContents('[a]')); }); }); \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts index a6755918258..14e684e145e 100644 --- a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts +++ b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts @@ -17,7 +17,7 @@ suite('ConfigurationService - Model', () => { const testObject = new FolderConfigurationModel(settingsConfig, [], ConfigurationScope.WINDOW); - assert.equal(testObject.getContentsFor('task'), undefined); + assert.equal(testObject.getSectionContents('task'), undefined); }); test('Test consolidate (settings and tasks)', () => { From fd70f31b703f27e8cdff476bb2a69e8ab6b75a53 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 6 Oct 2017 12:31:27 +0200 Subject: [PATCH 029/394] Update workspace configuration with memory configuration --- .../configuration/common/configurationModels.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index fcc05810bdb..c77ec098128 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -219,7 +219,6 @@ export class Configuration { private _globalConfiguration: ConfigurationModel; private _workspaceConsolidatedConfiguration: ConfigurationModel; protected _foldersConsolidatedConfigurations: StrictResourceMap; - protected _memoryConsolidatedConfigurations: StrictResourceMap; constructor(protected _defaults: ConfigurationModel, protected _user: ConfigurationModel, @@ -245,18 +244,18 @@ export class Configuration { protected merge(): void { this._globalConfiguration = this._defaults.merge(this._user); - this._workspaceConsolidatedConfiguration = this._globalConfiguration.merge(this._workspaceConfiguration); + this.updateWorkspaceConsolidateConfiguration(); this._foldersConsolidatedConfigurations = new StrictResourceMap(); for (const folder of this.folders.keys()) { this.mergeFolder(folder); } } - protected mergeFolder(folder: URI) { - this._foldersConsolidatedConfigurations.set(folder, this._workspaceConsolidatedConfiguration.merge(this.folders.get(folder))); + private updateWorkspaceConsolidateConfiguration() { + this._workspaceConsolidatedConfiguration = this._globalConfiguration.merge(this._workspaceConfiguration).merge(this._memoryConfiguration); } - protected mergeMemory(folder: URI) { + protected mergeFolder(folder: URI) { this._foldersConsolidatedConfigurations.set(folder, this._workspaceConsolidatedConfiguration.merge(this.folders.get(folder))); } @@ -281,11 +280,16 @@ export class Configuration { } else { memoryConfiguration = this._memoryConfiguration; } + if (value === void 0) { memoryConfiguration.removeValue(key); } else { memoryConfiguration.setValue(key, value); } + + if (!overrides.resource) { + this.updateWorkspaceConsolidateConfiguration(); + } } lookup(key: string, overrides: IConfigurationOverrides = {}): { @@ -335,7 +339,7 @@ export class Configuration { } if (!resource) { - return this._workspaceConsolidatedConfiguration.merge(this._memoryConfiguration); + return this._workspaceConsolidatedConfiguration; } let consolidateConfiguration = this._workspaceConsolidatedConfiguration; From 94fb905f00f598bfc9945a22ad5ecbe4d85eab70 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 9 Oct 2017 22:18:42 +0200 Subject: [PATCH 030/394] enable dbus on linux docker containers --- build/tfs/linux/ia32/Dockerfile | 5 ++++- build/tfs/linux/x64/Dockerfile | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/build/tfs/linux/ia32/Dockerfile b/build/tfs/linux/ia32/Dockerfile index b309a1e940f..25d621d99fb 100644 --- a/build/tfs/linux/ia32/Dockerfile +++ b/build/tfs/linux/ia32/Dockerfile @@ -40,6 +40,9 @@ ADD xvfb.init /etc/init.d/xvfb RUN chmod +x /etc/init.d/xvfb RUN update-rc.d xvfb defaults +# dbus +RUN ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon + # nvm ENV NVM_DIR /usr/local/nvm RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash @@ -47,4 +50,4 @@ RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | b # for libsecret ENV PKG_CONFIG_PATH /usr/lib/i386-linux-gnu/pkgconfig -CMD (service xvfb start; export DISPLAY=:10; ./start.sh) \ No newline at end of file +CMD (service xvfb start; service dbus start; export DISPLAY=:10; ./start.sh) \ No newline at end of file diff --git a/build/tfs/linux/x64/Dockerfile b/build/tfs/linux/x64/Dockerfile index 4fef9acb19a..ae9190c29db 100644 --- a/build/tfs/linux/x64/Dockerfile +++ b/build/tfs/linux/x64/Dockerfile @@ -36,8 +36,11 @@ ADD xvfb.init /etc/init.d/xvfb RUN chmod +x /etc/init.d/xvfb RUN update-rc.d xvfb defaults +# dbus +RUN ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon + # nvm ENV NVM_DIR /usr/local/nvm RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash -CMD (service xvfb start; export DISPLAY=:10; ./start.sh) \ No newline at end of file +CMD (service xvfb start; service dbus start; export DISPLAY=:10; ./start.sh) \ No newline at end of file From a05536bbf694956283fb76dc7aa3242f1602015b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Oct 2017 10:45:44 +0200 Subject: [PATCH 031/394] fix keys implementation --- test/smoke/src/spectron/client.ts | 71 ++++++++++++++++--------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index 20c4f463e2b..324dc9c8a2f 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -17,94 +17,95 @@ export class SpectronClient { private retryCount: number; private readonly retryDuration = 100; // in milliseconds - constructor(public spectron: Application, private application: SpectronApplication) { + constructor(readonly spectron: Application, private application: SpectronApplication) { this.retryCount = (WAIT_TIME * 1000) / this.retryDuration; } - public windowByIndex(index: number): Promise { + windowByIndex(index: number): Promise { return this.spectron.client.windowByIndex(index); } - public async keys(keys: string[] | string, capture: boolean = true): Promise { - return Promise.resolve(this.spectron.client.keys(keys)); + keys(keys: string[] | string, capture: boolean = true): Promise { + this.spectron.client.keys(keys); + return Promise.resolve(); } - public async getText(selector: string, capture: boolean = true): Promise { + async getText(selector: string, capture: boolean = true): Promise { return this.spectron.client.getText(selector); } - public async waitForText(selector: string, text?: string, accept?: (result: string) => boolean): Promise { + async waitForText(selector: string, text?: string, accept?: (result: string) => boolean): Promise { accept = accept ? accept : result => text !== void 0 ? text === result : !!result; return this.waitFor(() => this.spectron.client.getText(selector), accept, `getText with selector ${selector}`); } - public async waitForTextContent(selector: string, textContent?: string, accept?: (result: string) => boolean): Promise { + async waitForTextContent(selector: string, textContent?: string, accept?: (result: string) => boolean): Promise { accept = accept ? accept : (result => textContent !== void 0 ? textContent === result : !!result); const fn = async () => await this.spectron.client.selectorExecute(selector, div => Array.isArray(div) ? div[0].textContent : div.textContent); return this.waitFor(fn, s => accept!(typeof s === 'string' ? s : ''), `getTextContent with selector ${selector}`); } - public async waitForValue(selector: string, value?: string, accept?: (result: string) => boolean): Promise { + async waitForValue(selector: string, value?: string, accept?: (result: string) => boolean): Promise { accept = accept ? accept : result => value !== void 0 ? value === result : !!result; return this.waitFor(() => this.spectron.client.getValue(selector), accept, `getValue with selector ${selector}`); } - public async waitForHTML(selector: string, accept: (result: string) => boolean = (result: string) => !!result): Promise { + async waitForHTML(selector: string, accept: (result: string) => boolean = (result: string) => !!result): Promise { return this.waitFor(() => this.spectron.client.getHTML(selector), accept, `getHTML with selector ${selector}`); } - public async waitAndClick(selector: string): Promise { + async waitAndClick(selector: string): Promise { return this.waitFor(() => this.spectron.client.click(selector), void 0, `click with selector ${selector}`); } - public async click(selector: string): Promise { + async click(selector: string): Promise { return this.spectron.client.click(selector); } - public async doubleClickAndWait(selector: string, capture: boolean = true): Promise { + async doubleClickAndWait(selector: string, capture: boolean = true): Promise { return this.waitFor(() => this.spectron.client.doubleClick(selector), void 0, `doubleClick with selector ${selector}`); } - public async leftClick(selector: string, xoffset: number, yoffset: number, capture: boolean = true): Promise { + async leftClick(selector: string, xoffset: number, yoffset: number, capture: boolean = true): Promise { return this.spectron.client.leftClick(selector, xoffset, yoffset); } - public async rightClick(selector: string, capture: boolean = true): Promise { + async rightClick(selector: string, capture: boolean = true): Promise { return this.spectron.client.rightClick(selector); } - public async moveToObject(selector: string, capture: boolean = true): Promise { + async moveToObject(selector: string, capture: boolean = true): Promise { return this.spectron.client.moveToObject(selector); } - public async waitAndmoveToObject(selector: string): Promise { + async waitAndmoveToObject(selector: string): Promise { return this.waitFor(() => this.spectron.client.moveToObject(selector), void 0, `move to object with selector ${selector}`); } - public async setValue(selector: string, text: string, capture: boolean = true): Promise { + async setValue(selector: string, text: string, capture: boolean = true): Promise { return this.spectron.client.setValue(selector, text); } - public async waitForElements(selector: string, accept: (result: Element[]) => boolean = result => result.length > 0): Promise { + async waitForElements(selector: string, accept: (result: Element[]) => boolean = result => result.length > 0): Promise { return this.waitFor>(() => this.spectron.client.elements(selector), result => accept(result.value), `elements with selector ${selector}`) .then(result => result.value); } - public async waitForElement(selector: string, accept: (result: Element | undefined) => boolean = result => !!result): Promise { + async waitForElement(selector: string, accept: (result: Element | undefined) => boolean = result => !!result): Promise { return this.waitFor>(() => this.spectron.client.element(selector), result => accept(result ? result.value : void 0), `element with selector ${selector}`) .then(result => result.value); } - public async waitForVisibility(selector: string, accept: (result: boolean) => boolean = result => result): Promise { + async waitForVisibility(selector: string, accept: (result: boolean) => boolean = result => result): Promise { return this.waitFor(() => this.spectron.client.isVisible(selector), accept, `isVisible with selector ${selector}`); } - public async element(selector: string): Promise { + async element(selector: string): Promise { return this.spectron.client.element(selector) .then(result => result.value); } - public async waitForActiveElement(selector: string): Promise { + async waitForActiveElement(selector: string): Promise { return this.waitFor( () => this.spectron.client.execute(s => document.activeElement.matches(s), selector), r => r.value, @@ -112,49 +113,49 @@ export class SpectronClient { ); } - public async waitForAttribute(selector: string, attribute: string, accept: (result: string) => boolean = result => !!result): Promise { + async waitForAttribute(selector: string, attribute: string, accept: (result: string) => boolean = result => !!result): Promise { return this.waitFor(() => this.spectron.client.getAttribute(selector), accept, `attribute with selector ${selector}`); } - public async dragAndDrop(sourceElem: string, destinationElem: string, capture: boolean = true): Promise { + async dragAndDrop(sourceElem: string, destinationElem: string, capture: boolean = true): Promise { return this.spectron.client.dragAndDrop(sourceElem, destinationElem); } - public async selectByValue(selector: string, value: string, capture: boolean = true): Promise { + async selectByValue(selector: string, value: string, capture: boolean = true): Promise { return this.spectron.client.selectByValue(selector, value); } - public async getValue(selector: string, capture: boolean = true): Promise { + async getValue(selector: string, capture: boolean = true): Promise { return this.spectron.client.getValue(selector); } - public async getAttribute(selector: string, attribute: string, capture: boolean = true): Promise { + async getAttribute(selector: string, attribute: string, capture: boolean = true): Promise { return Promise.resolve(this.spectron.client.getAttribute(selector, attribute)); } - public clearElement(selector: string): any { + clearElement(selector: string): any { return this.spectron.client.clearElement(selector); } - public buttonDown(): any { + buttonDown(): any { return this.spectron.client.buttonDown(); } - public buttonUp(): any { + buttonUp(): any { return this.spectron.client.buttonUp(); } - public async isVisible(selector: string, capture: boolean = true): Promise { + async isVisible(selector: string, capture: boolean = true): Promise { return this.spectron.client.isVisible(selector); } - public async getTitle(): Promise { + async getTitle(): Promise { return this.spectron.client.getTitle(); } private running = false; - public async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string, retryCount?: number): Promise; - public async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string, retryCount?: number): Promise { + async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string, retryCount?: number): Promise; + async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string, retryCount?: number): Promise { if (this.running) { throw new Error('Not allowed to run nested waitFor calls!'); } @@ -190,7 +191,7 @@ export class SpectronClient { } } - public type(text: string): Promise { + type(text: string): Promise { return new Promise((res) => { let textSplit = text.split(' '); From bffbd010474200acd7419b22a6a57b685999e3c7 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Oct 2017 14:18:55 +0200 Subject: [PATCH 032/394] test: drop usages of keys() for typing --- test/smoke/src/areas/css/css.test.ts | 4 +- test/smoke/src/areas/debug/debug.ts | 4 +- test/smoke/src/areas/editor/editor.test.ts | 11 +-- test/smoke/src/areas/editor/editor.ts | 68 ++++++++----- test/smoke/src/areas/editor/quickoutline.ts | 2 +- test/smoke/src/areas/editor/rename.ts | 26 ----- .../smoke/src/areas/explorer/explorer.test.ts | 6 +- test/smoke/src/areas/explorer/explorer.ts | 2 +- test/smoke/src/areas/extensions/extensions.ts | 15 ++- test/smoke/src/areas/git/git.test.ts | 4 +- test/smoke/src/areas/git/scm.ts | 9 +- .../src/areas/multiroot/multiroot.test.ts | 3 +- .../src/areas/preferences/keybindings.ts | 34 +++---- .../src/areas/preferences/preferences.test.ts | 3 +- test/smoke/src/areas/preferences/settings.ts | 30 +++--- test/smoke/src/areas/problems/problems.ts | 4 +- test/smoke/src/areas/quickopen/quickopen.ts | 27 ++---- test/smoke/src/areas/search/search.test.ts | 10 +- test/smoke/src/areas/search/search.ts | 97 ++++++++----------- .../src/areas/statusbar/statusbar.test.ts | 2 +- test/smoke/src/areas/terminal/terminal.ts | 17 ++-- .../areas/workbench/data-migration.test.ts | 5 +- test/smoke/src/areas/workbench/workbench.ts | 8 +- test/smoke/src/spectron/application.ts | 4 +- test/smoke/src/spectron/client.ts | 38 ++++---- 25 files changed, 182 insertions(+), 251 deletions(-) delete mode 100644 test/smoke/src/areas/editor/rename.ts diff --git a/test/smoke/src/areas/css/css.test.ts b/test/smoke/src/areas/css/css.test.ts index 7b064431e0a..d0b4c01b201 100644 --- a/test/smoke/src/areas/css/css.test.ts +++ b/test/smoke/src/areas/css/css.test.ts @@ -21,7 +21,7 @@ describe('CSS', () => { it('verifies warnings for the empty rule', async () => { await app.workbench.quickopen.openFile('style.css'); - await app.client.type('.foo{}'); + await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); let warning = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING)); await app.screenCapturer.capture('CSS Warning in editor'); @@ -37,7 +37,7 @@ describe('CSS', () => { it('verifies that warning becomes an error once setting changed', async () => { await app.workbench.settingsEditor.addUserSetting('css.lint.emptyRules', '"error"'); await app.workbench.quickopen.openFile('style.css'); - await app.client.type('.foo{}'); + await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); let error = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR)); await app.screenCapturer.capture('CSS Error in editor'); diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index a47299176d2..7537ca1e69a 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -41,7 +41,7 @@ export class Debug extends Viewlet { } async openDebugViewlet(): Promise { - await this.spectron.command('workbench.view.debug'); + await this.spectron.runCommand('workbench.view.debug'); await this.spectron.client.waitForElement(DEBUG_VIEW); } @@ -114,8 +114,8 @@ export class Debug extends Viewlet { async waitForReplCommand(text: string, accept: (result: string) => boolean): Promise { await this.spectron.workbench.quickopen.runCommand('Debug: Focus Debug Console'); await this.spectron.client.waitForActiveElement(REPL_FOCUSED); + await this.spectron.client.setValue(REPL_FOCUSED, text); - await this.spectron.client.keys(text); // Wait for the keys to be picked up by the editor model such that repl evalutes what just got typed await this.spectron.workbench.editor.waitForEditorContents('debug:input', s => s.indexOf(text) >= 0); await this.spectron.client.keys(['Enter', 'NULL']); diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index 38634bb5a92..3ceb7d6f0a4 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; - import { SpectronApplication } from '../../spectron/application'; describe('Editor', () => { @@ -31,14 +29,9 @@ describe('Editor', () => { it(`renames local 'app' variable`, async function () { await app.workbench.quickopen.openFile('www'); - - const selector = await app.workbench.editor.getSelector('app', 7); - const rename = await app.workbench.editor.rename('app', 7); - await rename.rename('newApp'); - - const actual = await app.client.waitForText(selector, 'newApp'); + await app.workbench.editor.rename('www', 7, 'app', 'newApp'); + await app.workbench.editor.waitForEditorContents('www', contents => contents.indexOf('newApp') > -1); await app.screenCapturer.capture('Rename result'); - assert.equal(actual, 'newApp'); }); it('folds/unfolds the code correctly', async function () { diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 5c81f8f47bd..51c27c84d0a 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -6,7 +6,9 @@ import { SpectronApplication } from '../../spectron/application'; import { QuickOutline } from './quickoutline'; import { References } from './peek'; -import { Rename } from './rename'; + +const RENAME_BOX = '.monaco-editor .monaco-editor.rename-box'; +const RENAME_INPUT = `${RENAME_BOX} .rename-input`; export class Editor { @@ -18,13 +20,13 @@ export class Editor { constructor(private spectron: SpectronApplication) { } - public async openOutline(): Promise { + async openOutline(): Promise { const outline = new QuickOutline(this.spectron); await outline.open(); return outline; } - public async findReferences(term: string, line: number): Promise { + async findReferences(term: string, line: number): Promise { await this.clickOnTerm(term, line); await this.spectron.workbench.quickopen.runCommand('Find All References'); const references = new References(this.spectron); @@ -32,20 +34,22 @@ export class Editor { return references; } - public async rename(term: string, line: number): Promise { - await this.clickOnTerm(term, line); + async rename(filename: string, line: number, from: string, to: string): Promise { + await this.clickOnTerm(from, line); await this.spectron.workbench.quickopen.runCommand('Rename Symbol'); - const rename = new Rename(term, this.spectron); - await rename.waitUntilOpen(); - return rename; + + await this.spectron.client.waitForActiveElement(RENAME_INPUT); + await this.spectron.client.setValue(RENAME_INPUT, to); + + await this.spectron.client.keys(['Enter', 'NULL']); } - public async gotoDefinition(term: string, line: number): Promise { + async gotoDefinition(term: string, line: number): Promise { await this.clickOnTerm(term, line); await this.spectron.workbench.quickopen.runCommand('Go to Definition'); } - public async peekDefinition(term: string, line: number): Promise { + async peekDefinition(term: string, line: number): Promise { await this.clickOnTerm(term, line); await this.spectron.workbench.quickopen.runCommand('Peek Definition'); const peek = new References(this.spectron); @@ -53,7 +57,7 @@ export class Editor { return peek; } - public async waitForHighlightingLine(line: number): Promise { + async waitForHighlightingLine(line: number): Promise { const currentLineIndex = await this.getViewLineIndex(line); if (currentLineIndex) { await this.spectron.client.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`); @@ -62,60 +66,72 @@ export class Editor { throw new Error('Cannot find line ' + line); } - public async getSelector(term: string, line: number): Promise { + async getSelector(term: string, line: number): Promise { const lineIndex = await this.getViewLineIndex(line); const classNames = await this.spectron.client.waitFor(() => this.getClassSelectors(term, lineIndex), classNames => classNames && !!classNames.length, 'Getting class names for editor lines'); return `${Editor.VIEW_LINES}>:nth-child(${lineIndex}) span span.${classNames[0]}`; } - public async foldAtLine(line: number): Promise { + async foldAtLine(line: number): Promise { const lineIndex = await this.getViewLineIndex(line); await this.spectron.client.waitAndClick(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); await this.spectron.client.waitForElement(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); } - public async unfoldAtLine(line: number): Promise { + async unfoldAtLine(line: number): Promise { const lineIndex = await this.getViewLineIndex(line); await this.spectron.client.waitAndClick(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); await this.spectron.client.waitForElement(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); } - public async waitUntilHidden(line: number): Promise { + async waitUntilHidden(line: number): Promise { await this.spectron.client.waitFor(() => this.getViewLineIndexWithoutWait(line), lineNumber => lineNumber === undefined, 'Waiting until line number is hidden'); } - public async waitUntilShown(line: number): Promise { + async waitUntilShown(line: number): Promise { await this.getViewLineIndex(line); } - public async clickOnTerm(term: string, line: number): Promise { + async clickOnTerm(term: string, line: number): Promise { const selector = await this.getSelector(term, line); await this.spectron.client.waitAndClick(selector); } - public async waitForTypeInEditor(filename: string, text: string): Promise { - const editor = `.monaco-editor[data-uri$="${filename}"]`; - await this.spectron.client.waitAndClick(editor); + async waitForTypeInEditor(filename: string, text: string, selectorPrefix = ''): Promise { + const editor = [ + selectorPrefix || '', + `.monaco-editor[data-uri$="${filename}"]` + ].join(' '); + + await this.spectron.client.element(editor); const textarea = `${editor} textarea`; await this.spectron.client.waitForActiveElement(textarea); - await this.spectron.client.type(text); + // https://github.com/Microsoft/vscode/issues/34203#issuecomment-334441786 + for (let i = 0; i < text.length; i++) { + this.spectron.client.spectron.client.keys([text[i], 'NULL']); + await new Promise(c => setTimeout(c, 50)); + } - await this.waitForEditorContents(filename, c => c.indexOf(text) > -1); + await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } - public async waitForEditorContents(filename: string, accept: (contents: string) => boolean): Promise { - const selector = `.monaco-editor[data-uri$="${filename}"] .view-lines`; + async waitForEditorContents(filename: string, accept: (contents: string) => boolean, selectorPrefix = ''): Promise { + const selector = [ + selectorPrefix || '', + `.monaco-editor[data-uri$="${filename}"] .view-lines` + ].join(' '); + return this.spectron.client.waitForTextContent(selector, undefined, c => accept(c.replace(/\u00a0/g, ' '))); } - public async waitForActiveEditor(filename: string): Promise { + async waitForActiveEditor(filename: string): Promise { const selector = `.editor-container .monaco-editor[data-uri$="${filename}"] textarea`; return this.spectron.client.waitForActiveElement(selector); } - // public async waitForActiveEditorFirstLineText(filename: string): Promise { + // async waitForActiveEditorFirstLineText(filename: string): Promise { // const selector = `.editor-container .monaco-editor[data-uri$="${filename}"] textarea`; // const result = await this.spectron.client.waitFor( // () => this.spectron.client.spectron.client.execute(s => { diff --git a/test/smoke/src/areas/editor/quickoutline.ts b/test/smoke/src/areas/editor/quickoutline.ts index 35fab316ee0..852bd8b9145 100644 --- a/test/smoke/src/areas/editor/quickoutline.ts +++ b/test/smoke/src/areas/editor/quickoutline.ts @@ -14,7 +14,7 @@ export class QuickOutline extends QuickOpen { public async open(): Promise { await this.spectron.client.waitFor(async () => { - await this.spectron.command('workbench.action.gotoSymbol'); + await this.spectron.runCommand('workbench.action.gotoSymbol'); const entry = await this.spectron.client.element('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry'); if (entry) { const text = await this.spectron.client.getText('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry .monaco-icon-label .label-name .monaco-highlighted-label span'); diff --git a/test/smoke/src/areas/editor/rename.ts b/test/smoke/src/areas/editor/rename.ts deleted file mode 100644 index 521798c9ba3..00000000000 --- a/test/smoke/src/areas/editor/rename.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { SpectronApplication } from '../../spectron/application'; - -export class Rename { - - private static RENAME_BOX = '.monaco-editor .monaco-editor.rename-box'; - private static RENAME_INPUT = `${Rename.RENAME_BOX} .rename-input`; - - constructor(private term: string, private spectron: SpectronApplication) { - } - - public async waitUntilOpen(): Promise { - await this.spectron.client.waitForVisibility(Rename.RENAME_BOX); - await this.spectron.client.waitForValue(Rename.RENAME_INPUT, this.term); - } - - public async rename(newTerm: string): Promise { - await this.spectron.client.type(newTerm); - await this.spectron.client.keys(['Enter', 'NULL']); - await this.spectron.client.waitForVisibility(Rename.RENAME_BOX, result => !result); - } -} \ No newline at end of file diff --git a/test/smoke/src/areas/explorer/explorer.test.ts b/test/smoke/src/areas/explorer/explorer.test.ts index 658be5959b7..581851e0ab8 100644 --- a/test/smoke/src/areas/explorer/explorer.test.ts +++ b/test/smoke/src/areas/explorer/explorer.test.ts @@ -21,8 +21,7 @@ describe('Explorer', () => { 'jsconfig.json' ]; - await app.workbench.quickopen.openQuickOpen(); - await app.client.type('.js'); + await app.workbench.quickopen.openQuickOpen('.js'); await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m))); await app.client.keys(['Escape', 'NULL']); }); @@ -34,8 +33,7 @@ describe('Explorer', () => { 'package.json' ]; - await app.workbench.quickopen.openQuickOpen(); - await app.client.type('a.s'); + await app.workbench.quickopen.openQuickOpen('a.s'); await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m))); await app.client.keys(['Escape', 'NULL']); }); diff --git a/test/smoke/src/areas/explorer/explorer.ts b/test/smoke/src/areas/explorer/explorer.ts index e799bc0f225..1dd454462ac 100644 --- a/test/smoke/src/areas/explorer/explorer.ts +++ b/test/smoke/src/areas/explorer/explorer.ts @@ -17,7 +17,7 @@ export class Explorer extends Viewlet { } public openExplorerView(): Promise { - return this.spectron.command('workbench.view.explorer'); + return this.spectron.runCommand('workbench.view.explorer'); } public getOpenEditorsViewTitle(): Promise { diff --git a/test/smoke/src/areas/extensions/extensions.ts b/test/smoke/src/areas/extensions/extensions.ts index 62e0bb936db..d0c3f97320d 100644 --- a/test/smoke/src/areas/extensions/extensions.ts +++ b/test/smoke/src/areas/extensions/extensions.ts @@ -6,6 +6,8 @@ import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; +const SEARCH_BOX = 'div.extensions-viewlet[id="workbench.view.extensions"] input.search-box'; + export class Extensions extends Viewlet { constructor(spectron: SpectronApplication) { @@ -13,21 +15,18 @@ export class Extensions extends Viewlet { } async openExtensionsViewlet(): Promise { - await this.spectron.command('workbench.view.extensions'); + await this.spectron.runCommand('workbench.view.extensions'); await this.waitForExtensionsViewlet(); } async waitForExtensionsViewlet(): Promise { - await this.spectron.client.waitForActiveElement('div.extensions-viewlet[id="workbench.view.extensions"] input.search-box'); + await this.spectron.client.waitForActiveElement(SEARCH_BOX); } async searchForExtension(name: string): Promise { - const searchBoxSelector = 'div.extensions-viewlet[id="workbench.view.extensions"] .search-box'; - - await this.spectron.client.clearElement(searchBoxSelector); - await this.spectron.client.click(searchBoxSelector); - await this.spectron.client.waitForActiveElement('div.extensions-viewlet[id="workbench.view.extensions"] input.search-box'); - await this.spectron.client.keys(name); + await this.spectron.client.click(SEARCH_BOX); + await this.spectron.client.waitForActiveElement(SEARCH_BOX); + await this.spectron.client.setValue(SEARCH_BOX, name); } async installExtension(name: string): Promise { diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index 73d5d99f5e2..57c0240b1d4 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -19,11 +19,11 @@ describe('Git', () => { await app.workbench.scm.openSCMViewlet(); await app.workbench.quickopen.openFile('app.js'); - await app.client.type('.foo{}'); + await app.workbench.editor.waitForTypeInEditor('app.js', '.foo{}'); await app.workbench.saveOpenedFile(); await app.workbench.quickopen.openFile('index.jade'); - await app.client.type('hello world'); + await app.workbench.editor.waitForTypeInEditor('index.jade', 'hello world'); await app.workbench.saveOpenedFile(); await app.workbench.scm.refreshSCMViewlet(); diff --git a/test/smoke/src/areas/git/scm.ts b/test/smoke/src/areas/git/scm.ts index 90642445171..94576417744 100644 --- a/test/smoke/src/areas/git/scm.ts +++ b/test/smoke/src/areas/git/scm.ts @@ -30,7 +30,7 @@ export class SCM extends Viewlet { } async openSCMViewlet(): Promise { - await this.spectron.command('workbench.view.scm'); + await this.spectron.runCommand('workbench.view.scm'); await this.spectron.client.waitForElement(SCM_INPUT); } @@ -95,8 +95,9 @@ export class SCM extends Viewlet { } async commit(message: string): Promise { - await this.spectron.client.click(SCM_INPUT); - await this.spectron.client.type(message); - await this.spectron.client.click(COMMIT_COMMAND); + await this.spectron.client.waitAndClick(SCM_INPUT); + await this.spectron.client.waitForActiveElement(SCM_INPUT); + await this.spectron.client.setValue(SCM_INPUT, message); + await this.spectron.client.waitAndClick(COMMIT_COMMAND); } } \ No newline at end of file diff --git a/test/smoke/src/areas/multiroot/multiroot.test.ts b/test/smoke/src/areas/multiroot/multiroot.test.ts index 92c50c070e7..f341f3da137 100644 --- a/test/smoke/src/areas/multiroot/multiroot.test.ts +++ b/test/smoke/src/areas/multiroot/multiroot.test.ts @@ -16,8 +16,7 @@ describe('Multiroot', () => { after(() => app.stop()); it('shows results from all folders', async function () { - await app.workbench.quickopen.openQuickOpen(); - await app.workbench.quickopen.type('*.*'); + await app.workbench.quickopen.openQuickOpen('*.*'); await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6); await app.workbench.quickopen.closeQuickOpen(); diff --git a/test/smoke/src/areas/preferences/keybindings.ts b/test/smoke/src/areas/preferences/keybindings.ts index c6c7431ff19..1de2eba3470 100644 --- a/test/smoke/src/areas/preferences/keybindings.ts +++ b/test/smoke/src/areas/preferences/keybindings.ts @@ -5,36 +5,24 @@ import { SpectronApplication } from '../../spectron/application'; +const SEARCH_INPUT = '.settings-search-input input'; + export class KeybindingsEditor { - constructor(private spectron: SpectronApplication) { - // noop - } + constructor(private spectron: SpectronApplication) { } - public async openKeybindings(): Promise { - await this.spectron.command('workbench.action.openGlobalKeybindings'); - await this.spectron.client.waitForElement('.settings-search-input .synthetic-focus'); - } + async updateKeybinding(command: string, keys: string[], ariaLabel: string): Promise { + await this.spectron.runCommand('workbench.action.openGlobalKeybindings'); + await this.spectron.client.waitForActiveElement(SEARCH_INPUT); + await this.spectron.client.setValue(SEARCH_INPUT, command); - public async search(text: string, select: boolean = false): Promise { - await this.spectron.client.type(text); - if (select) { - await this.spectron.client.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item'); - await this.spectron.client.waitForElement('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item.focused.selected'); - } - } + await this.spectron.client.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item'); + await this.spectron.client.waitForElement('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item.focused.selected'); - public async openDefineKeybindingDialog(): Promise { await this.spectron.client.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item .action-item .icon.add'); - return this.spectron.client.waitForElement('.defineKeybindingWidget .monaco-inputbox.synthetic-focus'); - } + await this.spectron.client.waitForElement('.defineKeybindingWidget .monaco-inputbox.synthetic-focus'); - public async updateKeybinding(command: string, keys: string[], ariaLabel: string): Promise { - await this.search(command, true); - await this.openDefineKeybindingDialog(); - await this.spectron.client.keys(keys); - await this.spectron.client.keys(['Enter', 'NULL']); + await this.spectron.client.keys([...keys, 'NULL', 'Enter', 'NULL']); await this.spectron.client.waitForElement(`div[aria-label="Keybindings"] div[aria-label="Keybinding is ${ariaLabel}."]`); } - } \ No newline at end of file diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index 3074be7fd47..4a9939bf2b3 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -30,8 +30,7 @@ describe('Preferences', () => { it(`changes 'workbench.action.toggleSidebarPosition' command key binding and verifies it`, async function () { assert.ok(await app.workbench.activitybar.getActivityBar(ActivityBarPosition.LEFT), 'Activity bar should be positioned on the left.'); - await app.workbench.keybindingsEditor.openKeybindings(); - await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', ['Control', 'u', 'NULL'], 'Control+U'); + await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', ['Control', 'u'], 'Control+U'); await app.client.keys(['Control', 'u', 'NULL']); assert.ok(await app.workbench.activitybar.getActivityBar(ActivityBarPosition.RIGHT), 'Activity bar was not moved to right after toggling its position.'); diff --git a/test/smoke/src/areas/preferences/settings.ts b/test/smoke/src/areas/preferences/settings.ts index 24fd9d63e12..ce28c1b2c9e 100644 --- a/test/smoke/src/areas/preferences/settings.ts +++ b/test/smoke/src/areas/preferences/settings.ts @@ -10,30 +10,26 @@ export enum ActivityBarPosition { RIGHT = 1 }; +const SEARCH_INPUT = '.settings-search-input input'; +const EDITOR = '.editable-preferences-editor-container .monaco-editor textarea'; + export class SettingsEditor { - constructor(private spectron: SpectronApplication) { - // noop - } - - async openUserSettings(): Promise { - await this.spectron.command('workbench.action.openGlobalSettings'); - await this.spectron.client.waitForActiveElement('.settings-search-input input'); - } - - async focusEditableSettings(): Promise { - await this.spectron.client.keys(['ArrowDown', 'NULL'], false); - await this.spectron.client.waitForActiveElement('.editable-preferences-editor-container .monaco-editor textarea'); - await this.spectron.client.keys(['ArrowRight', 'NULL'], false); - } + constructor(private spectron: SpectronApplication) { } async addUserSetting(setting: string, value: string): Promise { - await this.openUserSettings(); - await this.focusEditableSettings(); + await this.spectron.runCommand('workbench.action.openGlobalSettings'); + await this.spectron.client.waitForActiveElement(SEARCH_INPUT); + + await this.spectron.client.keys(['ArrowDown', 'NULL']); + await this.spectron.client.waitForActiveElement(EDITOR); + + await this.spectron.client.keys(['ArrowRight', 'NULL']); await this.spectron.screenCapturer.capture('user settings is open and focused'); - await this.spectron.client.keys(`"${setting}": ${value},`); + await this.spectron.workbench.editor.waitForTypeInEditor('settings.json', `"${setting}": ${value}`, '.editable-preferences-editor-container'); await this.spectron.workbench.saveOpenedFile(); + await this.spectron.screenCapturer.capture('user settings has changed'); } } \ No newline at end of file diff --git a/test/smoke/src/areas/problems/problems.ts b/test/smoke/src/areas/problems/problems.ts index 2e6f7bc1e5a..ed1ea406c1a 100644 --- a/test/smoke/src/areas/problems/problems.ts +++ b/test/smoke/src/areas/problems/problems.ts @@ -20,14 +20,14 @@ export class Problems { public async showProblemsView(): Promise { if (!await this.isVisible()) { - await this.spectron.command('workbench.actions.view.problems'); + await this.spectron.runCommand('workbench.actions.view.problems'); await this.waitForProblemsView(); } } public async hideProblemsView(): Promise { if (await this.isVisible()) { - await this.spectron.command('workbench.actions.view.problems'); + await this.spectron.runCommand('workbench.actions.view.problems'); await this.spectron.client.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR, el => !el); } } diff --git a/test/smoke/src/areas/quickopen/quickopen.ts b/test/smoke/src/areas/quickopen/quickopen.ts index 5260874be38..4f70d280c11 100644 --- a/test/smoke/src/areas/quickopen/quickopen.ts +++ b/test/smoke/src/areas/quickopen/quickopen.ts @@ -15,28 +15,22 @@ export class QuickOpen { constructor(readonly spectron: SpectronApplication) { } - async openQuickOpen(): Promise { - await this.spectron.command('workbench.action.quickOpen'); + async openQuickOpen(value: string): Promise { + await this.spectron.runCommand('workbench.action.quickOpen'); await this.waitForQuickOpenOpened(); - } - async openCommandPallette(): Promise { - await this.spectron.command('workbench.action.showCommands'); - await this.waitForQuickOpenOpened(); + if (value) { + await this.spectron.client.setValue(QuickOpen.QUICK_OPEN_INPUT, value); + } } async closeQuickOpen(): Promise { - await this.spectron.command('workbench.action.closeQuickOpen'); + await this.spectron.runCommand('workbench.action.closeQuickOpen'); await this.waitForQuickOpenClosed(); } - async type(text: string): Promise { - await this.spectron.client.type(text); - } - async openFile(fileName: string): Promise { - await this.openQuickOpen(); - await this.type(fileName); + await this.openQuickOpen(fileName); await this.waitForQuickOpenElements(names => names.some(n => n === fileName)); await this.spectron.client.keys(['Enter', 'NULL']); @@ -45,10 +39,7 @@ export class QuickOpen { } async runCommand(commandText: string): Promise { - await this.openCommandPallette(); - - // type the text - await this.type(commandText); + await this.openQuickOpen(`> ${commandText}`); // wait for best choice to be focused await this.spectron.client.waitForTextContent(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT, commandText); @@ -69,7 +60,7 @@ export class QuickOpen { } async submit(text: string): Promise { - await this.spectron.client.type(text); + await this.spectron.client.setValue(QuickOpen.QUICK_OPEN_INPUT, text); await this.spectron.client.keys(['Enter', 'NULL']); await this.waitForQuickOpenClosed(); } diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index 5c0a7f46cd3..60972beb081 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -18,29 +18,23 @@ describe('Search', () => { }); it('searches only for *.js files & checks for correct result number', async function () { - await app.workbench.search.openSearchViewlet(); await app.workbench.search.searchFor('body'); await app.workbench.search.showQueryDetails(); - await app.workbench.search.setFilesToIncludeTextAndSearch('*.js'); - + await app.workbench.search.setFilesToIncludeText('*.js'); await app.workbench.search.submitSearch(); await app.workbench.search.waitForResultText('4 results in 1 file'); - await app.workbench.search.setFilesToIncludeTextAndSearch(''); + await app.workbench.search.setFilesToIncludeText(''); await app.workbench.search.hideQueryDetails(); }); it('dismisses result & checks for correct result number', async function () { - await app.workbench.search.openSearchViewlet(); await app.workbench.search.searchFor('body'); - await app.workbench.search.removeFileMatch(1); - await app.workbench.search.waitForResultText('3 results in 3 files'); }); it('replaces first search result with a replace term', async function () { - await app.workbench.search.openSearchViewlet(); await app.workbench.search.searchFor('body'); await app.workbench.search.setReplaceText('ydob'); diff --git a/test/smoke/src/areas/search/search.ts b/test/smoke/src/areas/search/search.ts index 3d3642ea37a..4267da79f47 100644 --- a/test/smoke/src/areas/search/search.ts +++ b/test/smoke/src/areas/search/search.ts @@ -6,92 +6,79 @@ import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; -export class Search extends Viewlet { +const VIEWLET = 'div[id="workbench.view.search"] .search-viewlet'; +const INPUT = `${VIEWLET} .search-widget .search-container .monaco-inputbox input`; +const INCLUDE_INPUT = `${VIEWLET} .query-details .monaco-inputbox input[aria-label="Search Include Patterns"]`; - static SEARCH_VIEWLET_XPATH = 'div[id="workbench.view.search"] .search-viewlet'; +export class Search extends Viewlet { constructor(spectron: SpectronApplication) { super(spectron); } - public async openSearchViewlet(): Promise { - if (!await this.isSearchViewletFocused()) { - await this.spectron.command('workbench.view.search'); - await this.spectron.client.waitForElement(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .search-container .monaco-inputbox.synthetic-focus input`); - } + async openSearchViewlet(): Promise { + await this.spectron.runCommand('workbench.view.search'); + await this.spectron.client.waitForActiveElement(INPUT); } - public async isSearchViewletFocused(): Promise { - const element = await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .search-container .monaco-inputbox.synthetic-focus input`); - return !!element; - } - - public async searchFor(text: string): Promise { - const searchBoxSelector = `${Search.SEARCH_VIEWLET_XPATH} .search-widget .search-container .monaco-inputbox input`; - - await this.spectron.client.clearElement(searchBoxSelector); - await this.spectron.client.click(searchBoxSelector); - await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .search-container .monaco-inputbox.synthetic-focus input`); - - await this.spectron.client.keys(text); - + async searchFor(text: string): Promise { + await this.spectron.client.click(INPUT); + await this.spectron.client.waitForActiveElement(INPUT); + await this.spectron.client.setValue(INPUT, text); await this.submitSearch(); } - public async submitSearch(): Promise { - await this.spectron.client.click(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .search-container .monaco-inputbox input`); - await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .search-container .monaco-inputbox.synthetic-focus input`); - await this.spectron.client.keys(['NULL', 'Enter', 'NULL'], false); - await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .messages[aria-hidden="false"]`); + async submitSearch(): Promise { + await this.spectron.client.click(INPUT); + await this.spectron.client.waitForActiveElement(INPUT); + + await this.spectron.client.keys(['Enter', 'NULL']); + await this.spectron.client.element(`${VIEWLET} .messages[aria-hidden="false"]`); } - public async setFilesToIncludeTextAndSearch(text: string): Promise { - await this.spectron.client.click(`${Search.SEARCH_VIEWLET_XPATH} .query-details .monaco-inputbox input[aria-label="Search Include Patterns"]`); - await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .query-details .monaco-inputbox.synthetic-focus input[aria-label="Search Include Patterns"]`); - await this.spectron.client.clearElement(`${Search.SEARCH_VIEWLET_XPATH} .query-details .monaco-inputbox.synthetic-focus input[aria-label="Search Include Patterns"]`); - - if (text) { - await this.spectron.client.keys(text); - } + async setFilesToIncludeText(text: string): Promise { + await this.spectron.client.click(INCLUDE_INPUT); + await this.spectron.client.waitForActiveElement(INCLUDE_INPUT); + await this.spectron.client.setValue(INCLUDE_INPUT, text || ''); } - public async showQueryDetails(): Promise { + async showQueryDetails(): Promise { if (!await this.areDetailsVisible()) { - await this.spectron.client.waitAndClick(`${Search.SEARCH_VIEWLET_XPATH} .query-details .more`); + await this.spectron.client.waitAndClick(`${VIEWLET} .query-details .more`); } } - public async hideQueryDetails(): Promise { + async hideQueryDetails(): Promise { if (await this.areDetailsVisible()) { - await this.spectron.client.waitAndClick(`${Search.SEARCH_VIEWLET_XPATH} .query-details.more .more`); + await this.spectron.client.waitAndClick(`${VIEWLET} .query-details.more .more`); } } - public async areDetailsVisible(): Promise { - const element = await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .query-details.more`); + async areDetailsVisible(): Promise { + const element = await this.spectron.client.element(`${VIEWLET} .query-details.more`); return !!element; } - public async removeFileMatch(index: number): Promise { - await this.spectron.client.waitAndmoveToObject(`${Search.SEARCH_VIEWLET_XPATH} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); - const file = await this.spectron.client.waitForText(`${Search.SEARCH_VIEWLET_XPATH} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`); - await this.spectron.client.click(`${Search.SEARCH_VIEWLET_XPATH} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-remove`); - await this.spectron.client.waitForText(`${Search.SEARCH_VIEWLET_XPATH} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`, void 0, result => result !== file); + async removeFileMatch(index: number): Promise { + await this.spectron.client.waitAndMoveToObject(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); + const file = await this.spectron.client.waitForText(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`); + await this.spectron.client.waitAndClick(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-remove`); + await this.spectron.client.waitForText(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`, void 0, result => result !== file); } - public async setReplaceText(text: string): Promise { - await this.spectron.client.waitAndClick(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .monaco-button.toggle-replace-button.collapse`); - await this.spectron.client.waitAndClick(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .replace-container .monaco-inputbox input[title="Replace"]`); - await this.spectron.client.element(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`); - await this.spectron.client.setValue(`${Search.SEARCH_VIEWLET_XPATH} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`, text); + async setReplaceText(text: string): Promise { + await this.spectron.client.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.collapse`); + await this.spectron.client.waitAndClick(`${VIEWLET} .search-widget .replace-container .monaco-inputbox input[title="Replace"]`); + await this.spectron.client.element(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`); + await this.spectron.client.setValue(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`, text); } - public async replaceFileMatch(index: number): Promise { - await this.spectron.client.waitAndmoveToObject(`${Search.SEARCH_VIEWLET_XPATH} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); - await this.spectron.client.click(`${Search.SEARCH_VIEWLET_XPATH} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-replace-all`); + async replaceFileMatch(index: number): Promise { + await this.spectron.client.waitAndMoveToObject(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); + await this.spectron.client.click(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-replace-all`); } - public async waitForResultText(text: string): Promise { - await this.spectron.client.waitForText(`${Search.SEARCH_VIEWLET_XPATH} .messages[aria-hidden="false"] .message>p`, text); + async waitForResultText(text: string): Promise { + await this.spectron.client.waitForText(`${VIEWLET} .messages[aria-hidden="false"] .message>p`, text); } } \ No newline at end of file diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 70d91d1557f..9ea1798e130 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -68,7 +68,7 @@ describe('Statusbar', () => { await app.workbench.quickopen.waitForQuickOpenOpened(); - await app.workbench.quickopen.submit('15'); + await app.workbench.quickopen.submit(':15'); await app.workbench.editor.waitForHighlightingLine(15); }); diff --git a/test/smoke/src/areas/terminal/terminal.ts b/test/smoke/src/areas/terminal/terminal.ts index eff9e3a2594..951497edccf 100644 --- a/test/smoke/src/areas/terminal/terminal.ts +++ b/test/smoke/src/areas/terminal/terminal.ts @@ -9,10 +9,10 @@ const PANEL_SELECTOR = 'div[id="workbench.panel.terminal"]'; const XTERM_SELECTOR = `${PANEL_SELECTOR} .terminal-wrapper`; export class Terminal { - constructor(private spectron: SpectronApplication) { - } - public async showTerminal(): Promise { + constructor(private spectron: SpectronApplication) { } + + async showTerminal(): Promise { if (!await this.isVisible()) { await this.spectron.workbench.quickopen.runCommand('View: Toggle Integrated Terminal'); await this.spectron.client.waitForElement(XTERM_SELECTOR); @@ -20,17 +20,18 @@ export class Terminal { } } - public async isVisible(): Promise { + async isVisible(): Promise { const element = await this.spectron.client.element(PANEL_SELECTOR); return !!element; } - public async runCommand(commandText: string): Promise { - await this.spectron.client.type(commandText); + async runCommand(commandText: string): Promise { + // TODO@Tyriar fix this. we should not use type but setValue + // await this.spectron.client.type(commandText); await this.spectron.client.keys(['Enter', 'NULL']); } - public async waitForTerminalText(fn: (text: string[]) => boolean, timeOutDescription: string = 'Getting Terminal Text'): Promise { + async waitForTerminalText(fn: (text: string[]) => boolean, timeOutDescription: string = 'Getting Terminal Text'): Promise { return this.spectron.client.waitFor(async () => { const terminalText = await this.getTerminalText(); if (fn(terminalText)) { @@ -40,7 +41,7 @@ export class Terminal { }, void 0, timeOutDescription); } - public getCurrentLineNumber(): Promise { + getCurrentLineNumber(): Promise { return this.getTerminalText().then(text => text.length); } diff --git a/test/smoke/src/areas/workbench/data-migration.test.ts b/test/smoke/src/areas/workbench/data-migration.test.ts index cb217fc46be..d52859bc1ae 100644 --- a/test/smoke/src/areas/workbench/data-migration.test.ts +++ b/test/smoke/src/areas/workbench/data-migration.test.ts @@ -49,10 +49,9 @@ describe('Data Migration', () => { await Util.removeFile(`${fileName}`); await app.start('Data Migration'); - await app.workbench.waitForActiveTab(fileName); - await app.client.type(firstTextPart); + await app.workbench.editor.waitForTypeInEditor('plainFile', firstTextPart); await app.workbench.saveOpenedFile(); - await app.client.type(secondTextPart); + await app.workbench.editor.waitForTypeInEditor('plainFile', secondTextPart); await app.stop(); await new Promise(c => setTimeout(c, 1000)); // wait until all resources are released (e.g. locked local storage) diff --git a/test/smoke/src/areas/workbench/workbench.ts b/test/smoke/src/areas/workbench/workbench.ts index 9bf860c3584..08a3204d1eb 100644 --- a/test/smoke/src/areas/workbench/workbench.ts +++ b/test/smoke/src/areas/workbench/workbench.ts @@ -57,7 +57,7 @@ export class Workbench { // ignore if there is no dirty file return Promise.resolve(); } - await this.spectron.command('workbench.action.files.save'); + await this.spectron.runCommand('workbench.action.files.save'); return this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty', element => !element); } @@ -71,8 +71,8 @@ export class Workbench { await this.editor.waitForActiveEditor(fileName); } - public async waitForActiveTab(fileName: string, isDirty: boolean = false): Promise { - return this.spectron.client.waitForElement(`.tabs-container div.tab.active${isDirty ? '.dirty' : ''}[aria-selected="true"][aria-label="${fileName}, tab"]`).then(() => true); + public async waitForActiveTab(fileName: string, isDirty: boolean = false): Promise { + return this.spectron.client.waitForElement(`.tabs-container div.tab.active${isDirty ? '.dirty' : ''}[aria-selected="true"][aria-label="${fileName}, tab"]`); } public async waitForTab(fileName: string, isDirty: boolean = false): Promise { @@ -80,7 +80,7 @@ export class Workbench { } public async newUntitledFile(): Promise { - await this.spectron.command('workbench.action.files.newUntitledFile'); + await this.spectron.runCommand('workbench.action.files.newUntitledFile'); await this.waitForEditorFocus('Untitled-1', true); } } diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 01be7f3f6f2..6b88aed84e8 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -262,7 +262,7 @@ export class SpectronApplication { * Retrieves the command from keybindings file and executes it with WebdriverIO client API * @param command command (e.g. 'workbench.action.files.newUntitledFile') */ - command(command: string, capture?: boolean): Promise { + runCommand(command: string): Promise { const binding = this.keybindings.find(x => x['command'] === command); if (!binding) { return this.workbench.quickopen.runCommand(command); @@ -278,7 +278,7 @@ export class SpectronApplication { keysToPress.push('NULL'); }); - return this.client.keys(keysToPress, capture); + return this.client.keys(keysToPress); } /** diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index 324dc9c8a2f..24857764b63 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -25,7 +25,7 @@ export class SpectronClient { return this.spectron.client.windowByIndex(index); } - keys(keys: string[] | string, capture: boolean = true): Promise { + keys(keys: string[]): Promise { this.spectron.client.keys(keys); return Promise.resolve(); } @@ -78,7 +78,7 @@ export class SpectronClient { return this.spectron.client.moveToObject(selector); } - async waitAndmoveToObject(selector: string): Promise { + async waitAndMoveToObject(selector: string): Promise { return this.waitFor(() => this.spectron.client.moveToObject(selector), void 0, `move to object with selector ${selector}`); } @@ -133,10 +133,6 @@ export class SpectronClient { return Promise.resolve(this.spectron.client.getAttribute(selector, attribute)); } - clearElement(selector: string): any { - return this.spectron.client.clearElement(selector); - } - buttonDown(): any { return this.spectron.client.buttonDown(); } @@ -191,22 +187,22 @@ export class SpectronClient { } } - type(text: string): Promise { - return new Promise((res) => { - let textSplit = text.split(' '); + // type(text: string): Promise { + // return new Promise((res) => { + // let textSplit = text.split(' '); - const type = async (i: number) => { - if (!textSplit[i] || textSplit[i].length <= 0) { - return res(); - } + // const type = async (i: number) => { + // if (!textSplit[i] || textSplit[i].length <= 0) { + // return res(); + // } - const toType = textSplit[i + 1] ? `${textSplit[i]} ` : textSplit[i]; - await this.keys(toType, false); - await this.keys(['NULL']); - await type(i + 1); - }; + // const toType = textSplit[i + 1] ? `${textSplit[i]} ` : textSplit[i]; + // await this.keys(toType); + // await this.keys(['NULL']); + // await type(i + 1); + // }; - return type(0); - }); - } + // return type(0); + // }); + // } } \ No newline at end of file From 2d2a6a38d66bf30735c37715a5ba69207c877c6c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Oct 2017 14:41:11 +0200 Subject: [PATCH 033/394] message --- test/smoke/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/smoke/README.md b/test/smoke/README.md index 995fc730a4c..48e4cd60acd 100644 --- a/test/smoke/README.md +++ b/test/smoke/README.md @@ -40,3 +40,7 @@ Here's an example: when opening quick open, focus goes from its list to its inpu ### I type in a Monaco editor instance, but the text doesn't appear to be there This is a **waiting** issue. When you type in a Monaco editor instance, you're really typing in a `textarea`. The `textarea` is then polled for its contents, then the editor model gets updated and finally the editor view gets updated. It's a good idea to always wait for the text to appear rendered in the editor after you type in it. + +### I type in a Monaco editor instance, but the text appears scrambled + +This is an issue which is **not yet fixed**. Unfortunately this seems to happen whenever the CPU load of the system is high. Rerunning the test will often result in a successful outcome. \ No newline at end of file From cbd02812d082470087903a418e119de27a36f60e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Oct 2017 16:14:13 +0200 Subject: [PATCH 034/394] upgrade spectron --- test/smoke/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke/package.json b/test/smoke/package.json index 8e1a6e4793e..54faf91b741 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -22,7 +22,7 @@ "ncp": "^2.0.0", "portastic": "^1.0.1", "rimraf": "^2.6.1", - "spectron": "~3.6.4", + "spectron": "^3.7.2", "strip-json-comments": "^2.0.1", "tmp": "0.0.33", "typescript": "^2.2.2" From 7d077703a7deddb82293db2faf02ac5bac900134 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Oct 2017 16:24:29 +0200 Subject: [PATCH 035/394] smoke: fix electron types --- test/smoke/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/smoke/package.json b/test/smoke/package.json index 54faf91b741..ebcf1a12e04 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -8,7 +8,6 @@ "mocha": "mocha" }, "devDependencies": { - "@types/electron": "~1.4.37", "@types/htmlparser2": "3.7.29", "@types/mkdirp": "0.5.1", "@types/mocha": "2.2.41", @@ -16,6 +15,7 @@ "@types/node": "8.0.33", "@types/rimraf": "2.0.2", "@types/webdriverio": "4.6.1", + "electron": "1.7.7", "htmlparser2": "^3.9.2", "mkdirp": "^0.5.1", "mocha": "^3.2.0", @@ -27,4 +27,4 @@ "tmp": "0.0.33", "typescript": "^2.2.2" } -} +} \ No newline at end of file From 28fcacfdceaaeeaa43b4a553746350031a4cd84e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Oct 2017 17:53:33 +0200 Subject: [PATCH 036/394] fix bad src of files in hygiene --- build/gulpfile.hygiene.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index ee780903b6b..b14398194a1 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -12,6 +12,7 @@ const gulptslint = require('gulp-tslint'); const gulpeslint = require('gulp-eslint'); const tsfmt = require('typescript-formatter'); const tslint = require('tslint'); +const vfs = require('vinyl-fs'); /** * Hygiene works by creating cascading subsets of all our files and @@ -235,7 +236,7 @@ const hygiene = exports.hygiene = (some, options) => { this.emit('data', file); }); - const result = gulp.src(some || all, { base: '.' }) + const result = vfs.src(some || all, { base: '.', follow: true }) .pipe(filter(f => !f.stat.isDirectory())) .pipe(filter(eolFilter)) .pipe(options.skipEOL ? es.through() : eol) @@ -265,7 +266,7 @@ const hygiene = exports.hygiene = (some, options) => { })); }; -gulp.task('hygiene', () => hygiene()); +gulp.task('hygiene', () => hygiene('')); // this allows us to run hygiene as a git pre-commit hook if (require.main === module) { From 193980e0baba336e63f892297942144bbc86844e Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 12 Oct 2017 12:48:00 +0200 Subject: [PATCH 037/394] Aquire instantiation service after workbench is intialized --- src/vs/workbench/electron-browser/workbench.ts | 2 ++ .../configuration/node/configurationService.ts | 16 +++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 59b300fc28b..128753dedd6 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -624,6 +624,8 @@ export class Workbench implements IPartService { Registry.as(EditorExtensions.EditorInputFactories).setInstantiationService(this.instantiationService); this.instantiationService.createInstance(DefaultConfigurationExportHelper); + + this.configurationService.setInstantiationService(this.getInstantiationService()); } private initSettings(): void { diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 9a1c04fb4be..6edf38685bb 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -7,6 +7,7 @@ import URI from 'vs/base/common/uri'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; +import * as assert from 'vs/base/common/assert'; import Event, { Emitter } from 'vs/base/common/event'; import { StrictResourceMap } from 'vs/base/common/map'; import * as errors from 'vs/base/common/errors'; @@ -149,14 +150,11 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat updateValue(key: string, value: any, target: ConfigurationTarget): TPromise updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { - if (this.configurationEditingService) { - const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0; - const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3); - if (target) { - return this.writeConfigurationValue(key, value, target, overrides); - } - } - return TPromise.as(null); + assert.ok(this.configurationEditingService, 'Workbench is not initialized yet'); + const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0; + const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3); + return target ? this.writeConfigurationValue(key, value, target, overrides) + : TPromise.as(null); } reloadConfiguration(folder?: IWorkspaceFolder, key?: string): TPromise { @@ -215,7 +213,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat .then(() => this.initializeConfiguration()); } - aquireDelayedServices(instantiationService: IInstantiationService): void { + setInstantiationService(instantiationService: IInstantiationService): void { this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService); } From 648e6f6aff9dce84ae1a88465f78c98eac01e5a5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 15:46:30 +0200 Subject: [PATCH 038/394] Implement a relative interval tree --- src/vs/editor/common/model/intervalTree.ts | 626 ++++++++++++++++++ .../test/common/model/intervalTree.test.ts | 365 ++++++++++ 2 files changed, 991 insertions(+) create mode 100644 src/vs/editor/common/model/intervalTree.ts create mode 100644 src/vs/editor/test/common/model/intervalTree.test.ts diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts new file mode 100644 index 00000000000..fb9b9294352 --- /dev/null +++ b/src/vs/editor/common/model/intervalTree.ts @@ -0,0 +1,626 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +// +// The red-black tree is based on the "Introduction to Algorithms" by Cormen, Leiserson and Rivest. +// + +export class Interval { + _intervalBrand: void; + + public start: number; + public end: number; + + constructor(start: number, end: number) { + this.start = start; + this.end = end; + } + + public compareToRelative(other: RelativeInterval, delta: number): number { + const otherStart = other.start + delta; + if (this.start === otherStart) { + const otherEnd = other.end + delta; + return this.end - otherEnd; + } + return this.start - otherStart; + } +} + +export class RelativeInterval { + _relativeIntervalBrand: void; + + public static fromInterval(interval: Interval, delta: number): RelativeInterval { + return new RelativeInterval(interval.start - delta, interval.end - delta); + } + + public start: number; + public end: number; + + constructor(start: number, end: number) { + this.start = start; + this.end = end; + } +} + +export const enum NodeColor { + Red, + Black +} + +export class IntervalNode { + + public left: IntervalNode; + public right: IntervalNode; + public parent: IntervalNode; + public color: NodeColor; + + public delta: number; + public interval: RelativeInterval; + public maxEnd: number; + + public resultInterval: Interval; + + constructor(interval: RelativeInterval, delta: number) { + this.parent = null; + this.left = null; + this.right = null; + this.color = NodeColor.Red; + + this.delta = delta; + this.interval = interval; + this.maxEnd = this.interval.end; + + this.resultInterval = null; + } + + public detach(): void { + this.parent = null; + this.left = null; + this.right = null; + } +} + +const SENTINEL: IntervalNode = new IntervalNode(new RelativeInterval(0, 0), 0); +SENTINEL.parent = SENTINEL; +SENTINEL.left = SENTINEL; +SENTINEL.right = SENTINEL; +SENTINEL.color = NodeColor.Black; + +function leftRotate(T: IntervalTree, x: IntervalNode): void { + const y = x.right; // set y. + + y.delta += x.delta; // y's delta is no longer influenced by x's delta + y.interval.start += x.delta; + y.interval.end += x.delta; + + x.right = y.left; // turn y's left subtree into x's right subtree. + if (y.left !== SENTINEL) { + y.left.parent = x; + } + y.parent = x.parent; // link x's parent to y. + if (x.parent === SENTINEL) { + T.root = y; + } else if (x === x.parent.left) { + x.parent.left = y; + } else { + x.parent.right = y; + } + + y.left = x; // put x on y's left. + x.parent = y; + + recomputeMaxEnd(x); + recomputeMaxEnd(y); +} + +function rightRotate(T: IntervalTree, y: IntervalNode): void { + const x = y.left; + + y.delta -= x.delta; + y.interval.start -= x.delta; + y.interval.end -= x.delta; + + y.left = x.right; + if (x.right !== SENTINEL) { + x.right.parent = y; + } + x.parent = y.parent; + if (y.parent === SENTINEL) { + T.root = x; + } else if (y === y.parent.right) { + y.parent.right = x; + } else { + y.parent.left = x; + } + + x.right = y; + y.parent = x; + + recomputeMaxEnd(y); + recomputeMaxEnd(x); +} + +function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { + let delta: number = 0; + let z = SENTINEL; + let x = T.root; + while (true) { + let cmp = interval.compareToRelative(x.interval, delta); + if (cmp < 0) { + // this node should be inserted to the left + // => it is not affected by the node's delta + if (x.left === SENTINEL) { + const relativeInterval = RelativeInterval.fromInterval(interval, delta); + z = new IntervalNode(relativeInterval, relativeInterval.start); + x.left = z; + break; + } else { + x = x.left; + } + } else { + // this node should be inserted to the right + // => it is not affected by the node's delta + if (x.right === SENTINEL) { + const relativeInterval = RelativeInterval.fromInterval(interval, delta + x.delta); + z = new IntervalNode(relativeInterval, relativeInterval.start); + x.right = z; + break; + } else { + delta += x.delta; + x = x.right; + } + } + } + + z.parent = x; + z.left = SENTINEL; + z.right = SENTINEL; + z.color = NodeColor.Red; + return z; +} + +function leftest(node: IntervalNode): IntervalNode { + while (node.left !== SENTINEL) { + node = node.left; + } + return node; +} + +function resetSentinel(): void { + SENTINEL.parent = SENTINEL; + SENTINEL.delta = 0; // optional + SENTINEL.interval.start = 0; // optional + SENTINEL.interval.end = 0; // optional +} + +function computeMaxEnd(node: IntervalNode): number { + let maxEnd = node.interval.end; + if (node.left !== SENTINEL) { + const leftMaxEnd = node.left.maxEnd; + if (leftMaxEnd > maxEnd) { + maxEnd = leftMaxEnd; + } + } + if (node.right !== SENTINEL) { + const rightMaxEnd = node.right.maxEnd + node.delta; + if (rightMaxEnd > maxEnd) { + maxEnd = rightMaxEnd; + } + } + return maxEnd; +} + +function recomputeMaxEnd(node: IntervalNode): void { + node.maxEnd = computeMaxEnd(node); +} + +function recomputeMaxEndToRoot(node: IntervalNode): void { + while (node !== SENTINEL) { + + const maxEnd = computeMaxEnd(node); + + if (node.maxEnd === maxEnd) { + // no need to go further + return; + } + + node.maxEnd = maxEnd; + node = node.parent; + } +} + +function treeDelete(T: IntervalTree, z: IntervalNode): void { + + let x: IntervalNode; + let y: IntervalNode; + + // RB-DELETE except we don't swap z and y in case c) + // i.e. we always delete what's pointed at by z. + + if (z.left === SENTINEL) { + x = z.right; + y = z; + + // x's delta is no longer influenced by z's delta + x.delta += z.delta; + x.interval.start += z.delta; + x.interval.end += z.delta; + + } else if (z.right === SENTINEL) { + x = z.left; + y = z; + + } else { + y = leftest(z.right); + x = y.right; + + // y's delta is no longer influenced by z's delta, + // but we don't want to walk the entire right-hand-side subtree of x. + // we therefore maintain z's delta in y, and adjust only x + x.interval.start += y.delta; + x.interval.end += y.delta; + // if (x.interval.end > x.maxEnd) { + // x.maxEnd = x.interval.end; + // } + x.delta += y.delta; + + y.interval.start += z.delta; + y.interval.end += z.delta; + y.delta = z.delta; + } + + if (y === T.root) { + T.root = x; + x.color = NodeColor.Black; + + z.detach(); + resetSentinel(); + recomputeMaxEnd(x); + return; + } + + let yWasRed = (y.color === NodeColor.Red); + + if (y === y.parent.left) { + y.parent.left = x; + } else { + y.parent.right = x; + } + + if (y === z) { + x.parent = y.parent; + } else { + + if (y.parent === z) { + x.parent = y; + } else { + x.parent = y.parent; + } + + y.left = z.left; + y.right = z.right; + y.parent = z.parent; + y.color = z.color; + + if (z === T.root) { + T.root = y; + } else { + if (z === z.parent.left) { + z.parent.left = y; + } else { + z.parent.right = y; + } + } + + if (y.left !== SENTINEL) { + y.left.parent = y; + } + if (y.right !== SENTINEL) { + y.right.parent = y; + } + } + + z.detach(); + + if (yWasRed) { + recomputeMaxEndToRoot(x.parent); + if (y !== z) { + recomputeMaxEndToRoot(y); + recomputeMaxEndToRoot(y.parent); + } + resetSentinel(); + return; + } + + recomputeMaxEndToRoot(x); + recomputeMaxEndToRoot(x.parent); + if (y !== z) { + recomputeMaxEndToRoot(y); + recomputeMaxEndToRoot(y.parent); + } + + // RB-DELETE-FIXUP + let w: IntervalNode; + while (x !== T.root && x.color === NodeColor.Black) { + + if (x === x.parent.left) { + w = x.parent.right; + + if (w.color === NodeColor.Red) { + w.color = NodeColor.Black; + x.parent.color = NodeColor.Red; + leftRotate(T, x.parent); + w = x.parent.right; + } + + if (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) { + w.color = NodeColor.Red; + x = x.parent; + } else { + if (w.right.color === NodeColor.Black) { + w.left.color = NodeColor.Black; + w.color = NodeColor.Red; + rightRotate(T, w); + w = x.parent.right; + } + + w.color = x.parent.color; + x.parent.color = NodeColor.Black; + w.right.color = NodeColor.Black; + leftRotate(T, x.parent); + x = T.root; + } + + } else { + w = x.parent.left; + + if (w.color === NodeColor.Red) { + w.color = NodeColor.Black; + x.parent.color = NodeColor.Red; + rightRotate(T, x.parent); + w = x.parent.left; + } + + if (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) { + w.color = NodeColor.Red; + x = x.parent; + + } else { + if (w.left.color === NodeColor.Black) { + w.right.color = NodeColor.Black; + w.color = NodeColor.Red; + leftRotate(T, w); + w = x.parent.left; + } + + w.color = x.parent.color; + x.parent.color = NodeColor.Black; + w.left.color = NodeColor.Black; + rightRotate(T, x.parent); + x = T.root; + } + } + } + + x.color = NodeColor.Black; + resetSentinel(); +} + +export class IntervalTree { + + public root: IntervalNode; + + constructor() { + this.root = SENTINEL; + } + + // public intervalSearch(interval: Interval): IntervalNode[] { + // let result: IntervalNode[] = []; + // if (this.root !== SENTINEL) { + // this._intervalSearch(this.root, 0, interval, result); + // } + // return result; + // } + + // private _intervalSearch(node: IntervalNode, delta: number, interval: Interval, result: IntervalNode[]): void { + // // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + // // Now, it is known that two intervals A and B overlap only when both + // // A.low ≤ B.high and A.high ≥ B.low. When searching the trees for + // // nodes overlapping with a given interval, you can immediately skip: + // // - all nodes to the right of nodes whose low value is past the end of the given interval. + // // - all nodes that have their maximum 'high' value below the start of the given interval. + + // if (delta + node.maxEnd < interval.start) { + // return; + // } + + + // } + + public insert(interval: Interval): IntervalNode { + if (this.root === SENTINEL) { + const relativeInterval = RelativeInterval.fromInterval(interval, 0); + const newNode = new IntervalNode(relativeInterval, relativeInterval.start); + newNode.parent = SENTINEL; + newNode.left = SENTINEL; + newNode.right = SENTINEL; + newNode.color = NodeColor.Black; + this.root = newNode; + return this.root; + } + + const newNode = treeInsert(this, interval); + + recomputeMaxEndToRoot(newNode.parent); + + // repair tree + let node = newNode; + while (node !== this.root && node.parent.color === NodeColor.Red) { + if (node.parent === node.parent.parent.left) { + const temp = node.parent.parent.right; + + if (temp.color === NodeColor.Red) { + node.parent.color = NodeColor.Black; + temp.color = NodeColor.Black; + node.parent.parent.color = NodeColor.Red; + node = node.parent.parent; + } else { + if (node === node.parent.right) { + node = node.parent; + leftRotate(this, node); + } + node.parent.color = NodeColor.Black; + node.parent.parent.color = NodeColor.Red; + rightRotate(this, node.parent.parent); + } + } else { + const temp = node.parent.parent.left; + + if (temp.color === NodeColor.Red) { + node.parent.color = NodeColor.Black; + temp.color = NodeColor.Black; + node.parent.parent.color = NodeColor.Red; + node = node.parent.parent; + } else { + if (node === node.parent.left) { + node = node.parent; + rightRotate(this, node); + } + node.parent.color = NodeColor.Black; + node.parent.parent.color = NodeColor.Red; + leftRotate(this, node.parent.parent); + } + } + } + + this.root.color = NodeColor.Black; + + return newNode; + } + + public delete(node: IntervalNode) { + treeDelete(this, node); + } + + public assertInvariants(): void { + assert(SENTINEL.color === NodeColor.Black); + assert(SENTINEL.parent === SENTINEL); + assert(SENTINEL.left === SENTINEL); + assert(SENTINEL.right === SENTINEL); + assert(SENTINEL.interval.start === 0); + assert(SENTINEL.interval.end === 0); + assert(SENTINEL.delta === 0); + assertValidTree(this); + } + + public getAllInOrder(): Interval[] { + let r: Interval[] = [], rLength = 0; + this.visitInOrder((n, delta) => { + r[rLength++] = new Interval(n.interval.start + delta, n.interval.end + delta); + }); + return r; + } + + public visitInOrder(visitor: (n: IntervalNode, delta: number) => void): void { + this._visitInOrder(this.root, 0, visitor); + } + + private _visitInOrder(n: IntervalNode, delta: number, visitor: (n: IntervalNode, delta: number) => void): void { + if (n.left !== SENTINEL) { + this._visitInOrder(n.left, delta, visitor); + } + + if (n !== SENTINEL) { + visitor(n, delta); + } + + if (n.right !== SENTINEL) { + this._visitInOrder(n.right, delta + n.delta, visitor); + } + } + + public print(): void { + let out: string[] = []; + this._print(this.root, '', 0, out); + console.log(out.join('')); + } + + private _print(n: IntervalNode, indent: string, delta: number, out: string[]): void { + out.push(`${indent}[${n.color === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.interval.start}->${n.interval.end}, ${n.maxEnd}] : {${delta + n.interval.start}->${delta + n.interval.end}}, maxEnd: ${n.maxEnd + delta}\n`); + if (n.left !== SENTINEL) { + this._print(n.left, indent + ' ', delta, out); + } else { + out.push(`${indent} NIL\n`); + } + if (n.right !== SENTINEL) { + this._print(n.right, indent + ' ', delta + n.delta, out); + } else { + out.push(`${indent} NIL\n`); + } + } +} + +function depth(n: IntervalNode): number { + if (n === SENTINEL) { + // The leafs are black + return 1; + } + assert(depth(n.left) === depth(n.right)); + return (n.color === NodeColor.Black ? 1 : 0) + depth(n.left); +} + +function assertValidNode(n: IntervalNode, delta): void { + if (n === SENTINEL) { + return; + } + + let l = n.left; + let r = n.right; + + if (n.color === NodeColor.Red) { + if (l.color !== NodeColor.Black) { + assert(false); + } + if (r.color !== NodeColor.Black) { + assert(false); + } + } + + let expectedMaxEnd = n.interval.end; + if (l !== SENTINEL) { + const lValue = new Interval(l.interval.start + delta, l.interval.end + delta); + assert(lValue.compareToRelative(n.interval, delta) <= 0); + expectedMaxEnd = Math.max(expectedMaxEnd, l.maxEnd); + } + if (r !== SENTINEL) { + const nValue = new Interval(n.interval.start + delta, n.interval.end + delta); + assert(nValue.compareToRelative(r.interval, delta + n.delta) <= 0); + expectedMaxEnd = Math.max(expectedMaxEnd, r.maxEnd + n.delta); + } + assert(n.maxEnd === expectedMaxEnd); + + assertValidNode(l, delta); + assertValidNode(r, delta + n.delta); +} + +function assertValidTree(tree: IntervalTree): void { + if (tree.root === SENTINEL) { + return; + } + if (tree.root.color !== NodeColor.Black) { + assert(false); + } + if (depth(tree.root.left) !== depth(tree.root.right)) { + assert(false); + } + assertValidNode(tree.root, 0); +} + +function assert(condition: boolean): void { + if (!condition) { + throw new Error('Assertion violation'); + } +} diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts new file mode 100644 index 00000000000..3c5caac63fc --- /dev/null +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -0,0 +1,365 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import { IntervalTree, Interval, IntervalNode } from 'vs/editor/common/model/intervalTree'; + +const GENERATE_TESTS = false; +let TEST_COUNT = GENERATE_TESTS ? 10000 : 0; +let PRINT_TREE = false; +const MIN_INTERVAL_START = 1; +const MAX_INTERVAL_END = 100; +const MIN_INSERTS = 1; +const MAX_INSERTS = 30; + +suite('IntervalTree', () => { + + class Oracle { + public intervals: Interval[]; + + constructor() { + this.intervals = []; + } + + public insert(interval: Interval): Interval { + this.intervals.push(interval); + this.intervals.sort((a, b) => { + if (a.start === b.start) { + return a.end - b.end; + } + return a.start - b.start; + }); + return interval; + } + + public delete(interval: Interval): void { + for (let i = 0, len = this.intervals.length; i < len; i++) { + if (this.intervals[i] === interval) { + this.intervals.splice(i, 1); + return; + } + } + } + } + + class TestState { + private _oracle: Oracle = new Oracle(); + private _tree: IntervalTree = new IntervalTree(); + private _lastNodeId = -1; + private _treeNodes: IntervalNode[] = []; + private _oracleNodes: Interval[] = []; + + public acceptOp(op: IOperation): void { + + + if (op.type === 'insert') { + if (PRINT_TREE) { + console.log(`insert: {${JSON.stringify(new Interval(op.begin, op.end))}}`); + } + let nodeId = (++this._lastNodeId); + this._treeNodes[nodeId] = this._tree.insert(new Interval(op.begin, op.end)); + this._oracleNodes[nodeId] = this._oracle.insert(new Interval(op.begin, op.end)); + } else { + if (PRINT_TREE) { + console.log(`delete: {${JSON.stringify(this._oracleNodes[op.id])}}`); + } + this._tree.delete(this._treeNodes[op.id]); + this._oracle.delete(this._oracleNodes[op.id]); + + this._treeNodes[op.id] = null; + this._oracleNodes[op.id] = null; + } + + if (PRINT_TREE) { + this._tree.print(); + } + + this._tree.assertInvariants(); + + let actual = this._tree.getAllInOrder(); + let expected = this._oracle.intervals; + assert.deepEqual(actual, expected); + } + + public getExistingNodeId(index: number): number { + let currIndex = -1; + for (let i = 0; i < this._treeNodes.length; i++) { + if (this._treeNodes[i] === null) { + continue; + } + currIndex++; + if (currIndex === index) { + return i; + } + } + throw new Error('unexpected'); + } + } + + interface IInsertOperation { + type: 'insert'; + begin: number; + end: number; + } + + interface IDeleteOperation { + type: 'delete'; + id: number; + } + + type IOperation = IInsertOperation | IDeleteOperation; + + function testIntervalTree(ops: IOperation[]): void { + let state = new TestState(); + for (let i = 0; i < ops.length; i++) { + state.acceptOp(ops[i]); + } + } + + function getRandomInt(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + class AutoTest { + private _ops: IOperation[] = []; + private _state: TestState = new TestState(); + private _insertCnt: number; + private _deleteCnt: number; + + constructor() { + this._insertCnt = getRandomInt(MIN_INSERTS, MAX_INSERTS); + this._deleteCnt = 0; + } + + public run() { + while (this._insertCnt > 0 || this._deleteCnt > 0) { + let type: 'insert' | 'delete'; + if (this._insertCnt > 0) { + type = 'insert'; + } else { + type = 'delete'; + } + if (type === 'insert') { + let begin = getRandomInt(MIN_INTERVAL_START, MAX_INTERVAL_END); + let length: number; + if (getRandomInt(1, 10) <= 2) { + // large range + length = getRandomInt(0, MAX_INTERVAL_END - begin); + } else { + // small range + length = getRandomInt(0, Math.min(MAX_INTERVAL_END - begin, 10)); + } + this._run({ + type: 'insert', + begin: begin, + end: begin + length + }); + this._insertCnt--; + this._deleteCnt++; + } else { + let idx = getRandomInt(0, this._deleteCnt - 1); + this._run({ + type: 'delete', + id: this._state.getExistingNodeId(idx) + }); + this._deleteCnt--; + // this._deleteCnt = 0; + } + } + } + + private _run(op: IOperation): void { + this._ops.push(op); + this._state.acceptOp(op); + } + + public print(): void { + console.log(`testIntervalTree(${JSON.stringify(this._ops)})`); + } + + } + + test('gen01', () => { + testIntervalTree([ + { type: 'insert', begin: 28, end: 35 }, + { type: 'insert', begin: 52, end: 54 }, + { type: 'insert', begin: 63, end: 69 } + ]); + }); + + test('gen02', () => { + testIntervalTree([ + { type: 'insert', begin: 80, end: 89 }, + { type: 'insert', begin: 92, end: 100 }, + { type: 'insert', begin: 99, end: 99 } + ]); + }); + + test('gen03', () => { + testIntervalTree([ + { type: 'insert', begin: 89, end: 96 }, + { type: 'insert', begin: 71, end: 74 }, + { type: 'delete', id: 1 } + ]); + }); + + test('gen04', () => { + testIntervalTree([ + { type: 'insert', begin: 44, end: 46 }, + { type: 'insert', begin: 85, end: 88 }, + { type: 'delete', id: 0 } + ]); + }); + + test('gen05', () => { + testIntervalTree([ + { type: 'insert', begin: 82, end: 90 }, + { type: 'insert', begin: 69, end: 73 }, + { type: 'delete', id: 0 }, + { type: 'delete', id: 1 } + ]); + }); + + test('gen06', () => { + testIntervalTree([ + { type: 'insert', begin: 41, end: 63 }, + { type: 'insert', begin: 98, end: 98 }, + { type: 'insert', begin: 47, end: 51 }, + { type: 'delete', id: 2 } + ]); + }); + + test('gen07', () => { + testIntervalTree([ + { type: 'insert', begin: 24, end: 26 }, + { type: 'insert', begin: 11, end: 28 }, + { type: 'insert', begin: 27, end: 30 }, + { type: 'insert', begin: 80, end: 85 }, + { type: 'delete', id: 1 } + ]); + }); + + test('gen08', () => { + testIntervalTree([ + { type: 'insert', begin: 100, end: 100 }, + { type: 'insert', begin: 100, end: 100 } + ]); + }); + + test('gen09', () => { + testIntervalTree([ + { type: 'insert', begin: 58, end: 65 }, + { type: 'insert', begin: 82, end: 96 }, + { type: 'insert', begin: 58, end: 65 } + ]); + }); + + test('gen10', () => { + testIntervalTree([ + { type: 'insert', begin: 32, end: 40 }, + { type: 'insert', begin: 25, end: 29 }, + { type: 'insert', begin: 24, end: 32 } + ]); + }); + + test('gen11', () => { + testIntervalTree([ + { type: 'insert', begin: 25, end: 70 }, + { type: 'insert', begin: 99, end: 100 }, + { type: 'insert', begin: 46, end: 51 }, + { type: 'insert', begin: 57, end: 57 }, + { type: 'delete', id: 2 } + ]); + }); + + test('gen12', () => { + testIntervalTree([ + { type: 'insert', begin: 20, end: 26 }, + { type: 'insert', begin: 10, end: 18 }, + { type: 'insert', begin: 99, end: 99 }, + { type: 'insert', begin: 37, end: 59 }, + { type: 'delete', id: 2 } + ]); + }); + + test('gen13', () => { + testIntervalTree([ + { type: 'insert', begin: 3, end: 91 }, + { type: 'insert', begin: 57, end: 57 }, + { type: 'insert', begin: 35, end: 44 }, + { type: 'insert', begin: 72, end: 81 }, + { type: 'delete', id: 2 } + ]); + }); + + test('gen14', () => { + testIntervalTree([ + { type: 'insert', begin: 58, end: 61 }, + { type: 'insert', begin: 34, end: 35 }, + { type: 'insert', begin: 56, end: 62 }, + { type: 'insert', begin: 69, end: 78 }, + { type: 'delete', id: 0 } + ]); + }); + + test('gen15', () => { + testIntervalTree([ + { type: 'insert', begin: 63, end: 69 }, + { type: 'insert', begin: 17, end: 24 }, + { type: 'insert', begin: 3, end: 13 }, + { type: 'insert', begin: 84, end: 94 }, + { type: 'insert', begin: 18, end: 23 }, + { type: 'insert', begin: 96, end: 98 }, + { type: 'delete', id: 1 } + ]); + }); + + test('gen16', () => { + testIntervalTree([ + { type: 'insert', begin: 27, end: 27 }, + { type: 'insert', begin: 42, end: 87 }, + { type: 'insert', begin: 42, end: 49 }, + { type: 'insert', begin: 69, end: 71 }, + { type: 'insert', begin: 20, end: 27 }, + { type: 'insert', begin: 8, end: 9 }, + { type: 'insert', begin: 42, end: 49 }, + { type: 'delete', id: 1 } + ]); + }); + + test('gen17', () => { + testIntervalTree([ + { type: 'insert', begin: 21, end: 23 }, + { type: 'insert', begin: 83, end: 87 }, + { type: 'insert', begin: 56, end: 58 }, + { type: 'insert', begin: 1, end: 55 }, + { type: 'insert', begin: 56, end: 59 }, + { type: 'insert', begin: 58, end: 60 }, + { type: 'insert', begin: 56, end: 65 }, + { type: 'delete', id: 1 }, + { type: 'delete', id: 0 }, + { type: 'delete', id: 6 } + ]); + }); + + // TEST_COUNT = 0; + // PRINT_TREE = true; + + for (let i = 0; i < TEST_COUNT; i++) { + if (i % 100 === 0) { + console.log(`TEST ${i + 1}/${TEST_COUNT}`); + } + let test = new AutoTest(); + + try { + test.run(); + } catch (err) { + console.log(err); + test.print(); + return; + } + } +}); From bc76ef88b9c09d6757e95a11e1060dd0227074e0 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 16:29:09 +0200 Subject: [PATCH 039/394] Implement interval searching --- src/vs/editor/common/model/intervalTree.ts | 61 ++- .../test/common/model/intervalTree.test.ts | 435 +++++++++++------- 2 files changed, 318 insertions(+), 178 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index fb9b9294352..60d9f8ca73d 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -73,7 +73,7 @@ export class IntervalNode { this.interval = interval; this.maxEnd = this.interval.end; - this.resultInterval = null; + this.resultInterval = new Interval(0, 0); } public detach(): void { @@ -417,28 +417,51 @@ export class IntervalTree { this.root = SENTINEL; } - // public intervalSearch(interval: Interval): IntervalNode[] { - // let result: IntervalNode[] = []; - // if (this.root !== SENTINEL) { - // this._intervalSearch(this.root, 0, interval, result); - // } - // return result; - // } + public intervalSearch(interval: Interval): IntervalNode[] { + let result: IntervalNode[] = []; + if (this.root !== SENTINEL) { + this._intervalSearch(this.root, 0, interval.start, interval.end, result); + } + return result; + } - // private _intervalSearch(node: IntervalNode, delta: number, interval: Interval, result: IntervalNode[]): void { - // // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree - // // Now, it is known that two intervals A and B overlap only when both - // // A.low ≤ B.high and A.high ≥ B.low. When searching the trees for - // // nodes overlapping with a given interval, you can immediately skip: - // // - all nodes to the right of nodes whose low value is past the end of the given interval. - // // - all nodes that have their maximum 'high' value below the start of the given interval. + private _intervalSearch(node: IntervalNode, delta: number, intervalStart: number, intervalEnd: number, result: IntervalNode[]): void { + // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + // Now, it is known that two intervals A and B overlap only when both + // A.low <= B.high and A.high >= B.low. When searching the trees for + // nodes overlapping with a given interval, you can immediately skip: + // a) all nodes to the right of nodes whose low value is past the end of the given interval. + // b) all nodes that have their maximum 'high' value below the start of the given interval. - // if (delta + node.maxEnd < interval.start) { - // return; - // } + const nodeMaxEnd = delta + node.maxEnd; + if (nodeMaxEnd < intervalStart) { + // Cover b) from above + return; + } + if (node.left !== SENTINEL) { + this._intervalSearch(node.left, delta, intervalStart, intervalEnd, result); + } - // } + const nodeStart = delta + node.interval.start; + + if (nodeStart > intervalEnd) { + // Cover a) from above + return; + } + + const nodeEnd = delta + node.interval.end; + if (nodeEnd >= intervalStart) { + // There is overlap + node.resultInterval.start = nodeStart; + node.resultInterval.end = nodeEnd; + result.push(node); + } + + if (node.right !== SENTINEL) { + this._intervalSearch(node.right, delta + node.delta, intervalStart, intervalEnd, result); + } + } public insert(interval: Interval): IntervalNode { if (this.root === SENTINEL) { diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index 3c5caac63fc..ec6d1dcfe1a 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -43,6 +43,17 @@ suite('IntervalTree', () => { } } } + + public search(interval: Interval): Interval[] { + let result: Interval[] = []; + for (let i = 0, len = this.intervals.length; i < len; i++) { + let int = this.intervals[i]; + if (int.start <= interval.end && int.end >= interval.start) { + result.push(int); + } + } + return result; + } } class TestState { @@ -62,7 +73,7 @@ suite('IntervalTree', () => { let nodeId = (++this._lastNodeId); this._treeNodes[nodeId] = this._tree.insert(new Interval(op.begin, op.end)); this._oracleNodes[nodeId] = this._oracle.insert(new Interval(op.begin, op.end)); - } else { + } else if (op.type === 'delete') { if (PRINT_TREE) { console.log(`delete: {${JSON.stringify(this._oracleNodes[op.id])}}`); } @@ -71,6 +82,12 @@ suite('IntervalTree', () => { this._treeNodes[op.id] = null; this._oracleNodes[op.id] = null; + } else { + let actualNodes = this._tree.intervalSearch(new Interval(op.begin, op.end)); + let actual = actualNodes.map(n => n.resultInterval); + let expected = this._oracle.search(new Interval(op.begin, op.end)); + assert.deepEqual(actual, expected); + return; } if (PRINT_TREE) { @@ -110,7 +127,13 @@ suite('IntervalTree', () => { id: number; } - type IOperation = IInsertOperation | IDeleteOperation; + interface ISearchOperation { + type: 'search'; + begin: number; + end: number; + } + + type IOperation = IInsertOperation | IDeleteOperation | ISearchOperation; function testIntervalTree(ops: IOperation[]): void { let state = new TestState(); @@ -123,6 +146,19 @@ suite('IntervalTree', () => { return Math.floor(Math.random() * (max - min + 1)) + min; } + function getRandomRange(min: number, max: number): [number, number] { + let begin = getRandomInt(min, max); + let length: number; + if (getRandomInt(1, 10) <= 2) { + // large range + length = getRandomInt(0, max - begin); + } else { + // small range + length = getRandomInt(0, Math.min(max - begin, 10)); + } + return [begin, begin + length]; + } + class AutoTest { private _ops: IOperation[] = []; private _state: TestState = new TestState(); @@ -143,19 +179,11 @@ suite('IntervalTree', () => { type = 'delete'; } if (type === 'insert') { - let begin = getRandomInt(MIN_INTERVAL_START, MAX_INTERVAL_END); - let length: number; - if (getRandomInt(1, 10) <= 2) { - // large range - length = getRandomInt(0, MAX_INTERVAL_END - begin); - } else { - // small range - length = getRandomInt(0, Math.min(MAX_INTERVAL_END - begin, 10)); - } + let range = getRandomRange(MIN_INTERVAL_START, MAX_INTERVAL_END); this._run({ type: 'insert', - begin: begin, - end: begin + length + begin: range[0], + end: range[1] }); this._insertCnt--; this._deleteCnt++; @@ -166,8 +194,15 @@ suite('IntervalTree', () => { id: this._state.getExistingNodeId(idx) }); this._deleteCnt--; - // this._deleteCnt = 0; } + + // Let's also search for something... + let searchRange = getRandomRange(MIN_INTERVAL_START, MAX_INTERVAL_END); + this._run({ + type: 'search', + begin: searchRange[0], + end: searchRange[1] + }); } } @@ -182,167 +217,169 @@ suite('IntervalTree', () => { } - test('gen01', () => { - testIntervalTree([ - { type: 'insert', begin: 28, end: 35 }, - { type: 'insert', begin: 52, end: 54 }, - { type: 'insert', begin: 63, end: 69 } - ]); - }); + suite('generated', () => { + test('gen01', () => { + testIntervalTree([ + { type: 'insert', begin: 28, end: 35 }, + { type: 'insert', begin: 52, end: 54 }, + { type: 'insert', begin: 63, end: 69 } + ]); + }); - test('gen02', () => { - testIntervalTree([ - { type: 'insert', begin: 80, end: 89 }, - { type: 'insert', begin: 92, end: 100 }, - { type: 'insert', begin: 99, end: 99 } - ]); - }); + test('gen02', () => { + testIntervalTree([ + { type: 'insert', begin: 80, end: 89 }, + { type: 'insert', begin: 92, end: 100 }, + { type: 'insert', begin: 99, end: 99 } + ]); + }); - test('gen03', () => { - testIntervalTree([ - { type: 'insert', begin: 89, end: 96 }, - { type: 'insert', begin: 71, end: 74 }, - { type: 'delete', id: 1 } - ]); - }); + test('gen03', () => { + testIntervalTree([ + { type: 'insert', begin: 89, end: 96 }, + { type: 'insert', begin: 71, end: 74 }, + { type: 'delete', id: 1 } + ]); + }); - test('gen04', () => { - testIntervalTree([ - { type: 'insert', begin: 44, end: 46 }, - { type: 'insert', begin: 85, end: 88 }, - { type: 'delete', id: 0 } - ]); - }); + test('gen04', () => { + testIntervalTree([ + { type: 'insert', begin: 44, end: 46 }, + { type: 'insert', begin: 85, end: 88 }, + { type: 'delete', id: 0 } + ]); + }); - test('gen05', () => { - testIntervalTree([ - { type: 'insert', begin: 82, end: 90 }, - { type: 'insert', begin: 69, end: 73 }, - { type: 'delete', id: 0 }, - { type: 'delete', id: 1 } - ]); - }); + test('gen05', () => { + testIntervalTree([ + { type: 'insert', begin: 82, end: 90 }, + { type: 'insert', begin: 69, end: 73 }, + { type: 'delete', id: 0 }, + { type: 'delete', id: 1 } + ]); + }); - test('gen06', () => { - testIntervalTree([ - { type: 'insert', begin: 41, end: 63 }, - { type: 'insert', begin: 98, end: 98 }, - { type: 'insert', begin: 47, end: 51 }, - { type: 'delete', id: 2 } - ]); - }); + test('gen06', () => { + testIntervalTree([ + { type: 'insert', begin: 41, end: 63 }, + { type: 'insert', begin: 98, end: 98 }, + { type: 'insert', begin: 47, end: 51 }, + { type: 'delete', id: 2 } + ]); + }); - test('gen07', () => { - testIntervalTree([ - { type: 'insert', begin: 24, end: 26 }, - { type: 'insert', begin: 11, end: 28 }, - { type: 'insert', begin: 27, end: 30 }, - { type: 'insert', begin: 80, end: 85 }, - { type: 'delete', id: 1 } - ]); - }); + test('gen07', () => { + testIntervalTree([ + { type: 'insert', begin: 24, end: 26 }, + { type: 'insert', begin: 11, end: 28 }, + { type: 'insert', begin: 27, end: 30 }, + { type: 'insert', begin: 80, end: 85 }, + { type: 'delete', id: 1 } + ]); + }); - test('gen08', () => { - testIntervalTree([ - { type: 'insert', begin: 100, end: 100 }, - { type: 'insert', begin: 100, end: 100 } - ]); - }); + test('gen08', () => { + testIntervalTree([ + { type: 'insert', begin: 100, end: 100 }, + { type: 'insert', begin: 100, end: 100 } + ]); + }); - test('gen09', () => { - testIntervalTree([ - { type: 'insert', begin: 58, end: 65 }, - { type: 'insert', begin: 82, end: 96 }, - { type: 'insert', begin: 58, end: 65 } - ]); - }); + test('gen09', () => { + testIntervalTree([ + { type: 'insert', begin: 58, end: 65 }, + { type: 'insert', begin: 82, end: 96 }, + { type: 'insert', begin: 58, end: 65 } + ]); + }); - test('gen10', () => { - testIntervalTree([ - { type: 'insert', begin: 32, end: 40 }, - { type: 'insert', begin: 25, end: 29 }, - { type: 'insert', begin: 24, end: 32 } - ]); - }); + test('gen10', () => { + testIntervalTree([ + { type: 'insert', begin: 32, end: 40 }, + { type: 'insert', begin: 25, end: 29 }, + { type: 'insert', begin: 24, end: 32 } + ]); + }); - test('gen11', () => { - testIntervalTree([ - { type: 'insert', begin: 25, end: 70 }, - { type: 'insert', begin: 99, end: 100 }, - { type: 'insert', begin: 46, end: 51 }, - { type: 'insert', begin: 57, end: 57 }, - { type: 'delete', id: 2 } - ]); - }); + test('gen11', () => { + testIntervalTree([ + { type: 'insert', begin: 25, end: 70 }, + { type: 'insert', begin: 99, end: 100 }, + { type: 'insert', begin: 46, end: 51 }, + { type: 'insert', begin: 57, end: 57 }, + { type: 'delete', id: 2 } + ]); + }); - test('gen12', () => { - testIntervalTree([ - { type: 'insert', begin: 20, end: 26 }, - { type: 'insert', begin: 10, end: 18 }, - { type: 'insert', begin: 99, end: 99 }, - { type: 'insert', begin: 37, end: 59 }, - { type: 'delete', id: 2 } - ]); - }); + test('gen12', () => { + testIntervalTree([ + { type: 'insert', begin: 20, end: 26 }, + { type: 'insert', begin: 10, end: 18 }, + { type: 'insert', begin: 99, end: 99 }, + { type: 'insert', begin: 37, end: 59 }, + { type: 'delete', id: 2 } + ]); + }); - test('gen13', () => { - testIntervalTree([ - { type: 'insert', begin: 3, end: 91 }, - { type: 'insert', begin: 57, end: 57 }, - { type: 'insert', begin: 35, end: 44 }, - { type: 'insert', begin: 72, end: 81 }, - { type: 'delete', id: 2 } - ]); - }); + test('gen13', () => { + testIntervalTree([ + { type: 'insert', begin: 3, end: 91 }, + { type: 'insert', begin: 57, end: 57 }, + { type: 'insert', begin: 35, end: 44 }, + { type: 'insert', begin: 72, end: 81 }, + { type: 'delete', id: 2 } + ]); + }); - test('gen14', () => { - testIntervalTree([ - { type: 'insert', begin: 58, end: 61 }, - { type: 'insert', begin: 34, end: 35 }, - { type: 'insert', begin: 56, end: 62 }, - { type: 'insert', begin: 69, end: 78 }, - { type: 'delete', id: 0 } - ]); - }); + test('gen14', () => { + testIntervalTree([ + { type: 'insert', begin: 58, end: 61 }, + { type: 'insert', begin: 34, end: 35 }, + { type: 'insert', begin: 56, end: 62 }, + { type: 'insert', begin: 69, end: 78 }, + { type: 'delete', id: 0 } + ]); + }); - test('gen15', () => { - testIntervalTree([ - { type: 'insert', begin: 63, end: 69 }, - { type: 'insert', begin: 17, end: 24 }, - { type: 'insert', begin: 3, end: 13 }, - { type: 'insert', begin: 84, end: 94 }, - { type: 'insert', begin: 18, end: 23 }, - { type: 'insert', begin: 96, end: 98 }, - { type: 'delete', id: 1 } - ]); - }); + test('gen15', () => { + testIntervalTree([ + { type: 'insert', begin: 63, end: 69 }, + { type: 'insert', begin: 17, end: 24 }, + { type: 'insert', begin: 3, end: 13 }, + { type: 'insert', begin: 84, end: 94 }, + { type: 'insert', begin: 18, end: 23 }, + { type: 'insert', begin: 96, end: 98 }, + { type: 'delete', id: 1 } + ]); + }); - test('gen16', () => { - testIntervalTree([ - { type: 'insert', begin: 27, end: 27 }, - { type: 'insert', begin: 42, end: 87 }, - { type: 'insert', begin: 42, end: 49 }, - { type: 'insert', begin: 69, end: 71 }, - { type: 'insert', begin: 20, end: 27 }, - { type: 'insert', begin: 8, end: 9 }, - { type: 'insert', begin: 42, end: 49 }, - { type: 'delete', id: 1 } - ]); - }); + test('gen16', () => { + testIntervalTree([ + { type: 'insert', begin: 27, end: 27 }, + { type: 'insert', begin: 42, end: 87 }, + { type: 'insert', begin: 42, end: 49 }, + { type: 'insert', begin: 69, end: 71 }, + { type: 'insert', begin: 20, end: 27 }, + { type: 'insert', begin: 8, end: 9 }, + { type: 'insert', begin: 42, end: 49 }, + { type: 'delete', id: 1 } + ]); + }); - test('gen17', () => { - testIntervalTree([ - { type: 'insert', begin: 21, end: 23 }, - { type: 'insert', begin: 83, end: 87 }, - { type: 'insert', begin: 56, end: 58 }, - { type: 'insert', begin: 1, end: 55 }, - { type: 'insert', begin: 56, end: 59 }, - { type: 'insert', begin: 58, end: 60 }, - { type: 'insert', begin: 56, end: 65 }, - { type: 'delete', id: 1 }, - { type: 'delete', id: 0 }, - { type: 'delete', id: 6 } - ]); + test('gen17', () => { + testIntervalTree([ + { type: 'insert', begin: 21, end: 23 }, + { type: 'insert', begin: 83, end: 87 }, + { type: 'insert', begin: 56, end: 58 }, + { type: 'insert', begin: 1, end: 55 }, + { type: 'insert', begin: 56, end: 59 }, + { type: 'insert', begin: 58, end: 60 }, + { type: 'insert', begin: 56, end: 65 }, + { type: 'delete', id: 1 }, + { type: 'delete', id: 0 }, + { type: 'delete', id: 6 } + ]); + }); }); // TEST_COUNT = 0; @@ -362,4 +399,84 @@ suite('IntervalTree', () => { return; } } + + suite('searching', () => { + + function createCormenTree(): IntervalTree { + let r = new IntervalTree(); + let data: [number, number][] = [ + [16, 21], + [8, 9], + [25, 30], + [5, 8], + [15, 23], + [17, 19], + [26, 26], + [0, 3], + [6, 10], + [19, 20] + ]; + data.forEach((int) => { + r.insert(new Interval(int[0], int[1])); + }); + return r; + } + + const T = createCormenTree(); + + function assertIntervalSearch(start: number, end: number, expected: [number, number][]): void { + let actualNodes = T.intervalSearch(new Interval(start, end)); + let actual = actualNodes.map((n) => <[number, number]>[n.resultInterval.start, n.resultInterval.end]); + assert.deepEqual(actual, expected); + } + + test('cormen 1->2', () => { + assertIntervalSearch( + 1, 2, + [ + [0, 3], + ] + ); + }); + + test('cormen 4->8', () => { + assertIntervalSearch( + 4, 8, + [ + [5, 8], + [6, 10], + [8, 9], + ] + ); + }); + + test('cormen 10->15', () => { + assertIntervalSearch( + 10, 15, + [ + [6, 10], + [15, 23], + ] + ); + }); + + test('cormen 21->25', () => { + assertIntervalSearch( + 21, 25, + [ + [15, 23], + [16, 21], + [25, 30], + ] + ); + }); + + test('cormen 24->24', () => { + assertIntervalSearch( + 24, 24, + [ + ] + ); + }); + }); }); From 8e6968f75fba6e7c5122019bb0644211a6c86337 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 16:38:34 +0200 Subject: [PATCH 040/394] Eliminate RelativeInterval --- src/vs/editor/common/model/intervalTree.ts | 150 +++++++++------------ 1 file changed, 64 insertions(+), 86 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 60d9f8ca73d..b612fe64607 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -19,32 +19,14 @@ export class Interval { this.end = end; } - public compareToRelative(other: RelativeInterval, delta: number): number { - const otherStart = other.start + delta; + public compareToRelative(otherStart: number, otherEnd: number): number { if (this.start === otherStart) { - const otherEnd = other.end + delta; return this.end - otherEnd; } return this.start - otherStart; } } -export class RelativeInterval { - _relativeIntervalBrand: void; - - public static fromInterval(interval: Interval, delta: number): RelativeInterval { - return new RelativeInterval(interval.start - delta, interval.end - delta); - } - - public start: number; - public end: number; - - constructor(start: number, end: number) { - this.start = start; - this.end = end; - } -} - export const enum NodeColor { Red, Black @@ -57,21 +39,23 @@ export class IntervalNode { public parent: IntervalNode; public color: NodeColor; + public start: number; + public end: number; public delta: number; - public interval: RelativeInterval; public maxEnd: number; public resultInterval: Interval; - constructor(interval: RelativeInterval, delta: number) { + constructor(start: number, end: number) { this.parent = null; this.left = null; this.right = null; this.color = NodeColor.Red; - this.delta = delta; - this.interval = interval; - this.maxEnd = this.interval.end; + this.start = start; + this.end = end; + this.delta = start; + this.maxEnd = end; this.resultInterval = new Interval(0, 0); } @@ -83,7 +67,7 @@ export class IntervalNode { } } -const SENTINEL: IntervalNode = new IntervalNode(new RelativeInterval(0, 0), 0); +const SENTINEL: IntervalNode = new IntervalNode(0, 0); SENTINEL.parent = SENTINEL; SENTINEL.left = SENTINEL; SENTINEL.right = SENTINEL; @@ -93,8 +77,8 @@ function leftRotate(T: IntervalTree, x: IntervalNode): void { const y = x.right; // set y. y.delta += x.delta; // y's delta is no longer influenced by x's delta - y.interval.start += x.delta; - y.interval.end += x.delta; + y.start += x.delta; + y.end += x.delta; x.right = y.left; // turn y's left subtree into x's right subtree. if (y.left !== SENTINEL) { @@ -120,8 +104,8 @@ function rightRotate(T: IntervalTree, y: IntervalNode): void { const x = y.left; y.delta -= x.delta; - y.interval.start -= x.delta; - y.interval.end -= x.delta; + y.start -= x.delta; + y.end -= x.delta; y.left = x.right; if (x.right !== SENTINEL) { @@ -148,13 +132,12 @@ function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { let z = SENTINEL; let x = T.root; while (true) { - let cmp = interval.compareToRelative(x.interval, delta); + let cmp = interval.compareToRelative(x.start + delta, x.end + delta); if (cmp < 0) { // this node should be inserted to the left // => it is not affected by the node's delta if (x.left === SENTINEL) { - const relativeInterval = RelativeInterval.fromInterval(interval, delta); - z = new IntervalNode(relativeInterval, relativeInterval.start); + z = new IntervalNode(interval.start - delta, interval.end - delta); x.left = z; break; } else { @@ -164,8 +147,7 @@ function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { // this node should be inserted to the right // => it is not affected by the node's delta if (x.right === SENTINEL) { - const relativeInterval = RelativeInterval.fromInterval(interval, delta + x.delta); - z = new IntervalNode(relativeInterval, relativeInterval.start); + z = new IntervalNode(interval.start - delta - x.delta, interval.end - delta - x.delta); x.right = z; break; } else { @@ -192,12 +174,12 @@ function leftest(node: IntervalNode): IntervalNode { function resetSentinel(): void { SENTINEL.parent = SENTINEL; SENTINEL.delta = 0; // optional - SENTINEL.interval.start = 0; // optional - SENTINEL.interval.end = 0; // optional + SENTINEL.start = 0; // optional + SENTINEL.end = 0; // optional } function computeMaxEnd(node: IntervalNode): number { - let maxEnd = node.interval.end; + let maxEnd = node.end; if (node.left !== SENTINEL) { const leftMaxEnd = node.left.maxEnd; if (leftMaxEnd > maxEnd) { @@ -246,8 +228,8 @@ function treeDelete(T: IntervalTree, z: IntervalNode): void { // x's delta is no longer influenced by z's delta x.delta += z.delta; - x.interval.start += z.delta; - x.interval.end += z.delta; + x.start += z.delta; + x.end += z.delta; } else if (z.right === SENTINEL) { x = z.left; @@ -260,15 +242,12 @@ function treeDelete(T: IntervalTree, z: IntervalNode): void { // y's delta is no longer influenced by z's delta, // but we don't want to walk the entire right-hand-side subtree of x. // we therefore maintain z's delta in y, and adjust only x - x.interval.start += y.delta; - x.interval.end += y.delta; - // if (x.interval.end > x.maxEnd) { - // x.maxEnd = x.interval.end; - // } + x.start += y.delta; + x.end += y.delta; x.delta += y.delta; - y.interval.start += z.delta; - y.interval.end += z.delta; + y.start += z.delta; + y.end += z.delta; y.delta = z.delta; } @@ -443,14 +422,14 @@ export class IntervalTree { this._intervalSearch(node.left, delta, intervalStart, intervalEnd, result); } - const nodeStart = delta + node.interval.start; + const nodeStart = delta + node.start; if (nodeStart > intervalEnd) { // Cover a) from above return; } - const nodeEnd = delta + node.interval.end; + const nodeEnd = delta + node.end; if (nodeEnd >= intervalStart) { // There is overlap node.resultInterval.start = nodeStart; @@ -465,8 +444,7 @@ export class IntervalTree { public insert(interval: Interval): IntervalNode { if (this.root === SENTINEL) { - const relativeInterval = RelativeInterval.fromInterval(interval, 0); - const newNode = new IntervalNode(relativeInterval, relativeInterval.start); + const newNode = new IntervalNode(interval.start, interval.end); newNode.parent = SENTINEL; newNode.left = SENTINEL; newNode.right = SENTINEL; @@ -480,41 +458,41 @@ export class IntervalTree { recomputeMaxEndToRoot(newNode.parent); // repair tree - let node = newNode; - while (node !== this.root && node.parent.color === NodeColor.Red) { - if (node.parent === node.parent.parent.left) { - const temp = node.parent.parent.right; + let x = newNode; + while (x !== this.root && x.parent.color === NodeColor.Red) { + if (x.parent === x.parent.parent.left) { + const y = x.parent.parent.right; - if (temp.color === NodeColor.Red) { - node.parent.color = NodeColor.Black; - temp.color = NodeColor.Black; - node.parent.parent.color = NodeColor.Red; - node = node.parent.parent; + if (y.color === NodeColor.Red) { + x.parent.color = NodeColor.Black; + y.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + x = x.parent.parent; } else { - if (node === node.parent.right) { - node = node.parent; - leftRotate(this, node); + if (x === x.parent.right) { + x = x.parent; + leftRotate(this, x); } - node.parent.color = NodeColor.Black; - node.parent.parent.color = NodeColor.Red; - rightRotate(this, node.parent.parent); + x.parent.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + rightRotate(this, x.parent.parent); } } else { - const temp = node.parent.parent.left; + const y = x.parent.parent.left; - if (temp.color === NodeColor.Red) { - node.parent.color = NodeColor.Black; - temp.color = NodeColor.Black; - node.parent.parent.color = NodeColor.Red; - node = node.parent.parent; + if (y.color === NodeColor.Red) { + x.parent.color = NodeColor.Black; + y.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + x = x.parent.parent; } else { - if (node === node.parent.left) { - node = node.parent; - rightRotate(this, node); + if (x === x.parent.left) { + x = x.parent; + rightRotate(this, x); } - node.parent.color = NodeColor.Black; - node.parent.parent.color = NodeColor.Red; - leftRotate(this, node.parent.parent); + x.parent.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + leftRotate(this, x.parent.parent); } } } @@ -533,8 +511,8 @@ export class IntervalTree { assert(SENTINEL.parent === SENTINEL); assert(SENTINEL.left === SENTINEL); assert(SENTINEL.right === SENTINEL); - assert(SENTINEL.interval.start === 0); - assert(SENTINEL.interval.end === 0); + assert(SENTINEL.start === 0); + assert(SENTINEL.end === 0); assert(SENTINEL.delta === 0); assertValidTree(this); } @@ -542,7 +520,7 @@ export class IntervalTree { public getAllInOrder(): Interval[] { let r: Interval[] = [], rLength = 0; this.visitInOrder((n, delta) => { - r[rLength++] = new Interval(n.interval.start + delta, n.interval.end + delta); + r[rLength++] = new Interval(n.start + delta, n.end + delta); }); return r; } @@ -572,7 +550,7 @@ export class IntervalTree { } private _print(n: IntervalNode, indent: string, delta: number, out: string[]): void { - out.push(`${indent}[${n.color === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.interval.start}->${n.interval.end}, ${n.maxEnd}] : {${delta + n.interval.start}->${delta + n.interval.end}}, maxEnd: ${n.maxEnd + delta}\n`); + out.push(`${indent}[${n.color === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.start}->${n.end}, ${n.maxEnd}] : {${delta + n.start}->${delta + n.end}}, maxEnd: ${n.maxEnd + delta}\n`); if (n.left !== SENTINEL) { this._print(n.left, indent + ' ', delta, out); } else { @@ -612,15 +590,15 @@ function assertValidNode(n: IntervalNode, delta): void { } } - let expectedMaxEnd = n.interval.end; + let expectedMaxEnd = n.end; if (l !== SENTINEL) { - const lValue = new Interval(l.interval.start + delta, l.interval.end + delta); - assert(lValue.compareToRelative(n.interval, delta) <= 0); + const lValue = new Interval(l.start + delta, l.end + delta); + assert(lValue.compareToRelative(n.start + delta, n.end + delta) <= 0); expectedMaxEnd = Math.max(expectedMaxEnd, l.maxEnd); } if (r !== SENTINEL) { - const nValue = new Interval(n.interval.start + delta, n.interval.end + delta); - assert(nValue.compareToRelative(r.interval, delta + n.delta) <= 0); + const nValue = new Interval(n.start + delta, n.end + delta); + assert(nValue.compareToRelative(r.start + delta + n.delta, r.end + delta + n.delta) <= 0); expectedMaxEnd = Math.max(expectedMaxEnd, r.maxEnd + n.delta); } assert(n.maxEnd === expectedMaxEnd); From a324329559cb6a40bce3cbd12d1488224d682001 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 17:15:13 +0200 Subject: [PATCH 041/394] Reorganize code --- src/vs/editor/common/model/intervalTree.ts | 559 +++++++++++---------- 1 file changed, 286 insertions(+), 273 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index b612fe64607..4960d1274a6 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -73,58 +73,188 @@ SENTINEL.left = SENTINEL; SENTINEL.right = SENTINEL; SENTINEL.color = NodeColor.Black; -function leftRotate(T: IntervalTree, x: IntervalNode): void { - const y = x.right; // set y. +export class IntervalTree { - y.delta += x.delta; // y's delta is no longer influenced by x's delta - y.start += x.delta; - y.end += x.delta; + public root: IntervalNode; - x.right = y.left; // turn y's left subtree into x's right subtree. - if (y.left !== SENTINEL) { - y.left.parent = x; - } - y.parent = x.parent; // link x's parent to y. - if (x.parent === SENTINEL) { - T.root = y; - } else if (x === x.parent.left) { - x.parent.left = y; - } else { - x.parent.right = y; + constructor() { + this.root = SENTINEL; } - y.left = x; // put x on y's left. - x.parent = y; + public intervalSearch(interval: Interval): IntervalNode[] { + if (this.root === SENTINEL) { + return []; + } + let result: IntervalNode[] = []; + intervalSearchRecursive(this.root, 0, interval.start, interval.end, result); + return result; + } - recomputeMaxEnd(x); - recomputeMaxEnd(y); + public insert(interval: Interval): IntervalNode { + return rbTreeInsert(this, interval); + } + + public delete(node: IntervalNode) { + rbTreeDelete(this, node); + } + + public assertInvariants(): void { + assert(SENTINEL.color === NodeColor.Black); + assert(SENTINEL.parent === SENTINEL); + assert(SENTINEL.left === SENTINEL); + assert(SENTINEL.right === SENTINEL); + assert(SENTINEL.start === 0); + assert(SENTINEL.end === 0); + assert(SENTINEL.delta === 0); + assertValidTree(this); + } + + public getAllInOrder(): Interval[] { + let r: Interval[] = [], rLength = 0; + this.visitInOrder((n, delta) => { + r[rLength++] = new Interval(n.start + delta, n.end + delta); + }); + return r; + } + + public visitInOrder(visitor: (n: IntervalNode, delta: number) => void): void { + this._visitInOrder(this.root, 0, visitor); + } + + private _visitInOrder(n: IntervalNode, delta: number, visitor: (n: IntervalNode, delta: number) => void): void { + if (n.left !== SENTINEL) { + this._visitInOrder(n.left, delta, visitor); + } + + if (n !== SENTINEL) { + visitor(n, delta); + } + + if (n.right !== SENTINEL) { + this._visitInOrder(n.right, delta + n.delta, visitor); + } + } + + public print(): void { + let out: string[] = []; + this._print(this.root, '', 0, out); + console.log(out.join('')); + } + + private _print(n: IntervalNode, indent: string, delta: number, out: string[]): void { + out.push(`${indent}[${n.color === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.start}->${n.end}, ${n.maxEnd}] : {${delta + n.start}->${delta + n.end}}, maxEnd: ${n.maxEnd + delta}\n`); + if (n.left !== SENTINEL) { + this._print(n.left, indent + ' ', delta, out); + } else { + out.push(`${indent} NIL\n`); + } + if (n.right !== SENTINEL) { + this._print(n.right, indent + ' ', delta + n.delta, out); + } else { + out.push(`${indent} NIL\n`); + } + } } -function rightRotate(T: IntervalTree, y: IntervalNode): void { - const x = y.left; +//#region Searching +function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStart: number, intervalEnd: number, result: IntervalNode[]): void { + // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + // Now, it is known that two intervals A and B overlap only when both + // A.low <= B.high and A.high >= B.low. When searching the trees for + // nodes overlapping with a given interval, you can immediately skip: + // a) all nodes to the right of nodes whose low value is past the end of the given interval. + // b) all nodes that have their maximum 'high' value below the start of the given interval. - y.delta -= x.delta; - y.start -= x.delta; - y.end -= x.delta; - - y.left = x.right; - if (x.right !== SENTINEL) { - x.right.parent = y; - } - x.parent = y.parent; - if (y.parent === SENTINEL) { - T.root = x; - } else if (y === y.parent.right) { - y.parent.right = x; - } else { - y.parent.left = x; + const nodeMaxEnd = delta + node.maxEnd; + if (nodeMaxEnd < intervalStart) { + // Cover b) from above + return; } - x.right = y; - y.parent = x; + if (node.left !== SENTINEL) { + intervalSearchRecursive(node.left, delta, intervalStart, intervalEnd, result); + } - recomputeMaxEnd(y); - recomputeMaxEnd(x); + const nodeStart = delta + node.start; + + if (nodeStart > intervalEnd) { + // Cover a) from above + return; + } + + const nodeEnd = delta + node.end; + if (nodeEnd >= intervalStart) { + // There is overlap + node.resultInterval.start = nodeStart; + node.resultInterval.end = nodeEnd; + result.push(node); + } + + if (node.right !== SENTINEL) { + intervalSearchRecursive(node.right, delta + node.delta, intervalStart, intervalEnd, result); + } +} +//#endregion + +//#region Insertion +function rbTreeInsert(T: IntervalTree, interval: Interval): IntervalNode { + if (T.root === SENTINEL) { + const newNode = new IntervalNode(interval.start, interval.end); + newNode.parent = SENTINEL; + newNode.left = SENTINEL; + newNode.right = SENTINEL; + newNode.color = NodeColor.Black; + T.root = newNode; + return T.root; + } + + const newNode = treeInsert(T, interval); + + recomputeMaxEndWalkToRoot(newNode.parent); + + // repair tree + let x = newNode; + while (x !== T.root && x.parent.color === NodeColor.Red) { + if (x.parent === x.parent.parent.left) { + const y = x.parent.parent.right; + + if (y.color === NodeColor.Red) { + x.parent.color = NodeColor.Black; + y.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + x = x.parent.parent; + } else { + if (x === x.parent.right) { + x = x.parent; + leftRotate(T, x); + } + x.parent.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + rightRotate(T, x.parent.parent); + } + } else { + const y = x.parent.parent.left; + + if (y.color === NodeColor.Red) { + x.parent.color = NodeColor.Black; + y.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + x = x.parent.parent; + } else { + if (x === x.parent.left) { + x = x.parent; + rightRotate(T, x); + } + x.parent.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + leftRotate(T, x.parent.parent); + } + } + } + + T.root.color = NodeColor.Black; + + return newNode; } function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { @@ -163,58 +293,10 @@ function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { z.color = NodeColor.Red; return z; } +//#endregion -function leftest(node: IntervalNode): IntervalNode { - while (node.left !== SENTINEL) { - node = node.left; - } - return node; -} - -function resetSentinel(): void { - SENTINEL.parent = SENTINEL; - SENTINEL.delta = 0; // optional - SENTINEL.start = 0; // optional - SENTINEL.end = 0; // optional -} - -function computeMaxEnd(node: IntervalNode): number { - let maxEnd = node.end; - if (node.left !== SENTINEL) { - const leftMaxEnd = node.left.maxEnd; - if (leftMaxEnd > maxEnd) { - maxEnd = leftMaxEnd; - } - } - if (node.right !== SENTINEL) { - const rightMaxEnd = node.right.maxEnd + node.delta; - if (rightMaxEnd > maxEnd) { - maxEnd = rightMaxEnd; - } - } - return maxEnd; -} - -function recomputeMaxEnd(node: IntervalNode): void { - node.maxEnd = computeMaxEnd(node); -} - -function recomputeMaxEndToRoot(node: IntervalNode): void { - while (node !== SENTINEL) { - - const maxEnd = computeMaxEnd(node); - - if (node.maxEnd === maxEnd) { - // no need to go further - return; - } - - node.maxEnd = maxEnd; - node = node.parent; - } -} - -function treeDelete(T: IntervalTree, z: IntervalNode): void { +//#region Deletion +function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { let x: IntervalNode; let y: IntervalNode; @@ -305,20 +387,20 @@ function treeDelete(T: IntervalTree, z: IntervalNode): void { z.detach(); if (yWasRed) { - recomputeMaxEndToRoot(x.parent); + recomputeMaxEndWalkToRoot(x.parent); if (y !== z) { - recomputeMaxEndToRoot(y); - recomputeMaxEndToRoot(y.parent); + recomputeMaxEndWalkToRoot(y); + recomputeMaxEndWalkToRoot(y.parent); } resetSentinel(); return; } - recomputeMaxEndToRoot(x); - recomputeMaxEndToRoot(x.parent); + recomputeMaxEndWalkToRoot(x); + recomputeMaxEndWalkToRoot(x.parent); if (y !== z) { - recomputeMaxEndToRoot(y); - recomputeMaxEndToRoot(y.parent); + recomputeMaxEndWalkToRoot(y); + recomputeMaxEndWalkToRoot(y.parent); } // RB-DELETE-FIXUP @@ -388,182 +470,119 @@ function treeDelete(T: IntervalTree, z: IntervalNode): void { resetSentinel(); } -export class IntervalTree { +function leftest(node: IntervalNode): IntervalNode { + while (node.left !== SENTINEL) { + node = node.left; + } + return node; +} - public root: IntervalNode; +function resetSentinel(): void { + SENTINEL.parent = SENTINEL; + SENTINEL.delta = 0; // optional + SENTINEL.start = 0; // optional + SENTINEL.end = 0; // optional +} +//#endregion - constructor() { - this.root = SENTINEL; +//#region Rotations +function leftRotate(T: IntervalTree, x: IntervalNode): void { + const y = x.right; // set y. + + y.delta += x.delta; // y's delta is no longer influenced by x's delta + y.start += x.delta; + y.end += x.delta; + + x.right = y.left; // turn y's left subtree into x's right subtree. + if (y.left !== SENTINEL) { + y.left.parent = x; + } + y.parent = x.parent; // link x's parent to y. + if (x.parent === SENTINEL) { + T.root = y; + } else if (x === x.parent.left) { + x.parent.left = y; + } else { + x.parent.right = y; } - public intervalSearch(interval: Interval): IntervalNode[] { - let result: IntervalNode[] = []; - if (this.root !== SENTINEL) { - this._intervalSearch(this.root, 0, interval.start, interval.end, result); + y.left = x; // put x on y's left. + x.parent = y; + + recomputeMaxEnd(x); + recomputeMaxEnd(y); +} + +function rightRotate(T: IntervalTree, y: IntervalNode): void { + const x = y.left; + + y.delta -= x.delta; + y.start -= x.delta; + y.end -= x.delta; + + y.left = x.right; + if (x.right !== SENTINEL) { + x.right.parent = y; + } + x.parent = y.parent; + if (y.parent === SENTINEL) { + T.root = x; + } else if (y === y.parent.right) { + y.parent.right = x; + } else { + y.parent.left = x; + } + + x.right = y; + y.parent = x; + + recomputeMaxEnd(y); + recomputeMaxEnd(x); +} +//#endregion + +//#region max end computation + +function computeMaxEnd(node: IntervalNode): number { + let maxEnd = node.end; + if (node.left !== SENTINEL) { + const leftMaxEnd = node.left.maxEnd; + if (leftMaxEnd > maxEnd) { + maxEnd = leftMaxEnd; } - return result; } + if (node.right !== SENTINEL) { + const rightMaxEnd = node.right.maxEnd + node.delta; + if (rightMaxEnd > maxEnd) { + maxEnd = rightMaxEnd; + } + } + return maxEnd; +} - private _intervalSearch(node: IntervalNode, delta: number, intervalStart: number, intervalEnd: number, result: IntervalNode[]): void { - // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree - // Now, it is known that two intervals A and B overlap only when both - // A.low <= B.high and A.high >= B.low. When searching the trees for - // nodes overlapping with a given interval, you can immediately skip: - // a) all nodes to the right of nodes whose low value is past the end of the given interval. - // b) all nodes that have their maximum 'high' value below the start of the given interval. +function recomputeMaxEnd(node: IntervalNode): void { + node.maxEnd = computeMaxEnd(node); +} - const nodeMaxEnd = delta + node.maxEnd; - if (nodeMaxEnd < intervalStart) { - // Cover b) from above +function recomputeMaxEndWalkToRoot(node: IntervalNode): void { + while (node !== SENTINEL) { + + const maxEnd = computeMaxEnd(node); + + if (node.maxEnd === maxEnd) { + // no need to go further return; } - if (node.left !== SENTINEL) { - this._intervalSearch(node.left, delta, intervalStart, intervalEnd, result); - } - - const nodeStart = delta + node.start; - - if (nodeStart > intervalEnd) { - // Cover a) from above - return; - } - - const nodeEnd = delta + node.end; - if (nodeEnd >= intervalStart) { - // There is overlap - node.resultInterval.start = nodeStart; - node.resultInterval.end = nodeEnd; - result.push(node); - } - - if (node.right !== SENTINEL) { - this._intervalSearch(node.right, delta + node.delta, intervalStart, intervalEnd, result); - } - } - - public insert(interval: Interval): IntervalNode { - if (this.root === SENTINEL) { - const newNode = new IntervalNode(interval.start, interval.end); - newNode.parent = SENTINEL; - newNode.left = SENTINEL; - newNode.right = SENTINEL; - newNode.color = NodeColor.Black; - this.root = newNode; - return this.root; - } - - const newNode = treeInsert(this, interval); - - recomputeMaxEndToRoot(newNode.parent); - - // repair tree - let x = newNode; - while (x !== this.root && x.parent.color === NodeColor.Red) { - if (x.parent === x.parent.parent.left) { - const y = x.parent.parent.right; - - if (y.color === NodeColor.Red) { - x.parent.color = NodeColor.Black; - y.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; - x = x.parent.parent; - } else { - if (x === x.parent.right) { - x = x.parent; - leftRotate(this, x); - } - x.parent.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; - rightRotate(this, x.parent.parent); - } - } else { - const y = x.parent.parent.left; - - if (y.color === NodeColor.Red) { - x.parent.color = NodeColor.Black; - y.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; - x = x.parent.parent; - } else { - if (x === x.parent.left) { - x = x.parent; - rightRotate(this, x); - } - x.parent.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; - leftRotate(this, x.parent.parent); - } - } - } - - this.root.color = NodeColor.Black; - - return newNode; - } - - public delete(node: IntervalNode) { - treeDelete(this, node); - } - - public assertInvariants(): void { - assert(SENTINEL.color === NodeColor.Black); - assert(SENTINEL.parent === SENTINEL); - assert(SENTINEL.left === SENTINEL); - assert(SENTINEL.right === SENTINEL); - assert(SENTINEL.start === 0); - assert(SENTINEL.end === 0); - assert(SENTINEL.delta === 0); - assertValidTree(this); - } - - public getAllInOrder(): Interval[] { - let r: Interval[] = [], rLength = 0; - this.visitInOrder((n, delta) => { - r[rLength++] = new Interval(n.start + delta, n.end + delta); - }); - return r; - } - - public visitInOrder(visitor: (n: IntervalNode, delta: number) => void): void { - this._visitInOrder(this.root, 0, visitor); - } - - private _visitInOrder(n: IntervalNode, delta: number, visitor: (n: IntervalNode, delta: number) => void): void { - if (n.left !== SENTINEL) { - this._visitInOrder(n.left, delta, visitor); - } - - if (n !== SENTINEL) { - visitor(n, delta); - } - - if (n.right !== SENTINEL) { - this._visitInOrder(n.right, delta + n.delta, visitor); - } - } - - public print(): void { - let out: string[] = []; - this._print(this.root, '', 0, out); - console.log(out.join('')); - } - - private _print(n: IntervalNode, indent: string, delta: number, out: string[]): void { - out.push(`${indent}[${n.color === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.start}->${n.end}, ${n.maxEnd}] : {${delta + n.start}->${delta + n.end}}, maxEnd: ${n.maxEnd + delta}\n`); - if (n.left !== SENTINEL) { - this._print(n.left, indent + ' ', delta, out); - } else { - out.push(`${indent} NIL\n`); - } - if (n.right !== SENTINEL) { - this._print(n.right, indent + ' ', delta + n.delta, out); - } else { - out.push(`${indent} NIL\n`); - } + node.maxEnd = maxEnd; + node = node.parent; } } +//#endregion + +//#region Assertion + function depth(n: IntervalNode): number { if (n === SENTINEL) { // The leafs are black @@ -582,12 +601,8 @@ function assertValidNode(n: IntervalNode, delta): void { let r = n.right; if (n.color === NodeColor.Red) { - if (l.color !== NodeColor.Black) { - assert(false); - } - if (r.color !== NodeColor.Black) { - assert(false); - } + assert(l.color === NodeColor.Black); + assert(r.color === NodeColor.Black); } let expectedMaxEnd = n.end; @@ -611,12 +626,8 @@ function assertValidTree(tree: IntervalTree): void { if (tree.root === SENTINEL) { return; } - if (tree.root.color !== NodeColor.Black) { - assert(false); - } - if (depth(tree.root.left) !== depth(tree.root.right)) { - assert(false); - } + assert(tree.root.color === NodeColor.Black); + assert(depth(tree.root.left) === depth(tree.root.right)); assertValidNode(tree.root, 0); } @@ -625,3 +636,5 @@ function assert(condition: boolean): void { throw new Error('Assertion violation'); } } + +//#endregion From 7088898d4487ebacb4d2cee79db992caf537a6f5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 12 Oct 2017 17:32:44 +0200 Subject: [PATCH 042/394] Use a configuration event that can answer if a configuration has changed or not given a resource and override identifier. Requested configuration can be full key or section --- .../configuration/common/configuration.ts | 32 ++--- .../common/configurationModels.ts | 109 +++++++++++++++++- .../node/configurationService.ts | 6 +- .../parts/debug/browser/debugActionItems.ts | 2 +- .../watermark/electron-browser/watermark.ts | 2 +- .../common/configurationModels.ts | 70 +++++++---- .../node/configurationService.ts | 47 ++++---- 7 files changed, 193 insertions(+), 75 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index b9cbfb0a599..a2132efea12 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import * as arrays from 'vs/base/common/arrays'; import * as objects from 'vs/base/common/objects'; import * as types from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; @@ -12,7 +11,7 @@ import Event from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; export const IConfigurationService = createDecorator('configurationService'); @@ -30,12 +29,12 @@ export enum ConfigurationTarget { } export interface IConfigurationChangeEvent { - keys: string[]; - sections: string[]; - overrideIdentifiers?: string[]; + affectedKeys: string[]; - hasSectionChanged(section: string): boolean; - hasKeyChanged(key: string): boolean; + affectsConfiugration(configuration: string): boolean; + affectsConfiugration(configuration: string, overrideIdentifier: string): boolean; + affectsConfiugration(configuration: string, resource: URI): boolean; + affectsConfiugration(configuration: string, overrideIdentifier: string, resource: URI): boolean; // Following data is used for telemetry source: ConfigurationTarget; @@ -114,23 +113,6 @@ export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { add return { added, removed, updated }; } -export function toConfigurationUpdateEvent(udpated: string[], source: ConfigurationTarget, sourceConfig: any): IConfigurationChangeEvent { - const overrideIdentifiers = []; - const keys: string[] = []; - for (const key of udpated) { - if (OVERRIDE_PROPERTY_PATTERN.test(key)) { - overrideIdentifiers.push(overrideIdentifierFromKey(key).trim()); - } else { - keys.push(key); - } - } - const sections = arrays.distinct(keys.map(key => key.split('.')[0])); - const hasSectionChanged = (section) => sections.indexOf(section) !== -1; - const hasKeyChanged = (key) => keys.indexOf(key) !== -1; - - return { keys, sections, overrideIdentifiers, source, sourceConfig, hasSectionChanged, hasKeyChanged }; -} - export function toValuesTree(properties: { [qualifiedKey: string]: any }, conflictReporter: (message: string) => void): any { const root = Object.create(null); @@ -227,4 +209,4 @@ export function overrideIdentifierFromKey(key: string): string { export function keyFromOverrideIdentifier(overrideIdentifier: string): string { return `[${overrideIdentifier}]`; -} \ No newline at end of file +} diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index c77ec098128..f86a10ee7d1 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -11,7 +11,7 @@ import * as objects from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys } from 'vs/platform/configuration/common/configuration'; +import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { Workspace } from 'vs/platform/workspace/common/workspace'; export class ConfigurationModel implements IConfiguraionModel { @@ -42,6 +42,15 @@ export class ConfigurationModel implements IConfiguraionModel { } } + public setValueInOverrides(overrideIdentifier: string, key: string, value: any): void { + let override = this._overrides.filter(override => override.identifiers.indexOf(overrideIdentifier) !== -1)[0]; + if (!override) { + override = { identifiers: [overrideIdentifier], contents: {} }; + this._overrides.push(override); + } + addToValueTree(override.contents, key, value, e => { throw new Error(e); }); + } + public removeValue(key: string) { // Remove key from the value tree const index = this._keys.indexOf(key); @@ -272,7 +281,7 @@ export class Configuration { updateValue(key: string, value: any, overrides: IConfigurationOverrides = {}): void { let memoryConfiguration: ConfigurationModel; if (overrides.resource) { - let memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource); + memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource); if (!memoryConfiguration) { memoryConfiguration = new ConfigurationModel(); this._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration); @@ -404,4 +413,100 @@ export class Configuration { private static parseConfigurationModel(model: IConfiguraionModel): ConfigurationModel { return new ConfigurationModel(model.contents, model.keys, model.overrides); } +} + +export class ConfigurationChangeEvent implements IConfigurationChangeEvent { + + private changedConfiguration: ConfigurationModel = new ConfigurationModel(); + private changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); + private resources: URI[] = []; + + private _source: ConfigurationTarget; + private _sourceConfig: any; + + change(event: ConfigurationChangeEvent): ConfigurationChangeEvent + change(keys: string[], resource?: URI): ConfigurationChangeEvent + change(arg1: any, arg2?: any): ConfigurationChangeEvent { + if (arg1 instanceof ConfigurationChangeEvent) { + this.changedConfiguration = this.changedConfiguration.merge(arg1.changedConfiguration); + for (const resource of arg1.resources) { + let changedConfigurationByResource = this.getOrSetChangedConfigurationForResource(resource); + changedConfigurationByResource = changedConfigurationByResource.merge(arg1.changedConfigurationByResource.get(resource)); + this.changedConfigurationByResource.set(resource, changedConfigurationByResource); + } + } + return this.changeWithKeys(arg1, arg2); + } + + telemetryData(source: ConfigurationTarget, sourceConfig: any): ConfigurationChangeEvent { + this._source = source; + this._sourceConfig = sourceConfig; + return this; + } + + get affectedKeys(): string[] { + const keys = [...this.changedConfiguration.keys]; + this.changedConfigurationByResource.forEach(model => keys.push(...model.keys)); + return keys; + } + + get source(): ConfigurationTarget { + return this._source; + } + + get sourceConfig(): any { + return this._sourceConfig; + } + + affectsConfiugration(config: string): boolean + affectsConfiugration(config: string, overrideIdentifier: string): boolean + affectsConfiugration(config: string, resource: URI): boolean + affectsConfiugration(config: string, overrideIdentifier: string, resource: URI): boolean + affectsConfiugration(config: string, arg1?: any, arg2?: any): boolean { + let resource = arg1 instanceof URI ? arg1 : arg2 instanceof URI ? arg2 : void 0; + let overrideIdentifier = resource && arg1 !== resource ? arg1 : void 0; + let model = resource ? this.changedConfigurationByResource.get(resource) : this.changedConfiguration; + if (model) { + + if (overrideIdentifier) { + return model.overrides.some(override => override.identifiers.indexOf(overrideIdentifier) !== -1); + } + + let changedKeysTree = model.contents; + let requestedTree = toValuesTree({ [config]: true }, () => { }); + + let key; + while (typeof requestedTree === 'object' && (key = Object.keys(requestedTree)[0])) { // Only one key should present, since we added only one property + changedKeysTree = changedKeysTree[key]; + if (!changedKeysTree) { + return false; // Requested tree is not found + } + requestedTree = requestedTree[key]; + } + return true; + } + return false; + } + + private changeWithKeys(keys: string[], resource?: URI): ConfigurationChangeEvent { + let changedConfiguration = resource ? this.getOrSetChangedConfigurationForResource(resource) : this.changedConfiguration; + for (const key of keys) { + if (OVERRIDE_PROPERTY_PATTERN.test(key)) { + changedConfiguration.setValueInOverrides(overrideIdentifierFromKey(key), 'key'/* any key */, true); + } else { + changedConfiguration.setValue(key, true); + } + } + return this; + } + + private getOrSetChangedConfigurationForResource(resource: URI): ConfigurationModel { + let changedConfigurationByResource = this.changedConfigurationByResource.get(resource); + if (!changedConfigurationByResource) { + changedConfigurationByResource = new ConfigurationModel(); + this.changedConfigurationByResource.set(resource, changedConfigurationByResource); + this.resources.push(resource); + } + return changedConfigurationByResource; + } } \ No newline at end of file diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 893af01e558..035060db7de 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -8,8 +8,8 @@ import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, toConfigurationUpdateEvent, compare } from 'vs/platform/configuration/common/configuration'; -import { CustomConfigurationModel, DefaultConfigurationModel, ConfigurationModel, Configuration } from 'vs/platform/configuration/common/configurationModels'; +import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare } from 'vs/platform/configuration/common/configuration'; +import { CustomConfigurationModel, DefaultConfigurationModel, ConfigurationModel, Configuration, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import Event, { Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -132,7 +132,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe } private trigger(keys: string[], source: ConfigurationTarget): void { - this._onDidUpdateConfiguration.fire(toConfigurationUpdateEvent(keys, source, this.getTargetConfiguration(source))); + this._onDidUpdateConfiguration.fire(new ConfigurationChangeEvent().change(keys).telemetryData(source, this.getTargetConfiguration(source))); } private getTargetConfiguration(target: ConfigurationTarget): any { diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 18b677b7f61..4cba52bfbcc 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -55,7 +55,7 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem { private registerListeners(): void { this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - if (e.hasSectionChanged('launch')) { + if (e.affectsConfiugration('launch')) { this.updateOptions(); } })); diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index effbdb62019..11538b93dad 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -127,7 +127,7 @@ export class WatermarkContribution implements IWorkbenchContribution { } }); this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - if (e.hasKeyChanged(WORKBENCH_TIPS_ENABLED_KEY)) { + if (e.affectsConfiugration(WORKBENCH_TIPS_ENABLED_KEY)) { const enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); if (enabled !== this.enabled) { this.enabled = enabled; diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 1223ae638a7..b4518c06965 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,8 +5,8 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree } from 'vs/platform/configuration/common/configuration'; -import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; @@ -201,10 +201,9 @@ export class Configuration extends BaseConfiguration { this.merge(); } - updateUserConfiguration(user: ConfigurationModel): string[] { - let changedKeys = []; + updateUserConfiguration(user: ConfigurationModel): ConfigurationChangeEvent { const { added, updated, removed } = compare(this._user, user); - changedKeys = [...added, ...updated, ...removed]; + let changedKeys = [...added, ...updated, ...removed]; if (changedKeys.length) { const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace); @@ -212,15 +211,13 @@ export class Configuration extends BaseConfiguration { this.merge(); changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this.getValue(key))); - return changedKeys; } - return []; + return new ConfigurationChangeEvent().change(changedKeys); } - updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): string[] { - let changedKeys = []; + updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): ConfigurationChangeEvent { const { added, updated, removed } = compare(this._workspaceConfiguration, workspaceConfiguration); - changedKeys = [...added, ...updated, ...removed]; + let changedKeys = [...added, ...updated, ...removed]; if (changedKeys.length) { const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace); @@ -228,18 +225,16 @@ export class Configuration extends BaseConfiguration { this.merge(); changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this.getValue(key))); - return changedKeys; } - return []; + return new ConfigurationChangeEvent().change(changedKeys); } - updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel): string[] { + updateFolderConfiguration(resource: URI, configuration: FolderConfigurationModel): ConfigurationChangeEvent { const currentFolderConfiguration = this.folders.get(resource); if (currentFolderConfiguration) { - let changedKeys = []; const { added, updated, removed } = compare(currentFolderConfiguration, configuration); - changedKeys = [...added, ...updated, ...removed]; + let changedKeys = [...added, ...updated, ...removed]; if (changedKeys.length) { const oldConfiguartion = new Configuration(this._defaults, this._user, this._workspaceConfiguration, this.folders, this._memoryConfiguration, this._memoryConfigurationByResource, this._workspace); @@ -247,29 +242,62 @@ export class Configuration extends BaseConfiguration { this.mergeFolder(resource); changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key, { resource }), this.getValue(key, { resource }))); - return changedKeys; } - return []; + return new ConfigurationChangeEvent().change(changedKeys, resource); } this.folders.set(resource, configuration); this.mergeFolder(resource); - return configuration.keys; + return new ConfigurationChangeEvent().change(configuration.keys, resource); } - deleteFolderConfiguration(folder: URI): string[] { + deleteFolderConfiguration(folder: URI): ConfigurationChangeEvent { if (this._workspace && this._workspace.folders.length > 0 && this._workspace.folders[0].uri.toString() === folder.toString()) { // Do not remove workspace configuration - return []; + return new ConfigurationChangeEvent(); } const keys = this.folders.get(folder).keys; this.folders.delete(folder); this._foldersConsolidatedConfigurations.delete(folder); - return keys; + return new ConfigurationChangeEvent().change(keys, folder); } getFolderConfigurationModel(folder: URI): FolderConfigurationModel { return this.folders.get(folder); } +} + +export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent { + + constructor(private configurationChangeEvent: ConfigurationChangeEvent, private workspace: Workspace) { + } + + get affectedKeys(): string[] { + return this.configurationChangeEvent.affectedKeys; + } + + get source(): ConfigurationTarget { + return this.configurationChangeEvent.source; + } + + get sourceConfig(): any { + return this.configurationChangeEvent.sourceConfig; + } + + affectsConfiugration(config: string, arg1?: any, arg2?: any): boolean { + if (this.configurationChangeEvent.affectsConfiugration(config, arg1, arg2)) { + return true; + } + + let resource = arg1 instanceof URI ? arg1 : arg2 instanceof URI ? arg2 : void 0; + if (resource) { + let workspaceFolder = this.workspace.getFolder(resource); + if (workspaceFolder) { + return this.configurationChangeEvent.affectsConfiugration(config, resource && arg1 !== resource ? arg1 : void 0, resource); + } + } + + return false; + } } \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 6edf38685bb..a57b41a33f6 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -23,9 +23,9 @@ import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CustomConfigurationModel, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; -import { IConfigurationChangeEvent, ConfigurationTarget, toConfigurationUpdateEvent, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; -import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration } from 'vs/workbench/services/configuration/common/configurationModels'; +import { CustomConfigurationModel, ConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; +import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier } from 'vs/platform/configuration/common/configuration'; +import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { ConfigurationService as GlobalConfigurationService, isConfigurationOverrides } from 'vs/platform/configuration/node/configurationService'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -37,7 +37,6 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; -import { distinct, flatten } from 'vs/base/common/arrays'; import { IConfigurationEditingService, ConfigurationTarget as EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; @@ -327,7 +326,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // TODO: compare with old values?? const keys = this._configuration.keys(); - this.triggerConfigurationChange([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE); + this.triggerConfigurationChange(new ConfigurationChangeEvent().change([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder]), ConfigurationTarget.WORKSPACE); }); } @@ -363,7 +362,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat if (e.source === ConfigurationTarget.DEFAULT) { this.workspace.folders.forEach(folder => this._configuration.getFolderConfigurationModel(folder.uri).update()); this._configuration.updateDefaultConfiguration(this.baseConfigurationService.configuration.defaults); - this._onDidUpdateConfiguration.fire(e); + this.triggerConfigurationChange(new ConfigurationChangeEvent().change(e.affectedKeys), e.source); } else { let keys = this._configuration.updateUserConfiguration(this.baseConfigurationService.configuration.user); this.triggerConfigurationChange(keys, e.source); @@ -373,18 +372,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private onWorkspaceConfigurationChanged(): TPromise { if (this.workspace && this.workspace.configuration && this._configuration) { - const changedWorkspaceKeys = this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration); + const workspaceConfigurationChangeEvent = this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration); let configuredFolders = toWorkspaceFolders(this.workspaceConfiguration.workspaceConfigurationModel.folders, URI.file(paths.dirname(this.workspace.configuration.fsPath))); const changes = this.compareFolders(this.workspace.folders, configuredFolders); if (changes.added.length || changes.removed.length || changes.changed.length) { this.workspace.folders = configuredFolders; return this.onFoldersChanged() - .then(changedFolderKeys => { - this.triggerConfigurationChange([...changedFolderKeys, ...changedWorkspaceKeys], ConfigurationTarget.WORKSPACE_FOLDER); + .then(foldersConfigurationChangeEvent => { + this.triggerConfigurationChange(foldersConfigurationChangeEvent.change(workspaceConfigurationChangeEvent), ConfigurationTarget.WORKSPACE_FOLDER); this._onDidChangeWorkspaceFolders.fire(changes); }); } else { - this.triggerConfigurationChange(changedWorkspaceKeys, ConfigurationTarget.WORKSPACE); + this.triggerConfigurationChange(workspaceConfigurationChangeEvent, ConfigurationTarget.WORKSPACE); } } return TPromise.as(null); @@ -395,8 +394,11 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // handle file event for each folder this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event) // Update folder configuration if handled - .then(folderConfiguration => folderConfiguration ? this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration) : [])) - ).then(changedKeys => this.triggerConfigurationChange(flatten(changedKeys), ConfigurationTarget.WORKSPACE_FOLDER)); + .then(folderConfiguration => folderConfiguration ? this._configuration.updateFolderConfiguration(folder.uri, folderConfiguration) : new ConfigurationChangeEvent())) + ).then(changeEvents => { + const consolidateChangeEvent = changeEvents.reduce((consolidated, e) => consolidated.change(e), new ConfigurationChangeEvent()); + this.triggerConfigurationChange(consolidateChangeEvent, ConfigurationTarget.WORKSPACE_FOLDER); + }); } private onSingleFolderFileChanges(event: FileChangesEvent): TPromise { @@ -426,14 +428,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat }); } - private onFoldersChanged(): TPromise { - let changedKeys = []; + private onFoldersChanged(): TPromise { + let changeEvent = new ConfigurationChangeEvent(); // Remove the configurations of deleted folders for (const key of this.cachedFolderConfigs.keys()) { if (!this.workspace.folders.filter(folder => folder.uri.toString() === key.toString())[0]) { this.cachedFolderConfigs.delete(key); - changedKeys.push(...this._configuration.deleteFolderConfiguration(key)); + changeEvent = changeEvent.change(this._configuration.deleteFolderConfiguration(key)); } } @@ -442,12 +444,12 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.loadFolderConfigurations(toInitialize) .then(folderConfigurations => { folderConfigurations.forEach((folderConfiguration, index) => { - changedKeys.push(...this._configuration.updateFolderConfiguration(toInitialize[index].uri, folderConfiguration)); + changeEvent = changeEvent.change(this._configuration.updateFolderConfiguration(toInitialize[index].uri, folderConfiguration)); }); - return changedKeys; + return changeEvent; }); } - return TPromise.as(changedKeys); + return TPromise.as(changeEvent); } private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise { @@ -470,7 +472,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat if (target === ConfigurationTarget.MEMORY) { this._configuration.updateValue(key, value, overrides); - this.triggerConfigurationChange([key], target); + this.triggerConfigurationChange(new ConfigurationChangeEvent().change(overrides.overrideIdentifier ? [keyFromOverrideIdentifier(overrides.overrideIdentifier)] : [key], overrides.resource), target); return TPromise.as(null); } @@ -531,9 +533,10 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } } - private triggerConfigurationChange(keys: string[], target: ConfigurationTarget): void { - if (keys.length) { - this._onDidUpdateConfiguration.fire(toConfigurationUpdateEvent(distinct(keys), target, this.getTargetConfiguration(target))); + private triggerConfigurationChange(configurationEvent: ConfigurationChangeEvent, target: ConfigurationTarget): void { + if (configurationEvent.affectedKeys.length) { + configurationEvent.telemetryData(target, this.getTargetConfiguration(target)); + this._onDidUpdateConfiguration.fire(new WorkspaceConfigurationChangeEvent(configurationEvent, this.workspace)); } } From d902ab8a84dd0978841d2fbcab6db5a1ee49c212 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 17:44:29 +0200 Subject: [PATCH 043/394] Simplify IModelDecorationsChangedEvent --- src/vs/editor/common/model/textModelEvents.ts | 8 ---- .../common/model/textModelWithDecorations.ts | 41 ++++++++----------- .../common/viewModel/viewModelDecorations.ts | 20 +-------- .../common/model/modelDecorations.test.ts | 9 ---- src/vs/monaco.d.ts | 8 ---- 5 files changed, 18 insertions(+), 68 deletions(-) diff --git a/src/vs/editor/common/model/textModelEvents.ts b/src/vs/editor/common/model/textModelEvents.ts index 2acaf260be2..a4c73b4cb13 100644 --- a/src/vs/editor/common/model/textModelEvents.ts +++ b/src/vs/editor/common/model/textModelEvents.ts @@ -88,18 +88,10 @@ export interface IModelContentChangedEvent { * An event describing that model decorations have changed. */ export interface IModelDecorationsChangedEvent { - /** - * Lists of ids for added decorations. - */ - readonly addedDecorations: string[]; /** * Lists of ids for changed decorations. */ readonly changedDecorations: string[]; - /** - * List of ids for removed decorations. - */ - readonly removedDecorations: string[]; } /** diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index d86288a6b2c..fc5da7ad380 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -26,30 +26,27 @@ export const ClassName = { class DecorationsTracker { - public addedDecorations: string[]; - public addedDecorationsLen: number; + public didAddDecorations: boolean; + public didRemoveDecorations: boolean; + public changedDecorations: string[]; public changedDecorationsLen: number; - public removedDecorations: string[]; - public removedDecorationsLen: number; constructor() { - this.addedDecorations = []; - this.addedDecorationsLen = 0; + this.didAddDecorations = false; + this.didRemoveDecorations = false; this.changedDecorations = []; this.changedDecorationsLen = 0; - this.removedDecorations = []; - this.removedDecorationsLen = 0; } // --- Build decoration events - public addNewDecoration(id: string): void { - this.addedDecorations[this.addedDecorationsLen++] = id; + public markDidAddDecorations(): void { + this.didAddDecorations = true; } - public addRemovedDecoration(id: string): void { - this.removedDecorations[this.removedDecorationsLen++] = id; + public markDidRemoveDecorations(): void { + this.didRemoveDecorations = true; } public addMovedDecoration(id: string): void { @@ -494,9 +491,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed if (uniqueChangedDecorations.length > 0) { let e: textModelEvents.IModelDecorationsChangedEvent = { - addedDecorations: [], - changedDecorations: uniqueChangedDecorations, - removedDecorations: [] + changedDecorations: uniqueChangedDecorations }; this.emitModelDecorationsChangedEvent(e); } @@ -532,17 +527,15 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _handleTrackedDecorations(decorationsTracker: DecorationsTracker): void { if ( - decorationsTracker.addedDecorationsLen === 0 + !decorationsTracker.didAddDecorations && decorationsTracker.changedDecorationsLen === 0 - && decorationsTracker.removedDecorationsLen === 0 + && !decorationsTracker.didRemoveDecorations ) { return; } let e: textModelEvents.IModelDecorationsChangedEvent = { - addedDecorations: decorationsTracker.addedDecorations, - changedDecorations: decorationsTracker.changedDecorations, - removedDecorations: decorationsTracker.removedDecorations + changedDecorations: decorationsTracker.changedDecorations }; this.emitModelDecorationsChangedEvent(e); } @@ -592,7 +585,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._multiLineDecorationsMap[decorationId] = decoration; } - decorationsTracker.addNewDecoration(decorationId); + decorationsTracker.markDidAddDecorations(); return decorationId; } @@ -643,7 +636,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._multiLineDecorationsMap[decorationId] = decoration; } - decorationsTracker.addNewDecoration(decorationId); + decorationsTracker.markDidAddDecorations(); } return decorationIds; @@ -705,7 +698,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed delete this._internalDecorations[decoration.internalId]; if (decorationsTracker) { - decorationsTracker.addRemovedDecoration(decorationId); + decorationsTracker.markDidRemoveDecorations(); } } @@ -720,7 +713,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } if (decorationsTracker) { - decorationsTracker.addRemovedDecoration(decorationId); + decorationsTracker.markDidRemoveDecorations(); } removeMarkers[removeMarkersLen++] = decoration.startMarker; diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index f4311681f82..9a5f7b38e76 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -59,25 +59,7 @@ export class ViewModelDecorations implements IDisposable { } public onModelDecorationsChanged(e: IModelDecorationsChangedEvent): void { - let changedDecorations = e.changedDecorations; - for (let i = 0, len = changedDecorations.length; i < len; i++) { - let changedDecoration = changedDecorations[i]; - let myDecoration = this._decorationsCache[changedDecoration]; - if (!myDecoration) { - continue; - } - - myDecoration.range = null; - } - - let removedDecorations = e.removedDecorations; - if (this._decorationsCache !== null && this._decorationsCache !== undefined) { - for (let i = 0, len = removedDecorations.length; i < len; i++) { - let removedDecoration = removedDecorations[i]; - delete this._decorationsCache[removedDecoration]; - } - } - + this._decorationsCache = Object.create(null); this._clearCachedModelDecorationsResolver(); } diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 1b2264090f0..e8fd7a07654 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -207,9 +207,7 @@ suite('Editor Model - Model Decorations', () => { let listenerCalled = 0; thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.addedDecorations.length, 1); assert.equal(e.changedDecorations.length, 0); - assert.equal(e.removedDecorations.length, 0); }); addDecoration(thisModel, 1, 2, 3, 2, 'myType'); assert.equal(listenerCalled, 1, 'listener called'); @@ -220,10 +218,8 @@ suite('Editor Model - Model Decorations', () => { let decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.addedDecorations.length, 0); assert.equal(e.changedDecorations.length, 1); assert.equal(e.changedDecorations[0], decId); - assert.equal(e.removedDecorations.length, 0); }); thisModel.changeDecorations((changeAccessor) => { changeAccessor.changeDecoration(decId, new Range(1, 1, 1, 2)); @@ -236,10 +232,7 @@ suite('Editor Model - Model Decorations', () => { let decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.addedDecorations.length, 0); assert.equal(e.changedDecorations.length, 0); - assert.equal(e.removedDecorations.length, 1); - assert.equal(e.removedDecorations[0], decId); }); thisModel.changeDecorations((changeAccessor) => { changeAccessor.removeDecoration(decId); @@ -253,10 +246,8 @@ suite('Editor Model - Model Decorations', () => { thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.addedDecorations.length, 0); assert.equal(e.changedDecorations.length, 1); assert.equal(e.changedDecorations[0], decId); - assert.equal(e.removedDecorations.length, 0); }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'Hallo ')]); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index c43c2f05b34..902254d86d2 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2482,18 +2482,10 @@ declare module monaco.editor { * An event describing that model decorations have changed. */ export interface IModelDecorationsChangedEvent { - /** - * Lists of ids for added decorations. - */ - readonly addedDecorations: string[]; /** * Lists of ids for changed decorations. */ readonly changedDecorations: string[]; - /** - * List of ids for removed decorations. - */ - readonly removedDecorations: string[]; } /** From 6023aee90c9c09ea9a70aea81ab40827aa39e8d7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 18:08:23 +0200 Subject: [PATCH 044/394] Reduce usages of IModelDecorationsChangedEvent.changedDecorations --- .../browser/referencesWidget.ts | 17 ++++------ .../debug/browser/debugEditorModelManager.ts | 34 +++++++++++++------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index 0d299ca85af..bc0f080836d 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -108,20 +108,15 @@ class DecorationsManager implements IDisposable { } private _onDecorationChanged(event: IModelDecorationsChangedEvent): void { - const changedDecorations = event.changedDecorations, - toRemove: string[] = []; + const toRemove: string[] = []; - for (let i = 0, len = changedDecorations.length; i < len; i++) { - let reference = this._decorations.get(changedDecorations[i]); - if (!reference) { - continue; - } + this._decorations.forEach((reference, decorationId) => { + const newRange = this._editor.getModel().getDecorationRange(decorationId); - const newRange = this._editor.getModel().getDecorationRange(changedDecorations[i]); let ignore = false; if (Range.equalsRange(newRange, reference.range)) { - continue; + return; } else if (Range.spansMultipleLines(newRange)) { ignore = true; @@ -137,11 +132,11 @@ class DecorationsManager implements IDisposable { if (ignore) { this._decorationIgnoreSet.add(reference.id); - toRemove.push(changedDecorations[i]); + toRemove.push(decorationId); } else { reference.range = newRange; } - } + }); this._editor.changeDecorations((accessor) => { for (let i = 0, len = toRemove.length; i < len; i++) { diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 6fd5d7c1c20..10fb1886dfd 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -21,7 +21,7 @@ interface IDebugEditorModelData { toDispose: lifecycle.IDisposable[]; breakpointDecorationIds: string[]; breakpointLines: number[]; - breakpointDecorationsAsMap: Map; + breakpointDecorationsAsMap: Map; currentStackDecorations: string[]; dirty: boolean; topStackFrameRange: Range; @@ -81,11 +81,12 @@ export class DebugEditorModelManager implements IWorkbenchContribution { const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.uri.toString() === modelUrlStr); const currentStackDecorations = model.deltaDecorations([], this.createCallStackDecorations(modelUrlStr)); - const breakPointDecorations = model.deltaDecorations([], this.createBreakpointDecorations(breakpoints)); + const desiredDecorations = this.createBreakpointDecorations(model, breakpoints); + const breakPointDecorations = model.deltaDecorations([], desiredDecorations); const toDispose: lifecycle.IDisposable[] = [model.onDidChangeDecorations((e) => this.onModelDecorationsChanged(modelUrlStr, e))]; - const breakpointDecorationsAsMap = new Map(); - breakPointDecorations.forEach(bpd => breakpointDecorationsAsMap.set(bpd, true)); + const breakpointDecorationsAsMap = new Map(); + breakPointDecorations.forEach((decorationId, index) => breakpointDecorationsAsMap.set(decorationId, desiredDecorations[index].range)); this.modelDataMap.set(modelUrlStr, { model: model, @@ -191,7 +192,17 @@ export class DebugEditorModelManager implements IWorkbenchContribution { // I have no decorations return; } - if (!e.changedDecorations.some(decorationId => modelData.breakpointDecorationsAsMap.has(decorationId))) { + let somethingChanged = false; + modelData.breakpointDecorationsAsMap.forEach((breakpointRange, decorationId) => { + if (somethingChanged) { + return; + } + const newBreakpointRange = modelData.model.getDecorationRange(decorationId); + if (newBreakpointRange && !breakpointRange.equalsRange(newBreakpointRange)) { + somethingChanged = true; + } + }); + if (!somethingChanged) { // nothing to do, my decorations did not change. return; } @@ -254,16 +265,19 @@ export class DebugEditorModelManager implements IWorkbenchContribution { } private updateBreakpoints(modelData: IDebugEditorModelData, newBreakpoints: IBreakpoint[]): void { - modelData.breakpointDecorationIds = modelData.model.deltaDecorations(modelData.breakpointDecorationIds, this.createBreakpointDecorations(newBreakpoints)); + const desiredDecorations = this.createBreakpointDecorations(modelData.model, newBreakpoints); + modelData.breakpointDecorationIds = modelData.model.deltaDecorations(modelData.breakpointDecorationIds, desiredDecorations); modelData.breakpointDecorationsAsMap.clear(); - modelData.breakpointDecorationIds.forEach(id => modelData.breakpointDecorationsAsMap.set(id, true)); + modelData.breakpointDecorationIds.forEach((decorationId, index) => modelData.breakpointDecorationsAsMap.set(decorationId, desiredDecorations[index].range)); modelData.breakpointLines = newBreakpoints.map(bp => bp.lineNumber); } - private createBreakpointDecorations(breakpoints: IBreakpoint[]): IModelDeltaDecoration[] { + private createBreakpointDecorations(model: IModel, breakpoints: IBreakpoint[]): { range: Range; options: IModelDecorationOptions; }[] { return breakpoints.map((breakpoint) => { - const range = breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1) - : new Range(breakpoint.lineNumber, 1, breakpoint.lineNumber, Constants.MAX_SAFE_SMALL_INTEGER); // Decoration has to have a width #20688 + const range = model.validateRange( + breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1) + : new Range(breakpoint.lineNumber, 1, breakpoint.lineNumber, Constants.MAX_SAFE_SMALL_INTEGER) // Decoration has to have a width #20688 + ); return { options: this.getBreakpointDecorationOptions(breakpoint), range From a47159bad1c1d0abdc5aae35b2f6f76524cfc869 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 12 Oct 2017 18:31:42 +0200 Subject: [PATCH 045/394] Eliminate IModelDecorationsChangedEvent.changedDecorations --- src/vs/editor/common/model/textModelEvents.ts | 4 -- .../common/model/textModelWithDecorations.ts | 43 +++++++------------ .../common/viewModel/viewModelDecorations.ts | 3 +- .../editor/common/viewModel/viewModelImpl.ts | 3 +- .../browser/referencesWidget.ts | 5 +-- .../common/model/modelDecorations.test.ts | 8 +--- src/vs/monaco.d.ts | 4 -- .../debug/browser/debugEditorModelManager.ts | 5 +-- 8 files changed, 22 insertions(+), 53 deletions(-) diff --git a/src/vs/editor/common/model/textModelEvents.ts b/src/vs/editor/common/model/textModelEvents.ts index a4c73b4cb13..aaa66c7beab 100644 --- a/src/vs/editor/common/model/textModelEvents.ts +++ b/src/vs/editor/common/model/textModelEvents.ts @@ -88,10 +88,6 @@ export interface IModelContentChangedEvent { * An event describing that model decorations have changed. */ export interface IModelDecorationsChangedEvent { - /** - * Lists of ids for changed decorations. - */ - readonly changedDecorations: string[]; } /** diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index fc5da7ad380..9ed9c9a16e6 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -28,15 +28,12 @@ class DecorationsTracker { public didAddDecorations: boolean; public didRemoveDecorations: boolean; - - public changedDecorations: string[]; - public changedDecorationsLen: number; + public didChangeDecorations: boolean; constructor() { this.didAddDecorations = false; this.didRemoveDecorations = false; - this.changedDecorations = []; - this.changedDecorationsLen = 0; + this.didChangeDecorations = false; } // --- Build decoration events @@ -49,12 +46,8 @@ class DecorationsTracker { this.didRemoveDecorations = true; } - public addMovedDecoration(id: string): void { - this.changedDecorations[this.changedDecorationsLen++] = id; - } - - public addUpdatedDecoration(id: string): void { - this.changedDecorations[this.changedDecorationsLen++] = id; + public markDidChangeDecorations(): void { + this.didChangeDecorations = true; } } @@ -456,7 +449,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } /** - * Handle changed markers (i.e. update decorations ranges and return the changed decorations, unique and sorted by id) + * Handle changed markers (i.e. update decorations ranges) */ private _handleTrackedMarkers(markersTracker: MarkersTracker): void { let changedInternalDecorationIds = markersTracker.getDecorationIds(); @@ -466,8 +459,8 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed changedInternalDecorationIds.sort(); - let uniqueChangedDecorations: string[] = [], uniqueChangedDecorationsLen = 0; let previousInternalDecorationId: number = 0; + let somethingChanged = false; for (let i = 0, len = changedInternalDecorationIds.length; i < len; i++) { let internalDecorationId = changedInternalDecorationIds[i]; if (internalDecorationId === previousInternalDecorationId) { @@ -485,15 +478,11 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed let endMarker = decoration.endMarker.position; let range = TextModelWithDecorations._createRangeFromMarkers(startMarker, endMarker); decoration.setRange(this._multiLineDecorationsMap, range); - - uniqueChangedDecorations[uniqueChangedDecorationsLen++] = decoration.id; + somethingChanged = true; } - if (uniqueChangedDecorations.length > 0) { - let e: textModelEvents.IModelDecorationsChangedEvent = { - changedDecorations: uniqueChangedDecorations - }; - this.emitModelDecorationsChangedEvent(e); + if (somethingChanged) { + this.emitModelDecorationsChangedEvent(); } } @@ -528,20 +517,18 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _handleTrackedDecorations(decorationsTracker: DecorationsTracker): void { if ( !decorationsTracker.didAddDecorations - && decorationsTracker.changedDecorationsLen === 0 + && !decorationsTracker.didChangeDecorations && !decorationsTracker.didRemoveDecorations ) { return; } - let e: textModelEvents.IModelDecorationsChangedEvent = { - changedDecorations: decorationsTracker.changedDecorations - }; - this.emitModelDecorationsChangedEvent(e); + this.emitModelDecorationsChangedEvent(); } - private emitModelDecorationsChangedEvent(e: textModelEvents.IModelDecorationsChangedEvent): void { + private emitModelDecorationsChangedEvent(): void { if (!this._isDisposing) { + let e: textModelEvents.IModelDecorationsChangedEvent = {}; this._eventEmitter.emit(textModelEvents.TextModelEventType.ModelDecorationsChanged, e); } } @@ -666,7 +653,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed decoration.setRange(this._multiLineDecorationsMap, newRange); - decorationsTracker.addMovedDecoration(decorationId); + decorationsTracker.markDidChangeDecorations(); } private _changeDecorationOptionsImpl(decorationsTracker: DecorationsTracker, decorationId: string, options: ModelDecorationOptions): void { @@ -682,7 +669,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed decoration.setOptions(options); - decorationsTracker.addUpdatedDecoration(decorationId); + decorationsTracker.markDidChangeDecorations(); } private _removeDecorationImpl(decorationsTracker: DecorationsTracker, decorationId: string): void { diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index 9a5f7b38e76..59205a10171 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -9,7 +9,6 @@ import { Range } from 'vs/editor/common/core/range'; import { Position } from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { InlineDecoration, ViewModelDecoration, ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel'; -import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents'; export interface IDecorationsViewportData { /** @@ -58,7 +57,7 @@ export class ViewModelDecorations implements IDisposable { this._clearCachedModelDecorationsResolver(); } - public onModelDecorationsChanged(e: IModelDecorationsChangedEvent): void { + public onModelDecorationsChanged(): void { this._decorationsCache = Object.create(null); this._clearCachedModelDecorationsResolver(); } diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index f1a7fcbf961..68cdaf1ccbc 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -282,8 +282,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel break; } case textModelEvents.TextModelEventType.ModelDecorationsChanged: { - const e = data; - this.decorations.onModelDecorationsChanged(e); + this.decorations.onModelDecorationsChanged(); eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent()); break; } diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index bc0f080836d..42aaeb2fce0 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -38,7 +38,6 @@ import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/r import { registerColor, activeContrastBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant, ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; import { attachListStyler, attachBadgeStyler } from 'vs/platform/theme/common/styler'; -import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; @@ -81,7 +80,7 @@ class DecorationsManager implements IDisposable { } private _addDecorations(reference: FileReferences): void { - this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged(event))); + this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged())); this._editor.changeDecorations(accessor => { @@ -107,7 +106,7 @@ class DecorationsManager implements IDisposable { }); } - private _onDecorationChanged(event: IModelDecorationsChangedEvent): void { + private _onDecorationChanged(): void { const toRemove: string[] = []; this._decorations.forEach((reference, decorationId) => { diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index e8fd7a07654..84defed4ada 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -207,7 +207,6 @@ suite('Editor Model - Model Decorations', () => { let listenerCalled = 0; thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.changedDecorations.length, 0); }); addDecoration(thisModel, 1, 2, 3, 2, 'myType'); assert.equal(listenerCalled, 1, 'listener called'); @@ -218,8 +217,6 @@ suite('Editor Model - Model Decorations', () => { let decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.changedDecorations.length, 1); - assert.equal(e.changedDecorations[0], decId); }); thisModel.changeDecorations((changeAccessor) => { changeAccessor.changeDecoration(decId, new Range(1, 1, 1, 2)); @@ -232,7 +229,6 @@ suite('Editor Model - Model Decorations', () => { let decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.changedDecorations.length, 0); }); thisModel.changeDecorations((changeAccessor) => { changeAccessor.removeDecoration(decId); @@ -242,12 +238,10 @@ suite('Editor Model - Model Decorations', () => { test('decorations emit event when inserting one line text before it', () => { let listenerCalled = 0; - let decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); + addDecoration(thisModel, 1, 2, 3, 2, 'myType'); thisModel.onDidChangeDecorations((e) => { listenerCalled++; - assert.equal(e.changedDecorations.length, 1); - assert.equal(e.changedDecorations[0], decId); }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'Hallo ')]); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 902254d86d2..96c24eb1b18 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2482,10 +2482,6 @@ declare module monaco.editor { * An event describing that model decorations have changed. */ export interface IModelDecorationsChangedEvent { - /** - * Lists of ids for changed decorations. - */ - readonly changedDecorations: string[]; } /** diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 10fb1886dfd..55f5e51c46f 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -13,7 +13,6 @@ import { IModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecoration import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IDebugService, IBreakpoint, IRawBreakpoint, State } from 'vs/workbench/parts/debug/common/debug'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents'; import { MarkdownString } from 'vs/base/common/htmlContent'; interface IDebugEditorModelData { @@ -84,7 +83,7 @@ export class DebugEditorModelManager implements IWorkbenchContribution { const desiredDecorations = this.createBreakpointDecorations(model, breakpoints); const breakPointDecorations = model.deltaDecorations([], desiredDecorations); - const toDispose: lifecycle.IDisposable[] = [model.onDidChangeDecorations((e) => this.onModelDecorationsChanged(modelUrlStr, e))]; + const toDispose: lifecycle.IDisposable[] = [model.onDidChangeDecorations((e) => this.onModelDecorationsChanged(modelUrlStr))]; const breakpointDecorationsAsMap = new Map(); breakPointDecorations.forEach((decorationId, index) => breakpointDecorationsAsMap.set(decorationId, desiredDecorations[index].range)); @@ -186,7 +185,7 @@ export class DebugEditorModelManager implements IWorkbenchContribution { } // breakpoints management. Represent data coming from the debug service and also send data back. - private onModelDecorationsChanged(modelUrlStr: string, e: IModelDecorationsChangedEvent): void { + private onModelDecorationsChanged(modelUrlStr: string): void { const modelData = this.modelDataMap.get(modelUrlStr); if (modelData.breakpointDecorationsAsMap.size === 0) { // I have no decorations From 1a98d686af068f8a2d754f754db562e34cc96c23 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 12 Oct 2017 15:20:44 -0700 Subject: [PATCH 046/394] For line comment, always use start line of language for line comments that trigger block comments **Bug** When a line comment command falls back to a block comment, we currently get the language mode from the cursor. In jsx, when you are inside of a javascript expression, this results in the wrong language mode being selected **Fix** Make sure we always grab the language mode from the start of the line. This is consistent with what we do for regular line comments Fixes #36173 --- .../contrib/comment/common/lineCommentCommand.ts | 2 +- .../test/common/lineCommentCommand.test.ts | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts index 8f0abccfd32..e1d5bec1202 100644 --- a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts @@ -270,7 +270,7 @@ export class LineCommentCommand implements editorCommon.ICommand { */ private _executeBlockComment(model: editorCommon.ITokenizedModel, builder: editorCommon.IEditOperationBuilder, s: Selection): void { model.tokenizeIfCheap(s.startLineNumber); - let languageId = model.getLanguageIdAtPosition(s.startLineNumber, s.startColumn); + let languageId = model.getLanguageIdAtPosition(s.startLineNumber, 1); let config = LanguageConfigurationRegistry.getComments(languageId); if (!config || !config.blockCommentStartToken || !config.blockCommentEndToken) { // Mode does not support block comments diff --git a/src/vs/editor/contrib/comment/test/common/lineCommentCommand.test.ts b/src/vs/editor/contrib/comment/test/common/lineCommentCommand.test.ts index 57c946f76f9..743652c37a7 100644 --- a/src/vs/editor/contrib/comment/test/common/lineCommentCommand.test.ts +++ b/src/vs/editor/contrib/comment/test/common/lineCommentCommand.test.ts @@ -1002,4 +1002,20 @@ suite('Editor Contrib - Line Comment in mixed modes', () => { ); }); + test('issue #36173: Commenting code in JSX tag body', () => { + testLineCommentCommand( + [ + '
', + ' {123}', + '
', + ], + new Selection(2, 4, 2, 4), + [ + '
', + ' {/* {123} */}', + '
', + ], + new Selection(2, 8, 2, 8), + ); + }); }); From b5f41b98022df299ec8c99143be38bb8f7dae063 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Thu, 12 Oct 2017 15:59:00 -0700 Subject: [PATCH 047/394] Let workspaceContains trigger use rg --quiet (fixes #35236) --- src/vs/platform/search/common/search.ts | 6 ++ src/vs/workbench/node/extensionHostMain.ts | 4 +- .../services/search/node/fileSearch.ts | 10 ++- .../services/search/node/ripgrepFileSearch.ts | 4 + .../workbench/services/search/node/search.ts | 1 + .../services/search/node/searchService.ts | 1 + .../services/search/test/node/search.test.ts | 82 +++++++++++++++++++ 7 files changed, 104 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/search/common/search.ts b/src/vs/platform/search/common/search.ts index bb2a8df08e4..bdd1918a876 100644 --- a/src/vs/platform/search/common/search.ts +++ b/src/vs/platform/search/common/search.ts @@ -44,6 +44,12 @@ export interface ICommonQueryOptions { filePattern?: string; // file search only fileEncoding?: string; maxResults?: number; + /** + * If true no results will be returned. Instead `limitHit` will indicate if at least one result exists or not. + * + * Currently does not work with queries including a 'siblings clause'. + */ + exists?: boolean; sortByScore?: boolean; cacheKey?: string; useRipgrep?: boolean; diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index cda0a718027..a28fb2b6a9b 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -232,13 +232,13 @@ export class ExtensionHostMain { const query: ISearchQuery = { folderQueries, type: QueryType.File, - maxResults: 1, + exists: true, includePattern: includes, useRipgrep }; let result = await this._diskSearch.search(query); - if (result.results.length > 0) { + if (result.limitHit) { // a file was found matching one of the glob patterns return ( this._extensionService.activateById(extensionId, true) diff --git a/src/vs/workbench/services/search/node/fileSearch.ts b/src/vs/workbench/services/search/node/fileSearch.ts index ff457516718..02e7c5e570c 100644 --- a/src/vs/workbench/services/search/node/fileSearch.ts +++ b/src/vs/workbench/services/search/node/fileSearch.ts @@ -53,6 +53,7 @@ export class FileWalker { private normalizedFilePatternLowercase: string; private includePattern: glob.ParsedExpression; private maxResults: number; + private exists: boolean; private maxFilesize: number; private isLimitHit: boolean; private resultCount: number; @@ -77,6 +78,7 @@ export class FileWalker { this.filePattern = config.filePattern; this.includePattern = config.includePattern && glob.parse(config.includePattern); this.maxResults = config.maxResults || null; + this.exists = config.exists; this.maxFilesize = config.maxFilesize || null; this.walkedPaths = Object.create(null); this.resultCount = 0; @@ -234,6 +236,7 @@ export class FileWalker { return; } if (this.isLimitHit) { + done(); return; } @@ -392,9 +395,12 @@ export class FileWalker { cmd.on('close', (code: number) => { // ripgrep returns code=1 when no results are found - if (code !== 0 && ((isRipgrep && stderr.length) || !isRipgrep)) { + if (code !== 0 && (!isRipgrep || code !== 1)) { done(new Error(`command failed with error code ${code}: ${this.decodeData(stderr, encoding)}`)); } else { + if (isRipgrep && this.exists && code === 0) { + this.isLimitHit = true; + } done(null, '', true); } }); @@ -657,7 +663,7 @@ export class FileWalker { if (this.isFilePatternMatch(candidate.relativePath) && (!this.includePattern || this.includePattern(candidate.relativePath, candidate.basename))) { this.resultCount++; - if (this.maxResults && this.resultCount > this.maxResults) { + if (this.exists || (this.maxResults && this.resultCount > this.maxResults)) { this.isLimitHit = true; } diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 7b4b508b4e4..caba0ebd233 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -44,6 +44,10 @@ function getRgArgs(config: IRawSearch, folderQuery: IFolderSearch, includePatter // Follow symlinks args.push('--follow'); + if (config.exists) { + args.push('--quiet'); + } + // Folder to search args.push('--'); diff --git a/src/vs/workbench/services/search/node/search.ts b/src/vs/workbench/services/search/node/search.ts index 424b3b4f0f7..38c3be3415c 100644 --- a/src/vs/workbench/services/search/node/search.ts +++ b/src/vs/workbench/services/search/node/search.ts @@ -25,6 +25,7 @@ export interface IRawSearch { includePattern?: IExpression; contentPattern?: IPatternInfo; maxResults?: number; + exists?: boolean; sortByScore?: boolean; cacheKey?: string; maxFilesize?: number; diff --git a/src/vs/workbench/services/search/node/searchService.ts b/src/vs/workbench/services/search/node/searchService.ts index b7adc8e63a9..85c20bd1f10 100644 --- a/src/vs/workbench/services/search/node/searchService.ts +++ b/src/vs/workbench/services/search/node/searchService.ts @@ -266,6 +266,7 @@ export class DiskSearch implements ISearchResultProvider { excludePattern: query.excludePattern, includePattern: query.includePattern, maxResults: query.maxResults, + exists: query.exists, sortByScore: query.sortByScore, cacheKey: query.cacheKey, useRipgrep: query.useRipgrep, diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index abecd589774..f7fbebd6835 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -84,6 +84,88 @@ suite('FileSearchEngine', () => { }); }); + test('Files: exists', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + includePattern: { '**/file.txt': true }, + exists: true + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error, complete) => { + assert.ok(!error); + assert.equal(count, 0); + assert.ok(complete.limitHit); + done(); + }); + }); + + test('Files: not exists', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + includePattern: { '**/nofile.txt': true }, + exists: true + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error, complete) => { + assert.ok(!error); + assert.equal(count, 0); + assert.ok(!complete.limitHit); + done(); + }); + }); + + test('Files: exists without Ripgrep', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + includePattern: { '**/file.txt': true }, + exists: true, + useRipgrep: false + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error, complete) => { + assert.ok(!error); + assert.equal(count, 0); + assert.ok(complete.limitHit); + done(); + }); + }); + + test('Files: not exists without Ripgrep', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + includePattern: { '**/nofile.txt': true }, + exists: true, + useRipgrep: false + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error, complete) => { + assert.ok(!error); + assert.equal(count, 0); + assert.ok(!complete.limitHit); + done(); + }); + }); + test('Files: examples/com*', function (done: () => void) { let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, From 9ca019f9e8c7a6a35dcff32fa9bfb6439c5c1699 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 12 Oct 2017 15:38:21 -0700 Subject: [PATCH 048/394] Update js/ts grammars --- .../syntaxes/JavaScript.tmLanguage.json | 22 +++++++++---------- .../syntaxes/JavaScriptReact.tmLanguage.json | 22 +++++++++---------- .../syntaxes/TypeScript.tmLanguage.json | 22 +++++++++---------- .../syntaxes/TypeScriptReact.tmLanguage.json | 22 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index 466cb34a314..2c53d302110 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/5955a5aed3d8d2862c614f2137d22f2334d490e9", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", "name": "JavaScript (with React support)", "scopeName": "source.js", "fileTypes": [ @@ -278,7 +278,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js entity.name.function.js" @@ -512,7 +512,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js" @@ -739,7 +739,7 @@ }, { "name": "meta.definition.property.js entity.name.function.js", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" }, { "name": "meta.definition.property.js variable.object.property.js", @@ -1002,7 +1002,7 @@ }, { "name": "meta.arrow.js", - "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1950,7 +1950,7 @@ }, { "name": "meta.object.member.js", - "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js" @@ -2043,13 +2043,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2496,7 +2496,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.js" @@ -2576,7 +2576,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js" diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json index 29aa8b6a2a2..c516b79e5c9 100644 --- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/5955a5aed3d8d2862c614f2137d22f2334d490e9", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", "name": "JavaScript (with React support)", "scopeName": "source.js.jsx", "fileTypes": [ @@ -278,7 +278,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js.jsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js.jsx entity.name.function.js.jsx" @@ -512,7 +512,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -739,7 +739,7 @@ }, { "name": "meta.definition.property.js.jsx entity.name.function.js.jsx", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" }, { "name": "meta.definition.property.js.jsx variable.object.property.js.jsx", @@ -1002,7 +1002,7 @@ }, { "name": "meta.arrow.js.jsx", - "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1950,7 +1950,7 @@ }, { "name": "meta.object.member.js.jsx", - "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js.jsx" @@ -2043,13 +2043,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js.jsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2496,7 +2496,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.js.jsx" @@ -2576,7 +2576,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js.jsx" diff --git a/extensions/typescript/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript/syntaxes/TypeScript.tmLanguage.json index ba5c664ccf4..fc4a8971471 100644 --- a/extensions/typescript/syntaxes/TypeScript.tmLanguage.json +++ b/extensions/typescript/syntaxes/TypeScript.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/5955a5aed3d8d2862c614f2137d22f2334d490e9", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", "name": "TypeScript", "scopeName": "source.ts", "fileTypes": [ @@ -272,7 +272,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.ts", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.ts entity.name.function.ts" @@ -506,7 +506,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "captures": { "1": { "name": "storage.modifier.ts" @@ -733,7 +733,7 @@ }, { "name": "meta.definition.property.ts entity.name.function.ts", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" }, { "name": "meta.definition.property.ts variable.object.property.ts", @@ -996,7 +996,7 @@ }, { "name": "meta.arrow.ts", - "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1944,7 +1944,7 @@ }, { "name": "meta.object.member.ts", - "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.ts" @@ -2037,13 +2037,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.ts", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2527,7 +2527,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -2607,7 +2607,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.ts" diff --git a/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json b/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json index 8266fec39bb..aab4d2f34e3 100644 --- a/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json +++ b/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/5955a5aed3d8d2862c614f2137d22f2334d490e9", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", "name": "TypeScriptReact", "scopeName": "source.tsx", "fileTypes": [ @@ -275,7 +275,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.tsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx entity.name.function.tsx" @@ -509,7 +509,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -736,7 +736,7 @@ }, { "name": "meta.definition.property.tsx entity.name.function.tsx", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" }, { "name": "meta.definition.property.tsx variable.object.property.tsx", @@ -999,7 +999,7 @@ }, { "name": "meta.arrow.tsx", - "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1947,7 +1947,7 @@ }, { "name": "meta.object.member.tsx", - "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.tsx" @@ -2040,13 +2040,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.tsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2493,7 +2493,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -2573,7 +2573,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*[_$[:alpha:]\\{\\(\\[]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(\\[]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\((\\s*[_$[:alpha:]\\{\\(]([^()]|\\((\\s*[_$[:alpha:]\\{\\(]\\{\\(][^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.tsx" From ae20b2073a90a80422f3fc873ff212ce3a64da4b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 12 Oct 2017 15:47:26 -0700 Subject: [PATCH 049/394] Make sure we rewrite contentName for jsx grammar --- .../syntaxes/JavaScript.tmLanguage.json | 8 +- .../syntaxes/JavaScriptReact.tmLanguage.json | 8 +- .../test/colorize-results/test_jsx.json | 78 +++++++++---------- .../typescript/build/update-grammars.js | 3 + 4 files changed, 50 insertions(+), 47 deletions(-) diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index 2c53d302110..85546d41404 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -3225,7 +3225,7 @@ "include": "#expression" } ], - "contentName": "meta.embedded.line.tsx" + "contentName": "meta.embedded.line.js" }, "regex": { "patterns": [ @@ -3482,7 +3482,7 @@ } }, "end": "(?=^)", - "contentName": "comment.line.double-slash.tsx" + "contentName": "comment.line.double-slash.js" } ] }, @@ -4020,7 +4020,7 @@ "name": "punctuation.definition.tag.end.js" } }, - "contentName": "meta.jsx.children.tsx", + "contentName": "meta.jsx.children.js", "patterns": [ { "include": "#jsx-children" @@ -4124,7 +4124,7 @@ } }, "end": "(?=", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx punctuation.definition.tag.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx punctuation.definition.tag.end.js.jsx", "r": { "dark_plus": "punctuation.definition.tag: #808080", "light_plus": "punctuation.definition.tag: #800000", @@ -1651,7 +1651,7 @@ }, { "c": "Hello ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1662,7 +1662,7 @@ }, { "c": "{", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.embedded.expression.js.jsx punctuation.section.embedded.begin.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.begin.js.jsx", "r": { "dark_plus": "punctuation.section.embedded: #569CD6", "light_plus": "punctuation.section.embedded: #0000FF", @@ -1673,7 +1673,7 @@ }, { "c": "message", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.embedded.expression.js.jsx variable.other.readwrite.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.embedded.expression.js.jsx variable.other.readwrite.js.jsx", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -1684,7 +1684,7 @@ }, { "c": "}", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.embedded.expression.js.jsx punctuation.section.embedded.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.end.js.jsx", "r": { "dark_plus": "punctuation.section.embedded: #569CD6", "light_plus": "punctuation.section.embedded: #0000FF", @@ -1695,7 +1695,7 @@ }, { "c": "!", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1706,7 +1706,7 @@ }, { "c": "", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.without-attributes.js.jsx punctuation.definition.tag.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.without-attributes.js.jsx punctuation.definition.tag.end.js.jsx", "r": { "dark_plus": "punctuation.definition.tag: #808080", "light_plus": "punctuation.definition.tag: #800000", @@ -1739,7 +1739,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1750,7 +1750,7 @@ }, { "c": "<", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx punctuation.definition.tag.begin.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx punctuation.definition.tag.begin.js.jsx", "r": { "dark_plus": "punctuation.definition.tag: #808080", "light_plus": "punctuation.definition.tag: #800000", @@ -1761,7 +1761,7 @@ }, { "c": "a", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx entity.name.tag.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx entity.name.tag.js.jsx", "r": { "dark_plus": "entity.name.tag: #569CD6", "light_plus": "entity.name.tag: #800000", @@ -1772,7 +1772,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1783,7 +1783,7 @@ }, { "c": "href", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", "r": { "dark_plus": "entity.other.attribute-name: #9CDCFE", "light_plus": "entity.other.attribute-name: #FF0000", @@ -1794,7 +1794,7 @@ }, { "c": "=", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1805,7 +1805,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1816,7 +1816,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1827,7 +1827,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1838,7 +1838,7 @@ }, { "c": "onClick", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", "r": { "dark_plus": "entity.other.attribute-name: #9CDCFE", "light_plus": "entity.other.attribute-name: #FF0000", @@ -1849,7 +1849,7 @@ }, { "c": "=", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1860,7 +1860,7 @@ }, { "c": "{", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.begin.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.begin.js.jsx", "r": { "dark_plus": "punctuation.section.embedded: #569CD6", "light_plus": "punctuation.section.embedded: #0000FF", @@ -1871,7 +1871,7 @@ }, { "c": "this", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx meta.embedded.expression.js.jsx variable.language.this.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx variable.language.this.js.jsx", "r": { "dark_plus": "variable.language: #569CD6", "light_plus": "variable.language: #0000FF", @@ -1882,7 +1882,7 @@ }, { "c": ".", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.accessor.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.accessor.js.jsx", "r": { "dark_plus": "meta.embedded: #D4D4D4", "light_plus": "meta.embedded: #000000", @@ -1893,7 +1893,7 @@ }, { "c": "toggle", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx meta.embedded.expression.js.jsx variable.other.property.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx variable.other.property.js.jsx", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -1904,7 +1904,7 @@ }, { "c": "}", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.end.js.jsx", "r": { "dark_plus": "punctuation.section.embedded: #569CD6", "light_plus": "punctuation.section.embedded: #0000FF", @@ -1915,7 +1915,7 @@ }, { "c": ">", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx punctuation.definition.tag.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx punctuation.definition.tag.end.js.jsx", "r": { "dark_plus": "punctuation.definition.tag: #808080", "light_plus": "punctuation.definition.tag: #800000", @@ -1926,7 +1926,7 @@ }, { "c": "Toggle", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx meta.jsx.children.tsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.jsx.children.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1937,7 +1937,7 @@ }, { "c": "", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx meta.tag.js.jsx punctuation.definition.tag.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx punctuation.definition.tag.end.js.jsx", "r": { "dark_plus": "punctuation.definition.tag: #808080", "light_plus": "punctuation.definition.tag: #800000", @@ -1970,7 +1970,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.tsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", diff --git a/extensions/typescript/build/update-grammars.js b/extensions/typescript/build/update-grammars.js index e82549b4eef..bae3329d9b1 100644 --- a/extensions/typescript/build/update-grammars.js +++ b/extensions/typescript/build/update-grammars.js @@ -15,6 +15,9 @@ function adaptToJavaScript(grammar, replacementScope) { if (typeof rule.name === 'string') { rule.name = rule.name.replace(/\.tsx/g, replacementScope); } + if (typeof rule.contentName === 'string') { + rule.contentName = rule.contentName.replace(/\.tsx/g, replacementScope); + } for (var property in rule) { var value = rule[property]; if (typeof value === 'object') { From d1047a65ed5db2ffc26c01ebc6f4ed91a0b5eb26 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 12 Oct 2017 19:24:57 -0700 Subject: [PATCH 050/394] Pick up first TS 2.6 insiders --- extensions/npm-shrinkwrap.json | 6 +++--- extensions/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/npm-shrinkwrap.json b/extensions/npm-shrinkwrap.json index 4a636d0dcfe..3a586ecad98 100644 --- a/extensions/npm-shrinkwrap.json +++ b/extensions/npm-shrinkwrap.json @@ -3,9 +3,9 @@ "version": "0.0.1", "dependencies": { "typescript": { - "version": "2.5.3", - "from": "typescript@2.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.3.tgz" + "version": "2.6.0-insiders.20171013", + "from": "typescript@2.6.0-insiders.20171013", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.0-insiders.20171013.tgz" } } } diff --git a/extensions/package.json b/extensions/package.json index 798babbda78..ce960b5b23b 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "2.5.3" + "typescript": "2.6.0-insiders.20171013" }, "scripts": { "postinstall": "node ./postinstall" From c697689589e7f3b81551ba78b17d28f5ba88c6a0 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 09:30:33 +0200 Subject: [PATCH 051/394] [folding] add java folding regions --- extensions/java/language-configuration.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/extensions/java/language-configuration.json b/extensions/java/language-configuration.json index 5ae0cec3192..cc45a8a0139 100644 --- a/extensions/java/language-configuration.json +++ b/extensions/java/language-configuration.json @@ -23,5 +23,11 @@ ["\"", "\""], ["'", "'"], ["<", ">"] - ] + ], + "folding": { + "markers": { + "start": "^\\s*//\\s*(#?region\\b)|()" + } + } } From 479958b25dc41e66470ad43c35438d6261d97e5d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 Oct 2017 09:45:48 +0200 Subject: [PATCH 052/394] IntervalTree.insert gets passed in the node to be inserted --- src/vs/editor/common/model/intervalTree.ts | 55 ++++++++++--------- .../test/common/model/intervalTree.test.ts | 10 ++-- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 4960d1274a6..7160e8b546c 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -18,13 +18,6 @@ export class Interval { this.start = start; this.end = end; } - - public compareToRelative(otherStart: number, otherEnd: number): number { - if (this.start === otherStart) { - return this.end - otherEnd; - } - return this.start - otherStart; - } } export const enum NodeColor { @@ -44,7 +37,7 @@ export class IntervalNode { public delta: number; public maxEnd: number; - public resultInterval: Interval; + public absoluteInterval: Interval; constructor(start: number, end: number) { this.parent = null; @@ -57,7 +50,7 @@ export class IntervalNode { this.delta = start; this.maxEnd = end; - this.resultInterval = new Interval(0, 0); + this.absoluteInterval = new Interval(0, 0); } public detach(): void { @@ -90,8 +83,8 @@ export class IntervalTree { return result; } - public insert(interval: Interval): IntervalNode { - return rbTreeInsert(this, interval); + public insert(node: IntervalNode): void { + rbTreeInsert(this, node); } public delete(node: IntervalNode) { @@ -185,8 +178,8 @@ function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStar const nodeEnd = delta + node.end; if (nodeEnd >= intervalStart) { // There is overlap - node.resultInterval.start = nodeStart; - node.resultInterval.end = nodeEnd; + node.absoluteInterval.start = nodeStart; + node.absoluteInterval.end = nodeEnd; result.push(node); } @@ -197,9 +190,8 @@ function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStar //#endregion //#region Insertion -function rbTreeInsert(T: IntervalTree, interval: Interval): IntervalNode { +function rbTreeInsert(T: IntervalTree, newNode: IntervalNode): IntervalNode { if (T.root === SENTINEL) { - const newNode = new IntervalNode(interval.start, interval.end); newNode.parent = SENTINEL; newNode.left = SENTINEL; newNode.right = SENTINEL; @@ -208,7 +200,7 @@ function rbTreeInsert(T: IntervalTree, interval: Interval): IntervalNode { return T.root; } - const newNode = treeInsert(T, interval); + treeInsert(T, newNode); recomputeMaxEndWalkToRoot(newNode.parent); @@ -257,17 +249,20 @@ function rbTreeInsert(T: IntervalTree, interval: Interval): IntervalNode { return newNode; } -function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { +function treeInsert(T: IntervalTree, z: IntervalNode): void { let delta: number = 0; - let z = SENTINEL; let x = T.root; + const zAbsoluteStart = z.start; + const zAbsoluteEnd = z.end; while (true) { - let cmp = interval.compareToRelative(x.start + delta, x.end + delta); + const cmp = intervalCompare(zAbsoluteStart, zAbsoluteEnd, x.start + delta, x.end + delta); if (cmp < 0) { // this node should be inserted to the left // => it is not affected by the node's delta if (x.left === SENTINEL) { - z = new IntervalNode(interval.start - delta, interval.end - delta); + z.start -= delta; + z.end -= delta; + z.maxEnd -= delta; x.left = z; break; } else { @@ -277,7 +272,9 @@ function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { // this node should be inserted to the right // => it is not affected by the node's delta if (x.right === SENTINEL) { - z = new IntervalNode(interval.start - delta - x.delta, interval.end - delta - x.delta); + z.start -= (delta + x.delta); + z.end -= (delta + x.delta); + z.maxEnd -= (delta + x.delta); x.right = z; break; } else { @@ -291,7 +288,6 @@ function treeInsert(T: IntervalTree, interval: Interval): IntervalNode { z.left = SENTINEL; z.right = SENTINEL; z.color = NodeColor.Red; - return z; } //#endregion @@ -581,6 +577,15 @@ function recomputeMaxEndWalkToRoot(node: IntervalNode): void { //#endregion +//#region utils +function intervalCompare(aStart: number, aEnd: number, bStart: number, bEnd: number): number { + if (aStart === bStart) { + return aEnd - bEnd; + } + return aStart - bStart; +} +//#endregion + //#region Assertion function depth(n: IntervalNode): number { @@ -607,13 +612,11 @@ function assertValidNode(n: IntervalNode, delta): void { let expectedMaxEnd = n.end; if (l !== SENTINEL) { - const lValue = new Interval(l.start + delta, l.end + delta); - assert(lValue.compareToRelative(n.start + delta, n.end + delta) <= 0); + assert(intervalCompare(l.start + delta, l.end + delta, n.start + delta, n.end + delta) <= 0); expectedMaxEnd = Math.max(expectedMaxEnd, l.maxEnd); } if (r !== SENTINEL) { - const nValue = new Interval(n.start + delta, n.end + delta); - assert(nValue.compareToRelative(r.start + delta + n.delta, r.end + delta + n.delta) <= 0); + assert(intervalCompare(n.start + delta, n.end + delta, r.start + delta + n.delta, r.end + delta + n.delta) <= 0); expectedMaxEnd = Math.max(expectedMaxEnd, r.maxEnd + n.delta); } assert(n.maxEnd === expectedMaxEnd); diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index ec6d1dcfe1a..d8518b27a68 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -71,7 +71,8 @@ suite('IntervalTree', () => { console.log(`insert: {${JSON.stringify(new Interval(op.begin, op.end))}}`); } let nodeId = (++this._lastNodeId); - this._treeNodes[nodeId] = this._tree.insert(new Interval(op.begin, op.end)); + this._treeNodes[nodeId] = new IntervalNode(op.begin, op.end); + this._tree.insert(this._treeNodes[nodeId]); this._oracleNodes[nodeId] = this._oracle.insert(new Interval(op.begin, op.end)); } else if (op.type === 'delete') { if (PRINT_TREE) { @@ -84,7 +85,7 @@ suite('IntervalTree', () => { this._oracleNodes[op.id] = null; } else { let actualNodes = this._tree.intervalSearch(new Interval(op.begin, op.end)); - let actual = actualNodes.map(n => n.resultInterval); + let actual = actualNodes.map(n => n.absoluteInterval); let expected = this._oracle.search(new Interval(op.begin, op.end)); assert.deepEqual(actual, expected); return; @@ -417,7 +418,8 @@ suite('IntervalTree', () => { [19, 20] ]; data.forEach((int) => { - r.insert(new Interval(int[0], int[1])); + let node = new IntervalNode(int[0], int[1]); + r.insert(node); }); return r; } @@ -426,7 +428,7 @@ suite('IntervalTree', () => { function assertIntervalSearch(start: number, end: number, expected: [number, number][]): void { let actualNodes = T.intervalSearch(new Interval(start, end)); - let actual = actualNodes.map((n) => <[number, number]>[n.resultInterval.start, n.resultInterval.end]); + let actual = actualNodes.map((n) => <[number, number]>[n.absoluteInterval.start, n.absoluteInterval.end]); assert.deepEqual(actual, expected); } From 1621e289c4a2466c6f98e56edeaf7978ab229637 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 13 Oct 2017 09:55:05 +0200 Subject: [PATCH 053/394] fix broken terminal --- .../electron-browser/terminalInstance.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index da798434930..113ed5e0e48 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -511,14 +511,16 @@ export class TerminalInstance implements ITerminalInstance { // background since scrollTop changes take no effect but the terminal's position does // change since the number of visible rows decreases. this._xterm.emit('scroll', this._xterm.buffer.ydisp); - // Force a layout when the instance becomes invisible. This is particularly important - // for ensuring that terminals that are created in the background by an extension will - // correctly get correct character measurements in order to render to the screen (see - // #34554). - const computedStyle = window.getComputedStyle(this._container); - const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); - const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); - this.layout(new Dimension(width, height)); + if (this._container) { + // Force a layout when the instance becomes invisible. This is particularly important + // for ensuring that terminals that are created in the background by an extension will + // correctly get correct character measurements in order to render to the screen (see + // #34554). + const computedStyle = window.getComputedStyle(this._container); + const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); + const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); + this.layout(new Dimension(width, height)); + } } } From f1ee80be081b0d47f4423b9dc5f41a65c36146da Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 10:01:15 +0200 Subject: [PATCH 054/394] support opacity --- .../decorations/browser/decorations.ts | 1 + .../decorations/browser/decorationsService.ts | 123 +++++++++++------- 2 files changed, 75 insertions(+), 49 deletions(-) diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 72f06102f77..337311d6709 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -16,6 +16,7 @@ export const IResourceDecorationsService = createDecorator(); + private readonly _classNames2ColorIds = new Map(); constructor( private _themeService: IThemeService, @@ -35,59 +83,36 @@ class DecorationColors { dispose(): void { dispose(this._disposables); - this._styleElement.innerHTML = ''; + this._styleElement.parentElement.removeChild(this._styleElement); } - makeResourceDecoration(decoration: IResourceDecorationData): IResourceDecoration { - if (!decoration) { + asDecoration(data: IResourceDecorationData): IResourceDecoration { + if (!data) { return undefined; } - let { severity, letter, tooltip } = decoration; - let labelClassName, badgeClassName; + let key = DecorationRule.keyOf(data); + let rule = this._classNames2ColorIds.get(data.color); + let result = new ResourceDecoration(data); - let tuple = this._classNames2ColorIds.get(decoration.color); - - if (tuple) { - // from cache - labelClassName = tuple[0]; - badgeClassName = tuple[1]; - } else { - // new css rules - labelClassName = this._classNames.nextId(); - badgeClassName = this._classNames.nextId(); - this._classNames2ColorIds.set(decoration.color, [labelClassName, badgeClassName]); - this._createCssRules(labelClassName, badgeClassName, decoration.color); + if (!rule) { + // new css rule + rule = new DecorationRule(data); + this._classNames2ColorIds.set(key, rule); + rule.appendCSSRules(this._styleElement, this._themeService.getTheme()); } - return { - _decoBrand: undefined, - severity, - letter, - tooltip, - labelClassName, - badgeClassName - }; + result.labelClassName = rule.labelClassName; + result.badgeClassName = rule.badgeClassName; + return result; } private _onThemeChange(): void { - this._classNames2ColorIds.forEach((tuple, color) => { - const [labelClassName, badgeClassName] = tuple; - removeCSSRulesContainingSelector(labelClassName, this._styleElement); - removeCSSRulesContainingSelector(badgeClassName, this._styleElement); - this._createCssRules(labelClassName, badgeClassName, color); + this._classNames2ColorIds.forEach((rule, color) => { + rule.removeCSSRules(this._styleElement); + rule.appendCSSRules(this._styleElement, this._themeService.getTheme()); }); } - - private _createCssRules(labelClassName: string, badgeClassName: string, color: ColorIdentifier): void { - const theme = this._themeService.getTheme(); - // label - createCSSRule(`.${labelClassName}`, `color: ${theme.getColor(color)}`, this._styleElement); - createCSSRule(`.selected .${labelClassName}`, `color: ${theme.getColor(listActiveSelectionForeground)}`, this._styleElement); - - // badge - createCSSRule(`.${badgeClassName}`, `background-color: ${theme.getColor(color)}; color: ${theme.getColor(listActiveSelectionForeground)};`, this._styleElement); - } } class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { @@ -122,7 +147,7 @@ class DecorationProviderWrapper { private readonly _dispoable: IDisposable; constructor( - private readonly _decorationStyles: DecorationColors, + private readonly _decorationStyles: DecorationStyles, private readonly _provider: IDecorationsProvider, private readonly _emitter: Emitter ) { @@ -193,7 +218,7 @@ class DecorationProviderWrapper { } private _keepItem(uri: URI, data: IResourceDecorationData): IResourceDecoration { - let deco = data ? this._decorationStyles.makeResourceDecoration(data) : null; + let deco = data ? this._decorationStyles.asDecoration(data) : null; this._data.set(uri.toString(), deco); this._emitter.fire(uri); return deco; @@ -207,7 +232,7 @@ export class FileDecorationsService implements IResourceDecorationsService { private readonly _data = new LinkedList(); private readonly _onDidChangeDecorationsDelayed = new Emitter(); private readonly _onDidChangeDecorations = new Emitter(); - private readonly _decorationStyles: DecorationColors; + private readonly _decorationStyles: DecorationStyles; readonly onDidChangeDecorations: Event = any( this._onDidChangeDecorations.event, @@ -220,7 +245,7 @@ export class FileDecorationsService implements IResourceDecorationsService { constructor( @IThemeService themeService: IThemeService, ) { - this._decorationStyles = new DecorationColors(themeService); + this._decorationStyles = new DecorationStyles(themeService); } dispose(): void { From 0cd0f70b35e6c04141aa6bbde7b55e5172064a8c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 10:34:40 +0200 Subject: [PATCH 055/394] deco - move badge letter into css rule --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 5 +---- src/vs/workbench/browser/labels.ts | 3 +-- .../services/decorations/browser/decorations.ts | 1 - .../decorations/browser/decorationsService.ts | 9 ++++----- .../test/browser/decorationsService.test.ts | 12 ++++++------ 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 34f285e8c56..f522468ee32 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -19,7 +19,6 @@ export interface IIconLabelCreationOptions { } export interface ILabelBadgeOptions { - letter: string; title: string; className: string; } @@ -157,9 +156,7 @@ export class IconLabel { this.element.style.display = 'flex'; this.element.appendChild(this.badgeNode); } - const { letter, title } = options.badge; - this.badgeNode.innerHTML = letter; - this.badgeNode.title = title; + this.badgeNode.title = options.badge.title; dom.addClass(this.badgeNode, options.badge.className); dom.show(this.badgeNode); diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 963815fa275..8a312fa3457 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -190,9 +190,8 @@ export class ResourceLabel extends IconLabel { if (deco && this.options.fileDecorations.colors) { iconLabelOptions.extraClasses.push(deco.labelClassName); } - if (deco && deco.letter && this.options.fileDecorations.badges) { + if (deco && deco.badgeClassName && this.options.fileDecorations.badges) { iconLabelOptions.badge = { - letter: deco.letter, title: deco.tooltip, className: deco.badgeClassName, }; diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 337311d6709..9c3ae31c0d8 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -24,7 +24,6 @@ export interface IResourceDecorationData { export interface IResourceDecoration { readonly _decoBrand: undefined; readonly severity: Severity; - readonly letter?: string; readonly tooltip?: string; readonly labelClassName?: string; readonly badgeClassName?: string; diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 27ad1ddf8e4..a7ce6666458 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -20,8 +20,8 @@ import { listActiveSelectionForeground } from 'vs/platform/theme/common/colorReg class DecorationRule { static keyOf(data: IResourceDecorationData): string { - const { color, opacity } = data; - return `${color}/${opacity}`; + const { color, opacity, letter } = data; + return `${color}/${opacity}/${letter}`; } private static readonly _classNames = new IdGenerator('monaco-decorations-style-'); @@ -37,12 +37,13 @@ class DecorationRule { } appendCSSRules(element: HTMLStyleElement, theme: ITheme): void { - const { color, opacity } = this.data; + const { color, opacity, letter } = this.data; // label createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); createCSSRule(`.selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); // badge createCSSRule(`.${this.badgeClassName}`, `background-color: ${theme.getColor(color)}; color: ${theme.getColor(listActiveSelectionForeground)};`, element); + createCSSRule(`.${this.badgeClassName}::before`, `content: "${letter}"`, element); } removeCSSRules(element: HTMLStyleElement): void { @@ -55,14 +56,12 @@ class ResourceDecoration implements IResourceDecoration { _decoBrand: undefined; severity: Severity; - letter?: string; tooltip?: string; labelClassName?: string; badgeClassName?: string; constructor(data: IResourceDecorationData) { this.severity = data.severity; - this.letter = data.letter; this.tooltip = data.tooltip; } } diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index f6a004f6fb0..f9005929c61 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -38,7 +38,7 @@ suite('DecorationsService', function () { setTimeout(() => resolve({ severity: Severity.Info, color: 'someBlue', - letter: 'T' + tooltip: 'T' })); }); } @@ -53,7 +53,7 @@ suite('DecorationsService', function () { assert.equal(e.affectsResource(uri), true); // sync result - assert.deepEqual(service.getTopDecoration(uri, false).letter, 'T'); + assert.deepEqual(service.getTopDecoration(uri, false).tooltip, 'T'); assert.equal(callCounter, 1); }); }); @@ -68,12 +68,12 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return { severity: Severity.Info, color: 'someBlue', letter: 'Z' }; + return { severity: Severity.Info, color: 'someBlue', tooltip: 'Z' }; } }); // trigger -> sync - assert.deepEqual(service.getTopDecoration(uri, false).letter, 'Z'); + assert.deepEqual(service.getTopDecoration(uri, false).tooltip, 'Z'); assert.equal(callCounter, 1); }); @@ -86,12 +86,12 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return { severity: Severity.Info, color: 'someBlue', letter: 'J' }; + return { severity: Severity.Info, color: 'someBlue', tooltip: 'J' }; } }); // trigger -> sync - assert.deepEqual(service.getTopDecoration(uri, false).letter, 'J'); + assert.deepEqual(service.getTopDecoration(uri, false).tooltip, 'J'); assert.equal(callCounter, 1); // un-register -> ensure good event From 55643dd7e3f3e1577dd41b750a0a7f6ecbfb3749 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 13 Oct 2017 11:06:51 +0200 Subject: [PATCH 056/394] debug: make createProcess private and remove startDebugSession from exHostDebugService fixes #36132 --- .../electron-browser/mainThreadDebugService.ts | 16 ---------------- src/vs/workbench/api/node/extHost.protocol.ts | 1 - src/vs/workbench/api/node/extHostDebugService.ts | 8 -------- src/vs/workbench/parts/debug/common/debug.ts | 5 ----- .../parts/debug/electron-browser/debugService.ts | 9 ++------- .../parts/debug/test/common/mockDebug.ts | 4 ---- 6 files changed, 2 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts index 3776bf439c0..af2d72759b5 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts @@ -80,22 +80,6 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { }); } - public $startDebugSession(folderUri: uri | undefined, configuration: IConfig): TPromise { - if (configuration.request !== 'launch' && configuration.request !== 'attach') { - return TPromise.wrapError(new Error(`only 'launch' or 'attach' allowed for 'request' attribute`)); - } - - const folder = folderUri ? this.contextService.getWorkspace().folders.filter(wf => wf.uri.toString() === folderUri.toString()).pop() : undefined; - return this.debugService.createProcess(folder, configuration).then(process => { - if (process) { - return process.getId(); - } - return TPromise.wrapError(new Error('cannot create debug session')); - }, err => { - return TPromise.wrapError(err && err.message ? err.message : 'cannot start debug session'); - }); - } - public $customDebugAdapterRequest(sessionId: DebugSessionUUID, request: string, args: any): TPromise { const process = this.debugService.findProcessByUUID(sessionId); if (process) { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index a3d65955516..1156af8806e 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -393,7 +393,6 @@ export interface MainThreadDebugServiceShape extends IDisposable { $registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, handle: number): TPromise; $unregisterDebugConfigurationProvider(handle: number): TPromise; $startDebugging(folder: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise; - $startDebugSession(folder: URI | undefined, config: vscode.DebugConfiguration): TPromise; $customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise; } diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 0e27ea89109..71727e711d5 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -98,14 +98,6 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig); } - public startDebugSession(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration): TPromise { - return this._debugServiceProxy.$startDebugSession(folder ? folder.uri : undefined, config).then((id: DebugSessionUUID) => { - const debugSession = new ExtHostDebugSession(this._debugServiceProxy, id, config.type, config.name); - this._debugSessions.set(id, debugSession); - return debugSession; - }); - } - public $acceptDebugSessionStarted(id: DebugSessionUUID, type: string, name: string): void { let debugSession = this._debugSessions.get(id); diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index f226ca69b2b..24ee1c34060 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -591,11 +591,6 @@ export interface IDebugService { */ startDebugging(root: IWorkspaceFolder, configOrName?: IConfig | string, noDebug?: boolean): TPromise; - /** - * Creates a new debug process. Depending on the configuration will either 'launch' or 'attach'. - */ - createProcess(root: IWorkspaceFolder, config: IConfig): TPromise; - /** * Find process by ID. */ diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index b5f6a854f91..844f50b20e6 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -727,7 +727,7 @@ export class DebugService implements debug.IDebugService { return null; } - public createProcess(root: IWorkspaceFolder, config: debug.IConfig, sessionId?: string): TPromise { + private createProcess(root: IWorkspaceFolder, config: debug.IConfig, sessionId: string): TPromise { return this.textFileService.saveAll().then(() => (this.configurationManager.selectedLaunch ? this.configurationManager.selectedLaunch.resolveConfiguration(config) : TPromise.as(config)).then(resolvedConfig => { if (!resolvedConfig) { @@ -749,11 +749,6 @@ export class DebugService implements debug.IDebugService { return TPromise.wrapError(errors.create(message, { actions: [this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL), CloseAction] })); } - if (!sessionId) { - sessionId = generateUuid(); - this.updateStateAndEmit(sessionId, debug.State.Initializing); - } - return this.runPreLaunchTask(root, resolvedConfig.preLaunchTask).then((taskSummary: ITaskSummary) => { const errorCount = resolvedConfig.preLaunchTask ? this.markerService.getStatistics().errors : 0; const successExitCode = taskSummary && taskSummary.exitCode === 0; @@ -1003,7 +998,7 @@ export class DebugService implements debug.IDebugService { config.noDebug = process.configuration.noDebug; } config.__restart = restartData; - this.createProcess(process.session.root, config).then(() => c(null), err => e(err)); + this.createProcess(process.session.root, config, process.getId()).then(() => c(null), err => e(err)); }, 300); }); }).then(() => { diff --git a/src/vs/workbench/parts/debug/test/common/mockDebug.ts b/src/vs/workbench/parts/debug/test/common/mockDebug.ts index 975950318de..c36e51331c9 100644 --- a/src/vs/workbench/parts/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/parts/debug/test/common/mockDebug.ts @@ -92,10 +92,6 @@ export class MockDebugService implements debug.IDebugService { return TPromise.as(null); } - public createProcess(root: IWorkspaceFolder, config: debug.IConfig): TPromise { - return TPromise.as(null); - } - public findProcessByUUID(uuid: string): debug.IProcess | null { return null; } From 103b9ba1a2f9eecc4d4019552c66ca7f25eac989 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 11:10:55 +0200 Subject: [PATCH 057/394] deco - check for unused css rules every N change --- src/vs/base/common/map.ts | 6 +- src/vs/base/test/common/map.test.ts | 3 +- .../decorations/browser/decorationsService.ts | 80 ++++++++++++++----- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 894f82082b6..bb7f231500b 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -452,11 +452,11 @@ export class TernarySearchTree { } } - forEach(callback: (entry: [string, E]) => any) { + forEach(callback: (value: E, index: string) => any) { this._forEach(this._root, [], callback); } - private _forEach(node: TernarySearchTreeNode, parts: string[], callback: (entry: [string, E]) => any) { + private _forEach(node: TernarySearchTreeNode, parts: string[], callback: (value: E, index: string) => any) { if (!node) { return; } @@ -465,7 +465,7 @@ export class TernarySearchTree { let newParts = parts.slice(); newParts.push(node.str); if (node.element) { - callback([this._segments.join(newParts), node.element]); + callback(node.element, this._segments.join(newParts)); } this._forEach(node.mid, newParts, callback); } diff --git a/src/vs/base/test/common/map.test.ts b/src/vs/base/test/common/map.test.ts index e53c60a028b..9eff83860da 100644 --- a/src/vs/base/test/common/map.test.ts +++ b/src/vs/base/test/common/map.test.ts @@ -319,8 +319,7 @@ suite('Map', () => { map.forEach((value, key) => { assert.equal(trie.get(key), value); }); - trie.forEach(entry => { - const [key, element] = entry; + trie.forEach((element, key) => { assert.equal(element, map.get(key)); map.delete(key); }); diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index a7ce6666458..9c1917265c5 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -16,6 +16,7 @@ import { createStyleSheet, createCSSRule, removeCSSRulesContainingSelector } fro import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { IdGenerator } from 'vs/base/common/idGenerator'; import { listActiveSelectionForeground } from 'vs/platform/theme/common/colorRegistry'; +import { IIterator } from 'vs/base/common/iterator'; class DecorationRule { @@ -54,13 +55,15 @@ class DecorationRule { class ResourceDecoration implements IResourceDecoration { _decoBrand: undefined; + _key: string; severity: Severity; tooltip?: string; labelClassName?: string; badgeClassName?: string; - constructor(data: IResourceDecorationData) { + constructor(key: string, data: IResourceDecorationData) { + this._key = key; this.severity = data.severity; this.tooltip = data.tooltip; } @@ -70,7 +73,7 @@ class DecorationStyles { private readonly _disposables: IDisposable[]; private readonly _styleElement = createStyleSheet(); - private readonly _classNames2ColorIds = new Map(); + private readonly _decorationRules = new Map(); constructor( private _themeService: IThemeService, @@ -85,19 +88,19 @@ class DecorationStyles { this._styleElement.parentElement.removeChild(this._styleElement); } - asDecoration(data: IResourceDecorationData): IResourceDecoration { + asDecoration(data: IResourceDecorationData): ResourceDecoration { if (!data) { return undefined; } let key = DecorationRule.keyOf(data); - let rule = this._classNames2ColorIds.get(data.color); - let result = new ResourceDecoration(data); + let rule = this._decorationRules.get(key); + let result = new ResourceDecoration(key, data); if (!rule) { // new css rule rule = new DecorationRule(data); - this._classNames2ColorIds.set(key, rule); + this._decorationRules.set(key, rule); rule.appendCSSRules(this._styleElement, this._themeService.getTheme()); } @@ -107,11 +110,30 @@ class DecorationStyles { } private _onThemeChange(): void { - this._classNames2ColorIds.forEach((rule, color) => { + this._decorationRules.forEach(rule => { rule.removeCSSRules(this._styleElement); rule.appendCSSRules(this._styleElement, this._themeService.getTheme()); }); } + + cleanUp(iter: IIterator): void { + // remove every rule for which no more + // decoration (data) is kept. this isn't cheap + let usedDecorations = new Set(); + for (let e = iter.next(); !e.done; e = iter.next()) { + e.value.data.forEach(value => { + if (value instanceof ResourceDecoration) { + usedDecorations.add(value._key); + } + }); + } + this._decorationRules.forEach((value, index) => { + if (!usedDecorations.has(index)) { + value.removeCSSRules(this._styleElement); + this._decorationRules.delete(index); + } + }); + } } class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { @@ -142,7 +164,7 @@ class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { class DecorationProviderWrapper { - private readonly _data = TernarySearchTree.forPaths | IResourceDecoration>(); + readonly data = TernarySearchTree.forPaths | ResourceDecoration>(); private readonly _dispoable: IDisposable; constructor( @@ -152,7 +174,7 @@ class DecorationProviderWrapper { ) { this._dispoable = this._provider.onDidChange(uris => { for (const uri of uris) { - this._data.delete(uri.toString()); + this.data.delete(uri.toString()); this._fetchData(uri); } }); @@ -160,16 +182,16 @@ class DecorationProviderWrapper { dispose(): void { this._dispoable.dispose(); - this._data.clear(); + this.data.clear(); } knowsAbout(uri: URI): boolean { - return Boolean(this._data.get(uri.toString())) || Boolean(this._data.findSuperstr(uri.toString())); + return Boolean(this.data.get(uri.toString())) || Boolean(this.data.findSuperstr(uri.toString())); } - getOrRetrieve(uri: URI, includeChildren: boolean, callback: (data: IResourceDecoration, isChild: boolean) => void): void { + getOrRetrieve(uri: URI, includeChildren: boolean, callback: (data: ResourceDecoration, isChild: boolean) => void): void { const key = uri.toString(); - let item = this._data.get(key); + let item = this.data.get(key); if (isThenable(item)) { // pending -> still waiting @@ -187,9 +209,9 @@ class DecorationProviderWrapper { } if (includeChildren) { // (resolved) children - const childTree = this._data.findSuperstr(key); + const childTree = this.data.findSuperstr(key); if (childTree) { - childTree.forEach(([, value]) => { + childTree.forEach(value => { if (value && !isThenable(value)) { callback(value, true); } @@ -198,7 +220,7 @@ class DecorationProviderWrapper { } } - private _fetchData(uri: URI): IResourceDecoration { + private _fetchData(uri: URI): ResourceDecoration { const dataOrThenable = this._provider.provideDecorations(uri); if (!isThenable(dataOrThenable)) { @@ -209,16 +231,16 @@ class DecorationProviderWrapper { // async -> we have a result soon const request = Promise.resolve(dataOrThenable) .then(data => this._keepItem(uri, data)) - .catch(_ => this._data.delete(uri.toString())); + .catch(_ => this.data.delete(uri.toString())); - this._data.set(uri.toString(), request); + this.data.set(uri.toString(), request); return undefined; } } - private _keepItem(uri: URI, data: IResourceDecorationData): IResourceDecoration { + private _keepItem(uri: URI, data: IResourceDecorationData): ResourceDecoration { let deco = data ? this._decorationStyles.asDecoration(data) : null; - this._data.set(uri.toString(), deco); + this.data.set(uri.toString(), deco); this._emitter.fire(uri); return deco; } @@ -232,6 +254,7 @@ export class FileDecorationsService implements IResourceDecorationsService { private readonly _onDidChangeDecorationsDelayed = new Emitter(); private readonly _onDidChangeDecorations = new Emitter(); private readonly _decorationStyles: DecorationStyles; + private readonly _disposables: IDisposable[]; readonly onDidChangeDecorations: Event = any( this._onDidChangeDecorations.event, @@ -243,12 +266,27 @@ export class FileDecorationsService implements IResourceDecorationsService { constructor( @IThemeService themeService: IThemeService, + cleanUpCount: number = 17 ) { this._decorationStyles = new DecorationStyles(themeService); + + // every so many events we check if there are + // css styles that we don't need anymore + let count = 0; + let reg = this.onDidChangeDecorations(() => { + if (++count % cleanUpCount === 0) { + this._decorationStyles.cleanUp(this._data.iterator()); + } + }); + + this._disposables = [ + reg, + this._decorationStyles + ]; } dispose(): void { - this._decorationStyles.dispose(); + dispose(this._disposables); } registerDecortionsProvider(provider: IDecorationsProvider): IDisposable { From 1d2243a1b243713df09c210d920771e5a8429515 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 13 Oct 2017 08:43:17 +0200 Subject: [PATCH 058/394] Execute msbuild as a shell task (see 35752) --- src/vs/workbench/parts/tasks/common/taskTemplates.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/tasks/common/taskTemplates.ts b/src/vs/workbench/parts/tasks/common/taskTemplates.ts index 6165c13bc0a..35a33f94ca9 100644 --- a/src/vs/workbench/parts/tasks/common/taskTemplates.ts +++ b/src/vs/workbench/parts/tasks/common/taskTemplates.ts @@ -54,7 +54,7 @@ const msbuild: TaskEntry = { '\t"tasks": [', '\t\t{', '\t\t\t"taskName": "build",', - '\t\t\t"type": "process",', + '\t\t\t"type": "shell",', '\t\t\t"command": "msbuild",', '\t\t\t"args": [', '\t\t\t\t// Ask msbuild to generate full paths for file names.', From 033e6f1c3d98aae6c25ac996e052a572a4eb8fec Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 13 Oct 2017 11:27:55 +0200 Subject: [PATCH 059/394] debug: better state wrap up, make sure to not end up in INITIAZLING forever --- .../parts/debug/electron-browser/debugService.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 844f50b20e6..b3cda1acdc0 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -703,6 +703,12 @@ export class DebugService implements debug.IDebugService { const sessionId = generateUuid(); this.updateStateAndEmit(sessionId, debug.State.Initializing); + const wrapUpState = () => { + if (this.sessionStates.get(sessionId) === debug.State.Initializing) { + this.updateStateAndEmit(sessionId, debug.State.Inactive); + } + }; + return (type ? TPromise.as(null) : this.configurationManager.guessAdapter().then(a => type = a && a.type)).then(() => this.configurationManager.resolveConfigurationByProviders(launch ? launch.workspace.uri : undefined, type, config).then(config => { // a falsy config indicates an aborted launch @@ -710,10 +716,12 @@ export class DebugService implements debug.IDebugService { return this.createProcess(root, config, sessionId); } - this.updateStateAndEmit(sessionId, debug.State.Inactive); return launch.openConfigFile(false, type); // cast to ignore weird compile error }) - ); + ).then(() => wrapUpState(), (err) => { + wrapUpState(); + return err; + }); }) ))); } @@ -772,7 +780,6 @@ export class DebugService implements debug.IDebugService { }); return undefined; }, (err: TaskError) => { - this.updateStateAndEmit(sessionId, debug.State.Inactive); this.messageService.show(err.severity, { message: err.message, actions: [ @@ -783,7 +790,6 @@ export class DebugService implements debug.IDebugService { }); }); }, err => { - this.updateStateAndEmit(sessionId, debug.State.Inactive); if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(severity.Error, nls.localize('noFolderWorkspaceDebugError', "The active file can not be debugged. Make sure it is saved on disk and that you have a debug extension installed for that file type.")); return undefined; From 17bdd27d0a34ecf55b031c6ab2e236b49cac814e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 11:24:02 +0200 Subject: [PATCH 060/394] deco - use relative line height for badge --- src/vs/base/browser/ui/iconLabel/iconlabel.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconlabel.css b/src/vs/base/browser/ui/iconLabel/iconlabel.css index a1dda94d93e..77a60e33789 100644 --- a/src/vs/base/browser/ui/iconLabel/iconlabel.css +++ b/src/vs/base/browser/ui/iconLabel/iconlabel.css @@ -48,7 +48,7 @@ align-self: center; height: 12px; min-width: 10px; - line-height: 12px; + line-height: 125%; font-size: 80%; margin: 1px 15px 1px auto; padding: 2px 4px; From 8ee7a4991ea4dda9f74518f8aedbdc6422cfbbfe Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 11:29:35 +0200 Subject: [PATCH 061/394] deco - more boxy badges --- src/vs/base/browser/ui/iconLabel/iconlabel.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconlabel.css b/src/vs/base/browser/ui/iconLabel/iconlabel.css index 77a60e33789..259040da2c2 100644 --- a/src/vs/base/browser/ui/iconLabel/iconlabel.css +++ b/src/vs/base/browser/ui/iconLabel/iconlabel.css @@ -51,8 +51,8 @@ line-height: 125%; font-size: 80%; margin: 1px 15px 1px auto; - padding: 2px 4px; - border-radius: 14px; + padding: 2px 3px; + border-radius: 5px; font-weight: normal; text-align: center; } From 683b531ca9b4a90c7615275e2fc8bf9be934ecf2 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 13 Oct 2017 11:38:10 +0200 Subject: [PATCH 062/394] Addresses 35734 --- .../tasks/electron-browser/task.contribution.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 1737491b685..d1dc34a51f8 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -1421,6 +1421,8 @@ class TaskService extends EventEmitter implements ITaskService { let legacyTaskConfigurations = folderTasks.set ? this.getLegacyTaskConfigurations(folderTasks.set) : undefined; let customTasksToDelete: Task[] = []; if (configurations || legacyTaskConfigurations) { + let unUsedConfigurations: Set = new Set(); + Object.keys(configurations.byIdentifier).forEach(key => unUsedConfigurations.add(key)); for (let task of contributed) { if (!ContributedTask.is(task)) { continue; @@ -1428,6 +1430,7 @@ class TaskService extends EventEmitter implements ITaskService { if (configurations) { let configuringTask = configurations.byIdentifier[task.defines._key]; if (configuringTask) { + unUsedConfigurations.delete(task.defines._key); result.add(key, TaskConfig.createCustomTask(task, configuringTask)); } else { result.add(key, task); @@ -1458,6 +1461,15 @@ class TaskService extends EventEmitter implements ITaskService { } else { result.add(key, ...folderTasks.set.tasks); } + unUsedConfigurations.forEach((value) => { + let configuringTask = configurations.byIdentifier[value]; + this._outputChannel.append(nls.localize( + 'TaskService.noConfiguration', + 'Error: No task has been contributed for the following task configuration:\n{0}\nThe task configuration will be ignored.\n', + JSON.stringify(configuringTask._source.config.element, undefined, 4) + )); + this.showOutput(); + }); } else { result.add(key, ...folderTasks.set.tasks); result.add(key, ...contributed); From f61f960249f40ca4d9aaca11697340300e9eb0ed Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 11:46:13 +0200 Subject: [PATCH 063/394] deco - use weight instead of severity --- .../parts/markers/browser/markersFileDecorations.ts | 2 +- .../parts/scm/electron-browser/scmFileDecorations.ts | 3 +-- .../services/decorations/browser/decorations.ts | 5 ++--- .../services/decorations/browser/decorationsService.ts | 9 ++++----- .../decorations/test/browser/decorationsService.test.ts | 6 ++---- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts index d2e31659374..045838d7db9 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts @@ -41,7 +41,7 @@ class MarkersDecorationsProvider implements IDecorationsProvider { const [first] = markers; return { - severity: first.severity, + weight: 100 * first.severity, tooltip: localize('tooltip', "{0} problems in this file", markers.length), letter: markers.length.toString(), color: first.severity === Severity.Error ? editorErrorForeground : editorWarningForeground, diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index dec7a16bb77..3e15ece693a 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -10,7 +10,6 @@ import { IResourceDecorationsService, IDecorationsProvider, IResourceDecorationD import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource } from 'vs/workbench/services/scm/common/scm'; import URI from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; import Event, { Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; @@ -67,7 +66,7 @@ class SCMDecorationsProvider implements IDecorationsProvider { return undefined; } return { - severity: Severity.Info, + weight: 10, tooltip: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label), color: resource.decorations.color, letter: resource.decorations.tooltip.charAt(0) diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 9c3ae31c0d8..110b0e39b2a 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -7,14 +7,13 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import URI from 'vs/base/common/uri'; import Event from 'vs/base/common/event'; -import Severity from 'vs/base/common/severity'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { IDisposable } from 'vs/base/common/lifecycle'; export const IResourceDecorationsService = createDecorator('IFileDecorationsService'); export interface IResourceDecorationData { - readonly severity: Severity; + readonly weight?: number; readonly color?: ColorIdentifier; readonly opacity?: number; readonly letter?: string; @@ -23,7 +22,7 @@ export interface IResourceDecorationData { export interface IResourceDecoration { readonly _decoBrand: undefined; - readonly severity: Severity; + readonly weight?: number; readonly tooltip?: string; readonly labelClassName?: string; readonly badgeClassName?: string; diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 9c1917265c5..7d3172294cd 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -5,7 +5,6 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; import Event, { Emitter, debounceEvent, any } from 'vs/base/common/event'; import { IResourceDecorationsService, IResourceDecoration, IResourceDecorationChangeEvent, IDecorationsProvider, IResourceDecorationData } from './decorations'; import { TernarySearchTree } from 'vs/base/common/map'; @@ -57,14 +56,14 @@ class ResourceDecoration implements IResourceDecoration { _decoBrand: undefined; _key: string; - severity: Severity; + weight?: number; tooltip?: string; labelClassName?: string; badgeClassName?: string; constructor(key: string, data: IResourceDecorationData) { this._key = key; - this.severity = data.severity; + this.weight = data.weight; this.tooltip = data.tooltip; } } @@ -317,7 +316,7 @@ export class FileDecorationsService implements IResourceDecorationsService { // only bubble up color top = { _decoBrand: undefined, - severity: top.severity, + weight: top.weight, labelClassName: top.labelClassName }; } @@ -331,7 +330,7 @@ export class FileDecorationsService implements IResourceDecorationsService { return b; } else if (!b) { return a; - } else if (Severity.compare(a.severity, b.severity) < 0) { + } else if (a.weight > b.weight) { return a; } else { return b; diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index f9005929c61..d1611916273 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -10,7 +10,6 @@ import { FileDecorationsService } from 'vs/workbench/services/decorations/browse import { IDecorationsProvider, IResourceDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import URI from 'vs/base/common/uri'; import Event, { toPromise } from 'vs/base/common/event'; -import Severity from 'vs/base/common/severity'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; suite('DecorationsService', function () { @@ -36,7 +35,6 @@ suite('DecorationsService', function () { callCounter += 1; return new Promise(resolve => { setTimeout(() => resolve({ - severity: Severity.Info, color: 'someBlue', tooltip: 'T' })); @@ -68,7 +66,7 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return { severity: Severity.Info, color: 'someBlue', tooltip: 'Z' }; + return { color: 'someBlue', tooltip: 'Z' }; } }); @@ -86,7 +84,7 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return { severity: Severity.Info, color: 'someBlue', tooltip: 'J' }; + return { color: 'someBlue', tooltip: 'J' }; } }); From 0d3c0dcb4a19ceda197ca4a7c58118aa585c0126 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 13 Oct 2017 11:53:25 +0200 Subject: [PATCH 064/394] Use all keys configuration change event when configuration is initialized --- .../platform/configuration/common/configurationModels.ts | 8 ++++++++ .../services/configuration/node/configurationService.ts | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index f86a10ee7d1..68a3f544f61 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -415,6 +415,14 @@ export class Configuration { } } +export class AllKeysConfigurationChangeEvent implements IConfigurationChangeEvent { + + constructor(readonly affectedKeys: string[], readonly source: ConfigurationTarget, readonly sourceConfig: any) { } + + affectsConfiugration: () => true; + +} + export class ConfigurationChangeEvent implements IConfigurationChangeEvent { private changedConfiguration: ConfigurationModel = new ConfigurationModel(); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index a57b41a33f6..3cccaa1e6b2 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -23,7 +23,7 @@ import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CustomConfigurationModel, ConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; +import { CustomConfigurationModel, ConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier } from 'vs/platform/configuration/common/configuration'; import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; @@ -326,7 +326,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // TODO: compare with old values?? const keys = this._configuration.keys(); - this.triggerConfigurationChange(new ConfigurationChangeEvent().change([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder]), ConfigurationTarget.WORKSPACE); + this._onDidUpdateConfiguration.fire(new AllKeysConfigurationChangeEvent([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE))); }); } From 74423a68d62fc66f9c2678208a5a15c58f2e4476 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 11:58:32 +0200 Subject: [PATCH 065/394] deco - create css rules for decoration as late as possible --- .../decorations/browser/decorationsService.ts | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 7d3172294cd..10d7d30cd87 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -42,8 +42,10 @@ class DecorationRule { createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); createCSSRule(`.selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); // badge - createCSSRule(`.${this.badgeClassName}`, `background-color: ${theme.getColor(color)}; color: ${theme.getColor(listActiveSelectionForeground)};`, element); - createCSSRule(`.${this.badgeClassName}::before`, `content: "${letter}"`, element); + if (letter) { + createCSSRule(`.${this.badgeClassName}`, `background-color: ${theme.getColor(color)}; color: ${theme.getColor(listActiveSelectionForeground)};`, element); + createCSSRule(`.${this.badgeClassName}::before`, `content: "${letter}"`, element); + } } removeCSSRules(element: HTMLStyleElement): void { @@ -88,10 +90,6 @@ class DecorationStyles { } asDecoration(data: IResourceDecorationData): ResourceDecoration { - if (!data) { - return undefined; - } - let key = DecorationRule.keyOf(data); let rule = this._decorationRules.get(key); let result = new ResourceDecoration(key, data); @@ -163,11 +161,10 @@ class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { class DecorationProviderWrapper { - readonly data = TernarySearchTree.forPaths | ResourceDecoration>(); + readonly data = TernarySearchTree.forPaths | IResourceDecorationData>(); private readonly _dispoable: IDisposable; constructor( - private readonly _decorationStyles: DecorationStyles, private readonly _provider: IDecorationsProvider, private readonly _emitter: Emitter ) { @@ -188,7 +185,7 @@ class DecorationProviderWrapper { return Boolean(this.data.get(uri.toString())) || Boolean(this.data.findSuperstr(uri.toString())); } - getOrRetrieve(uri: URI, includeChildren: boolean, callback: (data: ResourceDecoration, isChild: boolean) => void): void { + getOrRetrieve(uri: URI, includeChildren: boolean, callback: (data: IResourceDecorationData, isChild: boolean) => void): void { const key = uri.toString(); let item = this.data.get(key); @@ -219,7 +216,7 @@ class DecorationProviderWrapper { } } - private _fetchData(uri: URI): ResourceDecoration { + private _fetchData(uri: URI): IResourceDecorationData { const dataOrThenable = this._provider.provideDecorations(uri); if (!isThenable(dataOrThenable)) { @@ -237,8 +234,8 @@ class DecorationProviderWrapper { } } - private _keepItem(uri: URI, data: IResourceDecorationData): ResourceDecoration { - let deco = data ? this._decorationStyles.asDecoration(data) : null; + private _keepItem(uri: URI, data: IResourceDecorationData): IResourceDecorationData { + let deco = data ? data : null; this.data.set(uri.toString(), deco); this._emitter.fire(uri); return deco; @@ -291,7 +288,6 @@ export class FileDecorationsService implements IResourceDecorationsService { registerDecortionsProvider(provider: IDecorationsProvider): IDisposable { const wrapper = new DecorationProviderWrapper( - this._decorationStyles, provider, this._onDidChangeDecorationsDelayed ); @@ -308,24 +304,28 @@ export class FileDecorationsService implements IResourceDecorationsService { } getTopDecoration(uri: URI, includeChildren: boolean): IResourceDecoration { - let top: IResourceDecoration; + let top: IResourceDecorationData; + let topIsChild: boolean; for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) { next.value.getOrRetrieve(uri, includeChildren, (candidate, isChild) => { top = FileDecorationsService._pickBest(top, candidate); - if (isChild && top === candidate) { - // only bubble up color - top = { - _decoBrand: undefined, - weight: top.weight, - labelClassName: top.labelClassName - }; - } + topIsChild = top === candidate && isChild; }); } - return top; + + if (!top) { + return undefined; + } + + let deco = this._decorationStyles.asDecoration(top); + if (topIsChild) { + // don't show badges for child status + deco.badgeClassName = ''; + } + return deco; } - private static _pickBest(a: IResourceDecoration, b: IResourceDecoration): IResourceDecoration { + private static _pickBest(a: IResourceDecorationData, b: IResourceDecorationData): IResourceDecorationData { if (!a) { return b; } else if (!b) { From 395112db9ecd3418a43b6c2504b4fb00fa9a87a7 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 11:14:20 +0200 Subject: [PATCH 066/394] [themes] use 'color-hex' in JSON schemas --- src/vs/platform/theme/common/colorExtensionPoint.ts | 6 +++--- src/vs/platform/theme/common/colorRegistry.ts | 5 ++--- src/vs/workbench/services/themes/common/colorThemeSchema.ts | 2 +- .../workbench/services/themes/common/fileIconThemeSchema.ts | 2 +- .../themes/electron-browser/workbenchThemeService.ts | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/vs/platform/theme/common/colorExtensionPoint.ts b/src/vs/platform/theme/common/colorExtensionPoint.ts index 51a47fdb4bb..d9e077db578 100644 --- a/src/vs/platform/theme/common/colorExtensionPoint.ts +++ b/src/vs/platform/theme/common/colorExtensionPoint.ts @@ -42,7 +42,7 @@ const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint Date: Fri, 13 Oct 2017 11:15:03 +0200 Subject: [PATCH 067/394] [json] update service --- extensions/json/server/npm-shrinkwrap.json | 19 +++++++++++++------ extensions/json/server/package.json | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/extensions/json/server/npm-shrinkwrap.json b/extensions/json/server/npm-shrinkwrap.json index 13925889795..4f69e09581f 100644 --- a/extensions/json/server/npm-shrinkwrap.json +++ b/extensions/json/server/npm-shrinkwrap.json @@ -43,9 +43,9 @@ "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.1.tgz" }, "vscode-json-languageservice": { - "version": "2.0.21", + "version": "2.0.22", "from": "vscode-json-languageservice@next", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-2.0.21.tgz" + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-2.0.22.tgz" }, "vscode-jsonrpc": { "version": "3.5.0-next.1", @@ -60,12 +60,19 @@ "vscode-languageserver-protocol": { "version": "3.5.0-next.3", "from": "vscode-languageserver-protocol@>=3.5.0-next.2 <4.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0-next.3.tgz" + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0-next.3.tgz", + "dependencies": { + "vscode-languageserver-types": { + "version": "3.5.0-next.1", + "from": "vscode-languageserver-types@>=3.5.0-next.1 <4.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0-next.1.tgz" + } + } }, "vscode-languageserver-types": { - "version": "3.5.0-next.1", - "from": "vscode-languageserver-types@>=3.5.0-next.1 <4.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0-next.1.tgz" + "version": "3.4.0", + "from": "vscode-languageserver-types@3.4.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.4.0.tgz" }, "vscode-nls": { "version": "2.0.2", diff --git a/extensions/json/server/package.json b/extensions/json/server/package.json index 3e4dfd6508f..e570819c565 100644 --- a/extensions/json/server/package.json +++ b/extensions/json/server/package.json @@ -10,7 +10,7 @@ "dependencies": { "jsonc-parser": "^1.0.0", "request-light": "^0.2.1", - "vscode-json-languageservice": "^2.0.21", + "vscode-json-languageservice": "^2.0.22", "vscode-languageserver": "^3.5.0-next.2", "vscode-nls": "^2.0.2", "vscode-uri": "^1.0.1" From fed4b741150cc5a2d6f8ebe12e05fc9d85db50d3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 11:50:37 +0200 Subject: [PATCH 068/394] Update IJSONSchema: v6 and custom properties --- src/vs/base/common/jsonSchema.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/jsonSchema.ts b/src/vs/base/common/jsonSchema.ts index 2aa8c50c9f7..538858e0c0d 100644 --- a/src/vs/base/common/jsonSchema.ts +++ b/src/vs/base/common/jsonSchema.ts @@ -6,6 +6,7 @@ export interface IJSONSchema { id?: string; + $id?: string; $schema?: string; type?: string | string[]; title?: string; @@ -17,7 +18,7 @@ export interface IJSONSchema { additionalProperties?: boolean | IJSONSchema; minProperties?: number; maxProperties?: number; - dependencies?: IJSONSchemaMap | { [name: string]: string[] }; + dependencies?: IJSONSchemaMap | { [prop: string]: string[] }; items?: IJSONSchema | IJSONSchema[]; minItems?: number; maxItems?: number; @@ -28,8 +29,8 @@ export interface IJSONSchema { maxLength?: number; minimum?: number; maximum?: number; - exclusiveMinimum?: boolean; - exclusiveMaximum?: boolean; + exclusiveMinimum?: boolean | number; + exclusiveMaximum?: boolean | number; multipleOf?: number; required?: string[]; $ref?: string; @@ -40,11 +41,19 @@ export interface IJSONSchema { enum?: any[]; format?: string; + // schema draft 06 + const?: any; + contains?: IJSONSchema; + propertyNames?: IJSONSchema; + + // VSCode extensions defaultSnippets?: IJSONSchemaSnippet[]; // VSCode extension errorMessage?: string; // VSCode extension patternErrorMessage?: string; // VSCode extension deprecationMessage?: string; // VSCode extension enumDescriptions?: string[]; // VSCode extension + markdownEnumDescriptions?: string[]; // VSCode extension + markdownDescription?: string; // VSCode extension doNotSuggest?: boolean; // VSCode extension } From 366d85a42c23370af4139dcbc92d313c68a9d27c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 11:54:05 +0200 Subject: [PATCH 069/394] Fix use of notifyConfigurationSchemaUpdated --- .../electron-browser/workbenchThemeService.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 8b5f5ce8412..59d95aacbcf 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -13,11 +13,10 @@ import { IWorkbenchThemeService, IColorTheme, ITokenColorCustomizations, IFileIc import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IJSONSchema } from 'vs/base/common/jsonSchema'; import errors = require('vs/base/common/errors'); import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IMessageService } from 'vs/platform/message/common/message'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -151,12 +150,12 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.colorThemeStore.onDidChange(themes => { colorThemeSettingSchema.enum = themes.map(t => t.settingsId); colorThemeSettingSchema.enumDescriptions = themes.map(t => themeData.description || ''); - configurationRegistry.notifyConfigurationSchemaUpdated(colorThemeSettingSchema); + configurationRegistry.notifyConfigurationSchemaUpdated(themeSettingsConfiguration); }); this.iconThemeStore.onDidChange(themes => { iconThemeSettingSchema.enum = [null, ...themes.map(t => t.settingsId)]; iconThemeSettingSchema.enumDescriptions = [iconThemeSettingSchema.enumDescriptions[0], ...themes.map(t => themeData.description || '')]; - configurationRegistry.notifyConfigurationSchemaUpdated(iconThemeSettingSchema); + configurationRegistry.notifyConfigurationSchemaUpdated(themeSettingsConfiguration); }); } @@ -534,7 +533,7 @@ class ConfigurationWriter { // Configuration: Themes const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); -const colorThemeSettingSchema: IJSONSchema = { +const colorThemeSettingSchema: IConfigurationPropertySchema = { type: 'string', description: nls.localize('colorTheme', "Specifies the color theme used in the workbench."), default: DEFAULT_THEME_SETTING_VALUE, @@ -543,7 +542,7 @@ const colorThemeSettingSchema: IJSONSchema = { errorMessage: nls.localize('colorThemeError', "Theme is unknown or not installed."), }; -const iconThemeSettingSchema: IJSONSchema = { +const iconThemeSettingSchema: IConfigurationPropertySchema = { type: ['string', 'null'], default: DEFAULT_ICON_THEME_SETTING_VALUE, description: nls.localize('iconTheme', "Specifies the icon theme used in the workbench or 'null' to not show any file icons."), @@ -551,7 +550,7 @@ const iconThemeSettingSchema: IJSONSchema = { enumDescriptions: [nls.localize('noIconThemeDesc', 'No file icons')], errorMessage: nls.localize('iconThemeError', "File icon theme is unknown or not installed.") }; -const colorCustomizationsSchema: IJSONSchema = { +const colorCustomizationsSchema: IConfigurationPropertySchema = { type: ['object'], description: nls.localize('workbenchColors', "Overrides colors from the currently selected color theme."), properties: colorThemeSchema.colorsSchema.properties, @@ -566,7 +565,7 @@ const colorCustomizationsSchema: IJSONSchema = { }] }; -configurationRegistry.registerConfiguration({ +const themeSettingsConfiguration: IConfigurationNode = { id: 'workbench', order: 7.1, type: 'object', @@ -575,7 +574,8 @@ configurationRegistry.registerConfiguration({ [ICON_THEME_SETTING]: iconThemeSettingSchema, [CUSTOM_WORKBENCH_COLORS_SETTING]: colorCustomizationsSchema } -}); +}; +configurationRegistry.registerConfiguration(themeSettingsConfiguration); function tokenGroupSettings(description: string) { return { From dd054ab5cee88e18e855a0a428ba1137800676d6 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 12:03:42 +0200 Subject: [PATCH 070/394] Warn about usage of token background colors --- src/vs/workbench/services/themes/common/colorThemeSchema.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/services/themes/common/colorThemeSchema.ts b/src/vs/workbench/services/themes/common/colorThemeSchema.ts index c2403012f98..af8bb743f48 100644 --- a/src/vs/workbench/services/themes/common/colorThemeSchema.ts +++ b/src/vs/workbench/services/themes/common/colorThemeSchema.ts @@ -124,6 +124,10 @@ export const tokenColorizationSettingSchema: IJSONSchema = { format: 'color-hex', defaultSnippets: [{ body: '${1:#FF0000}' }] }, + background: { + type: 'string', + deprecationMessage: nls.localize('schema.token.background.warning', 'Token background colors are currently not supported.') + }, fontStyle: { type: 'string', description: nls.localize('schema.token.fontStyle', 'Font style of the rule: One or a combination of \'italic\', \'bold\' and \'underline\''), From 9c78e13b29238d35aff12d8ae1788599d2c48115 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 13 Oct 2017 12:15:52 +0200 Subject: [PATCH 071/394] Gulp watch fails to trigger recompilation while TypeScript compiles (fixes #36214) --- build/lib/watch/index.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js index bed579ec075..93d9babc2de 100644 --- a/build/lib/watch/index.js +++ b/build/lib/watch/index.js @@ -19,14 +19,15 @@ function handleDeletions() { let watch = void 0; -if (!process.env['VSCODE_USE_LEGACY_WATCH']) { - try { - watch = require('./watch-nsfw'); - } catch (err) { - console.warn('Could not load our cross platform file watcher: ' + err.toString()); - console.warn('Falling back to our platform specific watcher...'); - } -} +// Disabled due to https://github.com/Microsoft/vscode/issues/36214 +// if (!process.env['VSCODE_USE_LEGACY_WATCH']) { +// try { +// watch = require('./watch-nsfw'); +// } catch (err) { +// console.warn('Could not load our cross platform file watcher: ' + err.toString()); +// console.warn('Falling back to our platform specific watcher...'); +// } +// } if (!watch) { watch = process.platform === 'win32' ? require('./watch-win32') : require('gulp-watch'); From 016cef69120bded64ed0e90cfd0bfa1596688ab2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 13 Oct 2017 12:23:41 +0200 Subject: [PATCH 072/394] Smart merge of override contents --- .../common/configurationModels.ts | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 68a3f544f61..7e5751fcdd4 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -60,17 +60,33 @@ export class ConfigurationModel implements IConfiguraionModel { } public override(identifier: string): ConfigurationModel { - const result = new ConfigurationModel(); - const contents = objects.clone(this.contents); - if (this._overrides) { - for (const override of this._overrides) { - if (override.identifiers.indexOf(identifier) !== -1) { - merge(contents, override.contents, true); + const overrideContents = this.getContentsForOverrideIdentifer(identifier); + + if (!overrideContents) { + // If there are no overrides, use base contents + return new ConfigurationModel(this._contents); + } + + let contents = {}; + for (const key of Object.keys(this._contents)) { + + let contentsForKey = this._contents[key]; + let overrideContentsForKey = overrideContents[key]; + + // If there are override contents for the key clone and merge otherwise use base contents + if (overrideContentsForKey) { + // Clone and merge only if base contents is of type object otherwise just override + if (typeof contentsForKey === 'object') { + contentsForKey = objects.clone(contents[key]); + merge(contentsForKey, overrideContentsForKey, true); + } else { + contentsForKey = overrideContentsForKey; } } + + contents[key] = contentsForKey; } - result._contents = contents; - return result; + return new ConfigurationModel(contents); } public merge(other: ConfigurationModel, overwrite: boolean = true): ConfigurationModel { @@ -93,6 +109,15 @@ export class ConfigurationModel implements IConfiguraionModel { } source._overrides = overrides; } + + private getContentsForOverrideIdentifer(identifier: string): any { + for (const override of this._overrides) { + if (override.identifiers.indexOf(identifier) !== -1) { + return override.contents; + } + } + return null; + } } export class DefaultConfigurationModel extends ConfigurationModel { From d475882151eaaef958c900a49ea77e0fcf51e44b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 13 Oct 2017 12:25:25 +0200 Subject: [PATCH 073/394] smoke: let's catch the sucker --- .../browser/controller/textAreaInput.ts | 3 +- .../browser/controller/textAreaState.ts | 4 +++ src/vs/editor/browser/view/viewController.ts | 8 +++++ test/smoke/src/areas/editor/editor.ts | 2 ++ .../src/areas/workbench/data-loss.test.ts | 35 ++++++++++++------- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/browser/controller/textAreaInput.ts b/src/vs/editor/browser/controller/textAreaInput.ts index 97926f7e12a..2844d654431 100644 --- a/src/vs/editor/browser/controller/textAreaInput.ts +++ b/src/vs/editor/browser/controller/textAreaInput.ts @@ -11,7 +11,7 @@ import * as strings from 'vs/base/common/strings'; import Event, { Emitter } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable } from 'vs/base/common/lifecycle'; -import { ITypeData, TextAreaState, ITextAreaWrapper } from 'vs/editor/browser/controller/textAreaState'; +import { ITypeData, TextAreaState, ITextAreaWrapper, log } from 'vs/editor/browser/controller/textAreaState'; import * as browser from 'vs/base/browser/browser'; import * as platform from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; @@ -220,6 +220,7 @@ export class TextAreaInput extends Disposable { })); this._register(dom.addDisposableListener(textArea.domNode, 'input', () => { + log.push(`${Date.now()}: input, last known state: ${this._textAreaState}, current state: ${this._textAreaState.readFromTextArea(this._textArea)}`); // Pretend here we touched the text area, as the `input` event will most likely // result in a `selectionchange` event which we want to ignore this._textArea.setIgnoreSelectionChangeTime('received input event'); diff --git a/src/vs/editor/browser/controller/textAreaState.ts b/src/vs/editor/browser/controller/textAreaState.ts index 88389a1c924..9c9220681a6 100644 --- a/src/vs/editor/browser/controller/textAreaState.ts +++ b/src/vs/editor/browser/controller/textAreaState.ts @@ -9,6 +9,9 @@ import { Position } from 'vs/editor/common/core/position'; import { EndOfLinePreference } from 'vs/editor/common/editorCommon'; import * as strings from 'vs/base/common/strings'; +export let log: string[] = []; +(this).myLog = log; + export interface ITextAreaWrapper { getValue(): string; setValue(reason: string, value: string): void; @@ -73,6 +76,7 @@ export class TextAreaState { } public writeToTextArea(reason: string, textArea: ITextAreaWrapper, select: boolean): void { + log.push(`${Date.now()}: writeToTextArea - ${reason} - ${this}`); // console.log(Date.now() + ': applyToTextArea ' + reason + ': ' + this.toString()); textArea.setValue(reason, this.value); if (select) { diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index e44a5286665..1dc419d8d79 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -14,6 +14,7 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents'; import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/common/controller/coreCommands'; import { Configuration } from 'vs/editor/browser/config/configuration'; +import { log } from 'vs/editor/browser/controller/textAreaState'; export interface ExecCoreEditorCommandFunc { (editorCommand: CoreEditorCommand, args: any): void; @@ -63,6 +64,7 @@ export class ViewController { } public paste(source: string, text: string, pasteOnNewLine: boolean): void { + log.push(`${Date.now()}: viewController.paste: ${text}, ${pasteOnNewLine}`); this.commandService.executeCommand(editorCommon.Handler.Paste, { text: text, pasteOnNewLine: pasteOnNewLine, @@ -70,12 +72,14 @@ export class ViewController { } public type(source: string, text: string): void { + log.push(`${Date.now()}: viewController.type: ${text}`); this.commandService.executeCommand(editorCommon.Handler.Type, { text: text }); } public replacePreviousChar(source: string, text: string, replaceCharCnt: number): void { + log.push(`${Date.now()}: viewController.replacePreviousChar: ${text}, ${replaceCharCnt}`); this.commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, { text: text, replaceCharCnt: replaceCharCnt @@ -83,18 +87,22 @@ export class ViewController { } public compositionStart(source: string): void { + log.push(`${Date.now()}: viewController.compositionStart`); this.commandService.executeCommand(editorCommon.Handler.CompositionStart, {}); } public compositionEnd(source: string): void { + log.push(`${Date.now()}: viewController.compositionEnd`); this.commandService.executeCommand(editorCommon.Handler.CompositionEnd, {}); } public cut(source: string): void { + log.push(`${Date.now()}: viewController.cut`); this.commandService.executeCommand(editorCommon.Handler.Cut, {}); } public setSelection(source: string, modelSelection: Selection): void { + log.push(`${Date.now()}: viewController.setSelection: ${modelSelection}`); this._execCoreEditorCommandFunc(CoreNavigationCommands.SetSelection, { source: source, selection: modelSelection diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 51c27c84d0a..0a9a238c6f8 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -114,6 +114,8 @@ export class Editor { await new Promise(c => setTimeout(c, 50)); } + // this.spectron.client.spectron.client.keys([text, 'NULL']); + await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index 68d7dd1b377..5eb4a801fd6 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -8,32 +8,41 @@ import { SpectronApplication } from '../../spectron/application'; describe('Dataloss', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Dataloss'); }); - after(() => app.stop()); + after(async () => { + const log = await app.client.spectron.client.execute(() => { + return (window as any).myLog as string[]; + }); + + console.log(log.value.join('\n')); + + await app.stop(); + + }); it(`verifies that 'hot exit' works for dirty files`, async function () { await app.workbench.newUntitledFile(); const untitled = 'Untitled-1'; - const textToTypeInUntitled = 'Hello, Unitled Code'; + const textToTypeInUntitled = 'Hello, Unitled Code alexandru dimaaaaa joao moreno'; await app.workbench.editor.waitForTypeInEditor(untitled, textToTypeInUntitled); await app.screenCapturer.capture('Untitled file before reload'); + await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1); const readmeMd = 'readme.md'; - const textToType = 'Hello, Code'; + const textToType = 'Hello, Code alexandru dimaaaaa joao moreno'; await app.workbench.explorer.openFile(readmeMd); await app.workbench.editor.waitForTypeInEditor(readmeMd, textToType); await app.screenCapturer.capture(`${readmeMd} before reload`); - - await app.reload(); - await app.screenCapturer.capture('After reload'); - - await app.workbench.waitForActiveTab(readmeMd, true); - await app.screenCapturer.capture(`${readmeMd} after reload`); await app.workbench.editor.waitForEditorContents(readmeMd, c => c.indexOf(textToType) > -1); - await app.workbench.waitForTab(untitled, true); - await app.workbench.selectTab(untitled, true); - await app.screenCapturer.capture('Untitled file after reload'); - await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1); + // await app.reload(); + // await app.screenCapturer.capture('After reload'); + + // await app.workbench.waitForActiveTab(readmeMd, true); + // await app.screenCapturer.capture(`${readmeMd} after reload`); + + // await app.workbench.waitForTab(untitled, true); + // await app.workbench.selectTab(untitled, true); + // await app.screenCapturer.capture('Untitled file after reload'); }); }); \ No newline at end of file From 07da4309a3635c0831537aaea067d9c30c737bc1 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 12:14:11 +0200 Subject: [PATCH 074/394] theme-schemas: set color defaults (for better code completion) --- src/vs/workbench/services/themes/common/colorThemeSchema.ts | 2 +- .../services/themes/electron-browser/workbenchThemeService.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/themes/common/colorThemeSchema.ts b/src/vs/workbench/services/themes/common/colorThemeSchema.ts index af8bb743f48..4e7c779283c 100644 --- a/src/vs/workbench/services/themes/common/colorThemeSchema.ts +++ b/src/vs/workbench/services/themes/common/colorThemeSchema.ts @@ -122,7 +122,7 @@ export const tokenColorizationSettingSchema: IJSONSchema = { type: 'string', description: nls.localize('schema.token.foreground', 'Foreground color for the token.'), format: 'color-hex', - defaultSnippets: [{ body: '${1:#FF0000}' }] + default: '#ff0000' }, background: { type: 'string', diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 59d95aacbcf..e09d12ba057 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -584,8 +584,7 @@ function tokenGroupSettings(description: string) { anyOf: [ { type: 'string', - format: 'color-hex', - defaultSnippets: [{ body: '#FF0000' }] + format: 'color-hex' }, colorThemeSchema.tokenColorizationSettingSchema ] From 694dff3057f87f3f713a52ec73186de90ebf122b Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 13 Oct 2017 12:24:23 +0200 Subject: [PATCH 075/394] Return error when terminal creation failed --- .../parts/tasks/electron-browser/terminalTaskSystem.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index 446001d7d91..b3e4d73c599 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -397,6 +397,9 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { }); }); } + if (!terminal) { + return TPromise.wrapError(new Error(`Failed to create terminal for task ${task._label}`)); + } this.terminalService.setActiveInstance(terminal); if (task.command.presentation.reveal === RevealKind.Always || (task.command.presentation.reveal === RevealKind.Silent && task.problemMatchers.length === 0)) { this.terminalService.showPanel(task.command.presentation.focus); From 62dab62fc0191d12c85fefb5ed839c6b910abfcc Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 13 Oct 2017 12:56:41 +0200 Subject: [PATCH 076/394] Improved error message for task not found --- .../parts/tasks/electron-browser/task.contribution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index d1dc34a51f8..69ae1d21ee8 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -1465,7 +1465,8 @@ class TaskService extends EventEmitter implements ITaskService { let configuringTask = configurations.byIdentifier[value]; this._outputChannel.append(nls.localize( 'TaskService.noConfiguration', - 'Error: No task has been contributed for the following task configuration:\n{0}\nThe task configuration will be ignored.\n', + 'Error: The {0} task detection didn\'t contribute a task for the following configuration:\n{1}\nThe task will be ignored.\n', + configuringTask.configures.type, JSON.stringify(configuringTask._source.config.element, undefined, 4) )); this.showOutput(); From 36c55adcf5918a74d990cf6e4fc5bfc4cbe6e4f2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 13:03:54 +0200 Subject: [PATCH 077/394] deco - enable marker decorations but disable them by default --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 3 +- .../markers/browser/markersFileDecorations.ts | 33 +++++++++++-------- .../parts/markers/markers.contribution.ts | 2 +- .../decorations/browser/decorationsService.ts | 2 +- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index f522468ee32..89dac41da35 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -152,12 +152,11 @@ export class IconLabel { if (options && options.badge) { if (!this.badgeNode) { this.badgeNode = document.createElement('span'); - this.badgeNode.className = 'label-badge'; this.element.style.display = 'flex'; this.element.appendChild(this.badgeNode); } this.badgeNode.title = options.badge.title; - dom.addClass(this.badgeNode, options.badge.className); + this.badgeNode.className = `label-badge ${options.badge.className}`; dom.show(this.badgeNode); } else if (this.badgeNode) { diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts index 045838d7db9..46f91a0b701 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts @@ -6,13 +6,12 @@ 'use strict'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { IMarkerService, IMarker } from 'vs/platform/markers/common/markers'; import { IResourceDecorationsService, IDecorationsProvider, IResourceDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import Event from 'vs/base/common/event'; import { localize } from 'vs/nls'; -import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { Registry } from 'vs/platform/registry/common/platform'; import Severity from 'vs/base/common/severity'; import { editorErrorForeground, editorWarningForeground } from 'vs/editor/common/view/editorColorRegistry'; @@ -31,18 +30,21 @@ class MarkersDecorationsProvider implements IDecorationsProvider { } provideDecorations(resource: URI): IResourceDecorationData { + let markers = this._markerService.read({ resource }); + let first: IMarker; + for (const marker of markers) { + if (!first || marker.severity > first.severity) { + first = marker; + } + } - const markers = this._markerService.read({ resource }) - .sort((a, b) => Severity.compare(a.severity, b.severity)); - - if (isFalsyOrEmpty(markers)) { + if (!first) { return undefined; } - const [first] = markers; return { weight: 100 * first.severity, - tooltip: localize('tooltip', "{0} problems in this file", markers.length), + tooltip: markers.length === 1 ? localize('tooltip.1', "1 problem in this file") : localize('tooltip.N', "{0} problems in this file", markers.length), letter: markers.length.toString(), color: first.severity === Severity.Error ? editorErrorForeground : editorWarningForeground, }; @@ -53,6 +55,7 @@ class MarkersFileDecorations implements IWorkbenchContribution { private readonly _disposables: IDisposable[]; private _provider: IDisposable; + private _enabled: boolean; constructor( @IMarkerService private _markerService: IMarkerService, @@ -63,7 +66,6 @@ class MarkersFileDecorations implements IWorkbenchContribution { this._disposables = [ this._configurationService.onDidUpdateConfiguration(this._updateEnablement, this), ]; - this._updateEnablement(); } @@ -77,11 +79,16 @@ class MarkersFileDecorations implements IWorkbenchContribution { } private _updateEnablement(): void { - let value = this._configurationService.getConfiguration<{ fileDecorations: { enabled: boolean } }>('problems'); - if (value.fileDecorations.enabled) { + let value = this._configurationService.getConfiguration<{ decorations: { enabled: boolean } }>('problems'); + if (value.decorations.enabled === this._enabled) { + return; + } + this._enabled = value.decorations.enabled; + if (this._enabled) { const provider = new MarkersDecorationsProvider(this._markerService); this._provider = this._decorationsService.registerDecortionsProvider(provider); } else if (this._provider) { + this._enabled = value.decorations.enabled; this._provider.dispose(); } } @@ -94,10 +101,10 @@ Registry.as(ConfigurationExtensions.Configuration).regis 'order': 101, 'type': 'object', 'properties': { - 'problems.fileDecorations.enabled': { + 'problems.decorations.enabled': { 'description': localize('markers.showOnFile', "Show Errors & Warnings on files and folder."), 'type': 'boolean', - 'default': true + 'default': false } } }); diff --git a/src/vs/workbench/parts/markers/markers.contribution.ts b/src/vs/workbench/parts/markers/markers.contribution.ts index 4ab845211d8..b7b91dbc852 100644 --- a/src/vs/workbench/parts/markers/markers.contribution.ts +++ b/src/vs/workbench/parts/markers/markers.contribution.ts @@ -5,7 +5,7 @@ import { registerContributions } from 'vs/workbench/parts/markers/browser/markersWorkbenchContributions'; import { registerContributions as registerElectronContributions } from 'vs/workbench/parts/markers/electron-browser/markersElectronContributions'; -// import './browser/markersFileDecorations'; +import './browser/markersFileDecorations'; registerContributions(); registerElectronContributions(); diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 10d7d30cd87..2b275e9dd54 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -309,7 +309,7 @@ export class FileDecorationsService implements IResourceDecorationsService { for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) { next.value.getOrRetrieve(uri, includeChildren, (candidate, isChild) => { top = FileDecorationsService._pickBest(top, candidate); - topIsChild = top === candidate && isChild; + topIsChild = top === candidate && isChild || topIsChild; }); } From 937fb72255c43c70c36440dcab1ad060e2ea5cfc Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 15:03:12 +0200 Subject: [PATCH 078/394] support to merge decorations --- .../decorations/browser/decorationsService.ts | 125 ++++++++++++------ 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 2b275e9dd54..0203f93a682 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -19,25 +19,37 @@ import { IIterator } from 'vs/base/common/iterator'; class DecorationRule { - static keyOf(data: IResourceDecorationData): string { - const { color, opacity, letter } = data; - return `${color}/${opacity}/${letter}`; + static keyOf(data: IResourceDecorationData | IResourceDecorationData[]): string { + if (Array.isArray(data)) { + return data.map(DecorationRule.keyOf).join(','); + } else { + const { color, opacity, letter } = data; + return `${color}/${opacity}/${letter}`; + } } private static readonly _classNames = new IdGenerator('monaco-decorations-style-'); - readonly data: IResourceDecorationData; + readonly data: IResourceDecorationData | IResourceDecorationData[]; readonly labelClassName: string; readonly badgeClassName: string; - constructor(data: IResourceDecorationData) { + constructor(data: IResourceDecorationData | IResourceDecorationData[]) { this.data = data; this.labelClassName = DecorationRule._classNames.nextId(); this.badgeClassName = DecorationRule._classNames.nextId(); } appendCSSRules(element: HTMLStyleElement, theme: ITheme): void { - const { color, opacity, letter } = this.data; + if (!Array.isArray(this.data)) { + this._appendForOne(this.data, element, theme); + } else { + this._appendForMany(this.data, element, theme); + } + } + + private _appendForOne(data: IResourceDecorationData, element: HTMLStyleElement, theme: ITheme): void { + const { color, opacity, letter } = data; // label createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); createCSSRule(`.selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); @@ -48,6 +60,27 @@ class DecorationRule { } } + private _appendForMany(data: IResourceDecorationData[], element: HTMLStyleElement, theme: ITheme): void { + // label + const { color, opacity } = data[0]; + createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); + createCSSRule(`.selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); + + // badge + let letters: string[] = []; + let colors: string[] = []; + for (const deco of data) { + letters.push(deco.letter); + colors.push(`${theme.getColor(deco.color).toString()} ${100 / data.length}%`); + } + createCSSRule(`.${this.badgeClassName}::before`, `content: "${letters.join('\u2002')}"`, element); + createCSSRule( + `.${this.badgeClassName}`, + `background: linear-gradient(90deg, ${colors.join()}); color: ${theme.getColor(listActiveSelectionForeground)};`, + element + ); + } + removeCSSRules(element: HTMLStyleElement): void { removeCSSRulesContainingSelector(this.labelClassName, element); removeCSSRulesContainingSelector(this.badgeClassName, element); @@ -55,18 +88,29 @@ class DecorationRule { } class ResourceDecoration implements IResourceDecoration { + + static from(data: IResourceDecorationData | IResourceDecorationData[]): ResourceDecoration { + let result = new ResourceDecoration(data); + if (Array.isArray(data)) { + result.weight = data[0].weight; + result.tooltip = data.map(d => d.tooltip).join(', '); + } else { + result.weight = data.weight; + result.tooltip = data.tooltip; + } + return result; + } + _decoBrand: undefined; - _key: string; + _data: IResourceDecorationData | IResourceDecorationData[]; weight?: number; tooltip?: string; labelClassName?: string; badgeClassName?: string; - constructor(key: string, data: IResourceDecorationData) { - this._key = key; - this.weight = data.weight; - this.tooltip = data.tooltip; + private constructor(data: IResourceDecorationData | IResourceDecorationData[]) { + this._data = data; } } @@ -89,10 +133,10 @@ class DecorationStyles { this._styleElement.parentElement.removeChild(this._styleElement); } - asDecoration(data: IResourceDecorationData): ResourceDecoration { + asDecoration(data: IResourceDecorationData | IResourceDecorationData[]): ResourceDecoration { let key = DecorationRule.keyOf(data); let rule = this._decorationRules.get(key); - let result = new ResourceDecoration(key, data); + let result = ResourceDecoration.from(data); if (!rule) { // new css rule @@ -116,16 +160,27 @@ class DecorationStyles { cleanUp(iter: IIterator): void { // remove every rule for which no more // decoration (data) is kept. this isn't cheap - let usedDecorations = new Set(); + let usedDecorations = new Set(); for (let e = iter.next(); !e.done; e = iter.next()) { e.value.data.forEach(value => { if (value instanceof ResourceDecoration) { - usedDecorations.add(value._key); + if (Array.isArray(value._data)) { + value._data.forEach(data => usedDecorations.add(data)); + } else { + usedDecorations.add(value._data); + } } }); } this._decorationRules.forEach((value, index) => { - if (!usedDecorations.has(index)) { + const { data } = value; + let remove: boolean; + if (Array.isArray(data)) { + remove = data.every(data => !usedDecorations.has(data)); + } else if (!usedDecorations.has(data)) { + remove = true; + } + if (remove) { value.removeCSSRules(this._styleElement); this._decorationRules.delete(index); } @@ -304,36 +359,26 @@ export class FileDecorationsService implements IResourceDecorationsService { } getTopDecoration(uri: URI, includeChildren: boolean): IResourceDecoration { - let top: IResourceDecorationData; - let topIsChild: boolean; + let data: IResourceDecorationData[] = []; + let onlyChildren = true; for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) { - next.value.getOrRetrieve(uri, includeChildren, (candidate, isChild) => { - top = FileDecorationsService._pickBest(top, candidate); - topIsChild = top === candidate && isChild || topIsChild; + next.value.getOrRetrieve(uri, includeChildren, (deco, isChild) => { + // top = FileDecorationsService._pickBest(top, candidate); + data.push(deco); + onlyChildren = onlyChildren && isChild; }); } - if (!top) { + if (data.length === 0) { return undefined; - } - - let deco = this._decorationStyles.asDecoration(top); - if (topIsChild) { - // don't show badges for child status - deco.badgeClassName = ''; - } - return deco; - } - - private static _pickBest(a: IResourceDecorationData, b: IResourceDecorationData): IResourceDecorationData { - if (!a) { - return b; - } else if (!b) { - return a; - } else if (a.weight > b.weight) { - return a; + } else if (onlyChildren) { + let result = this._decorationStyles.asDecoration(data.sort((a, b) => b.weight - a.weight)[0]); + result.badgeClassName = ''; + return result; + } else if (data.length === 1) { + return this._decorationStyles.asDecoration(data[0]); } else { - return b; + return this._decorationStyles.asDecoration(data.sort((a, b) => b.weight - a.weight)); } } } From 894c6c6193e46ea2db38f59135238a6e5b274283 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 15:13:11 +0200 Subject: [PATCH 079/394] deco - scm decorator hacks to make things look nice. time for extension api... --- .../parts/scm/electron-browser/scmFileDecorations.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index 3e15ece693a..dea57c82381 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -62,11 +62,11 @@ class SCMDecorationsProvider implements IDecorationsProvider { provideDecorations(uri: URI): IResourceDecorationData { const resource = this._data.get(uri.toString()); - if (!resource) { + if (!resource || !resource.decorations.color) { return undefined; } return { - weight: 10, + weight: 100 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0), tooltip: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label), color: resource.decorations.color, letter: resource.decorations.tooltip.charAt(0) From 80859dd7deb6a456e25f69bd290e07b3ea959db2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 Oct 2017 15:18:32 +0200 Subject: [PATCH 080/394] IntervalNode implements IModelDecoration --- src/vs/editor/common/model/intervalTree.ts | 100 +++++++++++++++--- .../test/common/model/intervalTree.test.ts | 13 ++- 2 files changed, 91 insertions(+), 22 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 7160e8b546c..d89868bc61a 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -4,10 +4,21 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { Range } from 'vs/editor/common/core/range'; +import { IModelDecoration } from 'vs/editor/common/editorCommon'; + // // The red-black tree is based on the "Introduction to Algorithms" by Cormen, Leiserson and Rivest. // +// TODO@interval!!! +export const ClassName = { + EditorInfoDecoration: 'infosquiggly', + EditorWarningDecoration: 'warningsquiggly', + EditorErrorDecoration: 'errorsquiggly' +}; + export class Interval { _intervalBrand: void; @@ -25,11 +36,11 @@ export const enum NodeColor { Black } -export class IntervalNode { +export class IntervalNode implements IModelDecoration { + public parent: IntervalNode; public left: IntervalNode; public right: IntervalNode; - public parent: IntervalNode; public color: NodeColor; public start: number; @@ -37,9 +48,17 @@ export class IntervalNode { public delta: number; public maxEnd: number; - public absoluteInterval: Interval; + public id: string; + public ownerId: number; + public options: ModelDecorationOptions; + public isForValidation: boolean; - constructor(start: number, end: number) { + public cachedVersionId: number; + public cachedAbsoluteStart: number; + public cachedAbsoluteEnd: number; + public range: Range; + + constructor(id: string, start: number, end: number) { this.parent = null; this.left = null; this.right = null; @@ -50,7 +69,34 @@ export class IntervalNode { this.delta = start; this.maxEnd = end; - this.absoluteInterval = new Interval(0, 0); + this.id = id; + this.ownerId = 0; + this.options = null; + this.isForValidation = false; + + this.cachedVersionId = 0; + this.cachedAbsoluteStart = start; + this.cachedAbsoluteEnd = end; + this.range = null; + } + + public setOptions(options: ModelDecorationOptions) { + this.options = options; + this.isForValidation = ( + this.options.className === ClassName.EditorErrorDecoration + || this.options.className === ClassName.EditorWarningDecoration + ); + } + + public setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void { + this.cachedVersionId = cachedVersionId; + if (this.cachedAbsoluteStart === absoluteStart && this.cachedAbsoluteEnd === absoluteEnd) { + // no change + return; + } + this.cachedAbsoluteStart = absoluteStart; + this.cachedAbsoluteEnd = absoluteEnd; + this.range = null; } public detach(): void { @@ -60,7 +106,7 @@ export class IntervalNode { } } -const SENTINEL: IntervalNode = new IntervalNode(0, 0); +const SENTINEL: IntervalNode = new IntervalNode(null, 0, 0); SENTINEL.parent = SENTINEL; SENTINEL.left = SENTINEL; SENTINEL.right = SENTINEL; @@ -74,12 +120,12 @@ export class IntervalTree { this.root = SENTINEL; } - public intervalSearch(interval: Interval): IntervalNode[] { + public intervalSearch(interval: Interval, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { if (this.root === SENTINEL) { return []; } let result: IntervalNode[] = []; - intervalSearchRecursive(this.root, 0, interval.start, interval.end, result); + intervalSearchRecursive(this.root, 0, interval.start, interval.end, filterOwnerId, filterOutValidation, cachedVersionId, result); return result; } @@ -87,10 +133,24 @@ export class IntervalTree { rbTreeInsert(this, node); } - public delete(node: IntervalNode) { + public delete(node: IntervalNode): void { rbTreeDelete(this, node); } + public resolveNode(node: IntervalNode, cachedVersionId: number): void { + let delta = 0; + while (node !== this.root) { + if (node === node.parent.right) { + delta += node.parent.delta; + } + node = node.parent; + } + + const nodeStart = node.start + delta; + const nodeEnd = node.end + delta; + node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); + } + public assertInvariants(): void { assert(SENTINEL.color === NodeColor.Black); assert(SENTINEL.parent === SENTINEL); @@ -150,7 +210,7 @@ export class IntervalTree { } //#region Searching -function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStart: number, intervalEnd: number, result: IntervalNode[]): void { +function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStart: number, intervalEnd: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number, result: IntervalNode[]): void { // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree // Now, it is known that two intervals A and B overlap only when both // A.low <= B.high and A.high >= B.low. When searching the trees for @@ -165,7 +225,7 @@ function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStar } if (node.left !== SENTINEL) { - intervalSearchRecursive(node.left, delta, intervalStart, intervalEnd, result); + intervalSearchRecursive(node.left, delta, intervalStart, intervalEnd, filterOwnerId, filterOutValidation, cachedVersionId, result); } const nodeStart = delta + node.start; @@ -178,13 +238,23 @@ function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStar const nodeEnd = delta + node.end; if (nodeEnd >= intervalStart) { // There is overlap - node.absoluteInterval.start = nodeStart; - node.absoluteInterval.end = nodeEnd; - result.push(node); + node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); + + let include = true; + if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) { + include = false; + } + if (filterOutValidation && node.isForValidation) { + include = false; + } + + if (include) { + result.push(node); + } } if (node.right !== SENTINEL) { - intervalSearchRecursive(node.right, delta + node.delta, intervalStart, intervalEnd, result); + intervalSearchRecursive(node.right, delta + node.delta, intervalStart, intervalEnd, filterOwnerId, filterOutValidation, cachedVersionId, result); } } //#endregion diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index d8518b27a68..7df8a19e0e3 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -65,13 +65,12 @@ suite('IntervalTree', () => { public acceptOp(op: IOperation): void { - if (op.type === 'insert') { if (PRINT_TREE) { console.log(`insert: {${JSON.stringify(new Interval(op.begin, op.end))}}`); } let nodeId = (++this._lastNodeId); - this._treeNodes[nodeId] = new IntervalNode(op.begin, op.end); + this._treeNodes[nodeId] = new IntervalNode(null, op.begin, op.end); this._tree.insert(this._treeNodes[nodeId]); this._oracleNodes[nodeId] = this._oracle.insert(new Interval(op.begin, op.end)); } else if (op.type === 'delete') { @@ -84,8 +83,8 @@ suite('IntervalTree', () => { this._treeNodes[op.id] = null; this._oracleNodes[op.id] = null; } else { - let actualNodes = this._tree.intervalSearch(new Interval(op.begin, op.end)); - let actual = actualNodes.map(n => n.absoluteInterval); + let actualNodes = this._tree.intervalSearch(new Interval(op.begin, op.end), 0, false, 0); + let actual = actualNodes.map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd)); let expected = this._oracle.search(new Interval(op.begin, op.end)); assert.deepEqual(actual, expected); return; @@ -418,7 +417,7 @@ suite('IntervalTree', () => { [19, 20] ]; data.forEach((int) => { - let node = new IntervalNode(int[0], int[1]); + let node = new IntervalNode(null, int[0], int[1]); r.insert(node); }); return r; @@ -427,8 +426,8 @@ suite('IntervalTree', () => { const T = createCormenTree(); function assertIntervalSearch(start: number, end: number, expected: [number, number][]): void { - let actualNodes = T.intervalSearch(new Interval(start, end)); - let actual = actualNodes.map((n) => <[number, number]>[n.absoluteInterval.start, n.absoluteInterval.end]); + let actualNodes = T.intervalSearch(new Interval(start, end), 0, false, 0); + let actual = actualNodes.map((n) => <[number, number]>[n.cachedAbsoluteStart, n.cachedAbsoluteEnd]); assert.deepEqual(actual, expected); } From 3a4ee7e2b66b47c129da1f93cc42f7735730339a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 Oct 2017 15:24:37 +0200 Subject: [PATCH 081/394] add failing, inactive test, #36089 --- .../contrib/snippet/test/browser/snippetVariables.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts index e5de27daa03..aad0d69ba7a 100644 --- a/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts @@ -164,4 +164,12 @@ suite('Snippet Variables Resolver', function () { assertVariableResolve2('${foobarfoobar/(foo)/${2:+FAR}/g}', 'barbar'); // bad group reference }); + + // test('Snippet transforms do not handle regex with alternatives or optional matches, #36089', function () { + // assertVariableResolve2( + // '${TM_FILENAME/^(.)|(?:-(.))|(\\.js)/${1:+/upcase}${2:+/upcase}/g}', + // 'MyClass', + // 'my-class.js' + // ); + // }); }); From a38df198437f5b7fa2f57de10a663daee01054e4 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 13 Oct 2017 16:01:23 +0200 Subject: [PATCH 082/394] take out composite handling from activityBarPart into compositeBar --- src/vs/workbench/browser/compositeBar.ts | 377 ++++++++++++++++++ .../workbench/browser/compositeBarActions.ts | 335 ++++++++++++++++ .../parts/activitybar/activitybarActions.ts | 366 +---------------- .../parts/activitybar/activitybarPart.ts | 370 ++--------------- 4 files changed, 769 insertions(+), 679 deletions(-) create mode 100644 src/vs/workbench/browser/compositeBar.ts create mode 100644 src/vs/workbench/browser/compositeBarActions.ts diff --git a/src/vs/workbench/browser/compositeBar.ts b/src/vs/workbench/browser/compositeBar.ts new file mode 100644 index 00000000000..0fc8b7b53ee --- /dev/null +++ b/src/vs/workbench/browser/compositeBar.ts @@ -0,0 +1,377 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import nls = require('vs/nls'); +import { Action } from 'vs/base/common/actions'; +import { illegalArgument } from 'vs/base/common/errors'; +import * as dom from 'vs/base/browser/dom'; +import * as arrays from 'vs/base/common/arrays'; +import { Dimension } from 'vs/base/browser/builder'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; +import Event, { Emitter } from 'vs/base/common/event'; +import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem } from 'vs/workbench/browser/compositeBarActions'; + +// first goal make the activity bar depend on the composite bar and everything works as before +// after that think about how to plug this into the panel part and the overflow nicely wokring (composite bar in panel will need overflow: hidden) +// on the action bar offsetWidth = gets the width of every child (on the first layout need to check if it is still in the constraints) + +export interface ICompositeBarOptions { + label: 'icon' | 'name'; + storageId: string; + orientation: ActionsOrientation; + composites: { id: string, name: string }[]; + getActivityAction: (compositeId: string) => ActivityAction; + getCompositePinnedAction: (compositeId: string) => Action; + getOpenCompositeAction: (compositeId: string) => Action; +} + +export class CompositeBar { + + private _onDidContextMenu: Emitter; + private _onDidDropComposite: Emitter<{ compositeId: string, toCompositeId: string }>; + + private dimension: Dimension; + private toDispose: IDisposable[]; + + private compositeSwitcherBar: ActionBar; + private compositeOverflowAction: CompositeOverflowActivityAction; + private compositeOverflowActionItem: CompositeOverflowActivityActionItem; + + private compositeIdToActions: { [compositeId: string]: ActivityAction; }; + private compositeIdToActionItems: { [compositeId: string]: IActionItem; }; + private compositeIdToActivityStack: { [compositeId: string]: ICompositeActivity[]; }; + + private pinnedComposites: string[]; + private activeCompositeId: string; + private activeUnpinnedCompositeId: string; + + constructor( + private options: ICompositeBarOptions, + @IContextMenuService private contextMenuService: IContextMenuService, + @IInstantiationService private instantiationService: IInstantiationService, + @IStorageService private storageService: IStorageService, + @IPartService private partService: IPartService, + @IThemeService themeService: IThemeService, + ) { + this.toDispose = []; + this.compositeIdToActionItems = Object.create(null); + this.compositeIdToActions = Object.create(null); + this.compositeIdToActivityStack = Object.create(null); + + this._onDidContextMenu = new Emitter(); + this._onDidDropComposite = new Emitter<{ compositeId: string, toCompositeId: string }>(); + + const pinnedComposites = JSON.parse(this.storageService.get(this.options.storageId, StorageScope.GLOBAL, null)) as string[]; + if (pinnedComposites) { + this.pinnedComposites = pinnedComposites; + } else { + this.pinnedComposites = this.options.composites.map(c => c.id); + } + } + + public get onDidContextMenu(): Event { + return this._onDidContextMenu.event; + } + + public get onDidDropComposite(): Event<{ compositeId: string, toCompositeId: string }> { + return this._onDidDropComposite.event; + } + + public activateComposite(id: string): void { + if (this.compositeIdToActions[id]) { + this.compositeIdToActions[id].activate(); + } + this.activeCompositeId = id; + + const activeUnpinnedCompositeShouldClose = this.activeUnpinnedCompositeId && this.activeUnpinnedCompositeId !== id; + const activeUnpinnedCompositeShouldShow = !this.pinnedComposites.some(pid => pid === id); + if (activeUnpinnedCompositeShouldShow || activeUnpinnedCompositeShouldClose) { + this.updateCompositeSwitcher(); + } + } + + public deactivateComposite(id: string): void { + if (this.compositeIdToActions[id]) { + this.compositeIdToActions[id].deactivate(); + } + } + + public showActivity(compositeId: string, badge: IBadge, clazz?: string): IDisposable { + if (!badge) { + throw illegalArgument('badge'); + } + + const activity = { badge, clazz }; + const stack = this.compositeIdToActivityStack[compositeId] || (this.compositeIdToActivityStack[compositeId] = []); + stack.unshift(activity); + + this.updateActivity(compositeId); + + return { + dispose: () => { + const stack = this.compositeIdToActivityStack[compositeId]; + if (!stack) { + return; + } + + const idx = stack.indexOf(activity); + if (idx < 0) { + return; + } + + stack.splice(idx, 1); + if (stack.length === 0) { + delete this.compositeIdToActivityStack[compositeId]; + } + + this.updateActivity(compositeId); + } + }; + } + + private updateActivity(compositeId: string) { + const action = this.compositeIdToActions[compositeId]; + if (!action) { + return; + } + + const stack = this.compositeIdToActivityStack[compositeId]; + + // reset + if (!stack || !stack.length) { + action.setBadge(undefined); + } + + // update + else { + const [{ badge, clazz }] = stack; + action.setBadge(badge); + if (clazz) { + action.class = clazz; + } + } + } + + public create(container: HTMLElement): void { + this.compositeSwitcherBar = new ActionBar(container, { + actionItemProvider: (action: Action) => action instanceof CompositeOverflowActivityAction ? this.compositeOverflowActionItem : this.compositeIdToActionItems[action.id], + orientation: this.options.orientation, + ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher"), + animated: false + }); + this.updateCompositeSwitcher(); + + // Contextmenu for composites + this.toDispose.push(dom.addDisposableListener(container, dom.EventType.CONTEXT_MENU, (e: MouseEvent) => { + dom.EventHelper.stop(e, true); + this._onDidContextMenu.fire(e); + })); + + // Allow to drop at the end to move composites to the end + this.toDispose.push(dom.addDisposableListener(container, dom.EventType.DROP, (e: DragEvent) => { + const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); + if (draggedCompositeId) { + dom.EventHelper.stop(e, true); + CompositeActionItem.clearDraggedComposite(); + + const targetId = this.pinnedComposites[this.pinnedComposites.length - 1]; + if (targetId !== draggedCompositeId) { + this._onDidDropComposite.fire({ compositeId: draggedCompositeId, toCompositeId: this.pinnedComposites[this.pinnedComposites.length - 1] }); + } + } + })); + } + + private updateCompositeSwitcher(): void { + if (!this.compositeSwitcherBar) { + return; // We have not been rendered yet so there is nothing to update. + } + + let compositesToShow = this.pinnedComposites; + + // Always show the active composite even if it is marked to be hidden + if (this.activeCompositeId && !compositesToShow.some(id => id === this.activeCompositeId)) { + this.activeUnpinnedCompositeId = this.activeCompositeId; + compositesToShow.push(this.activeUnpinnedCompositeId); + } else { + this.activeUnpinnedCompositeId = void 0; + } + + // Ensure we are not showing more composites than we have height for + let overflows = false; + if (this.dimension) { + // TODO@Isidor change this maxVisible computation to be dynamic + const maxVisible = Math.floor(this.dimension.height / 50); + overflows = compositesToShow.length > maxVisible; + + if (overflows) { + compositesToShow = compositesToShow.slice(0, maxVisible - 1 /* make room for overflow action */); + } + } + + const visibleComposites = Object.keys(this.compositeIdToActions); + const visibleCompositesChange = !arrays.equals(compositesToShow, visibleComposites); + + // Pull out overflow action if there is a composite change so that we can add it to the end later + if (this.compositeOverflowAction && visibleCompositesChange) { + this.compositeSwitcherBar.pull(this.compositeSwitcherBar.length() - 1); + + this.compositeOverflowAction.dispose(); + this.compositeOverflowAction = null; + + this.compositeOverflowActionItem.dispose(); + this.compositeOverflowActionItem = null; + } + + // Pull out composites that overflow or got hidden + visibleComposites.forEach(compositeId => { + if (compositesToShow.indexOf(compositeId) === -1) { + this.pullComposite(compositeId); + } + }); + + // Built actions for composites to show + const newCompositesToShow = compositesToShow + .filter(compositeId => !this.compositeIdToActions[compositeId]) + .map(compositeId => this.toAction(compositeId)); + + // Update when we have new composites to show + if (newCompositesToShow.length) { + + // Add to composite switcher + this.compositeSwitcherBar.push(newCompositesToShow, { label: true, icon: true }); + + // Make sure to activate the active one + if (this.activeCompositeId) { + const activeCompositeEntry = this.compositeIdToActions[this.activeCompositeId]; + if (activeCompositeEntry) { + activeCompositeEntry.activate(); + } + } + + // Make sure to restore activity + Object.keys(this.compositeIdToActions).forEach(compositeId => { + this.updateActivity(compositeId); + }); + } + + // Add overflow action as needed + if (visibleCompositesChange && overflows) { + this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => this.compositeOverflowActionItem.showMenu()); + this.compositeOverflowActionItem = this.instantiationService.createInstance( + CompositeOverflowActivityActionItem, + this.compositeOverflowAction, + () => this.getOverflowingComposites(), + () => this.activeCompositeId, + (compositeId: string) => this.compositeIdToActivityStack[compositeId] && this.compositeIdToActivityStack[compositeId][0].badge, + this.options.getOpenCompositeAction + ); + + this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: true, icon: true }); + } + } + + private getOverflowingComposites(): { id: string, name: string }[] { + let overflowingIds = this.pinnedComposites; + if (this.activeUnpinnedCompositeId) { + overflowingIds = overflowingIds.concat(this.activeUnpinnedCompositeId); + } + const visibleComposites = Object.keys(this.compositeIdToActions); + + overflowingIds = overflowingIds.filter(compositeId => visibleComposites.indexOf(compositeId) === -1); + return this.options.composites.filter(c => overflowingIds.indexOf(c.id) !== -1); + } + + public getVisibleComposites(): string[] { + return Object.keys(this.compositeIdToActions); + } + + private pullComposite(compositeId: string): void { + const index = Object.keys(this.compositeIdToActions).indexOf(compositeId); + if (index >= 0) { + this.compositeSwitcherBar.pull(index); + + const action = this.compositeIdToActions[compositeId]; + action.dispose(); + delete this.compositeIdToActions[compositeId]; + + const actionItem = this.compositeIdToActionItems[action.id]; + actionItem.dispose(); + delete this.compositeIdToActionItems[action.id]; + } + } + + private toAction(compositeId: string): ActivityAction { + const compositeActivityAction = this.options.getActivityAction(compositeId); + const pinnedAction = this.options.getCompositePinnedAction(compositeId); + this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction); + this.compositeIdToActions[compositeId] = compositeActivityAction; + + return compositeActivityAction; + } + + public unpin(compositeId: string): void { + const index = this.pinnedComposites.indexOf(compositeId); + this.pinnedComposites.splice(index, 1); + + this.updateCompositeSwitcher(); + } + + public isPinned(compositeId: string): boolean { + return this.pinnedComposites.indexOf(compositeId) >= 0; + } + + public pin(compositeId: string, update = true): void { + this.pinnedComposites.push(compositeId); + this.pinnedComposites = arrays.distinct(this.pinnedComposites); + + if (update) { + this.updateCompositeSwitcher(); + } + } + + public move(compositeId: string, toCompositeId: string): void { + + const fromIndex = this.pinnedComposites.indexOf(compositeId); + const toIndex = this.pinnedComposites.indexOf(toCompositeId); + + this.pinnedComposites.splice(fromIndex, 1); + this.pinnedComposites.splice(toIndex, 0, compositeId); + + // Clear composites that are impacted by the move + const visibleComposites = Object.keys(this.compositeIdToActions); + for (let i = Math.min(fromIndex, toIndex); i < visibleComposites.length; i++) { + this.pullComposite(visibleComposites[i]); + } + + // timeout helps to prevent artifacts from showing up + setTimeout(() => { + this.updateCompositeSwitcher(); + }, 0); + } + + public layout(dimension: Dimension): void { + this.dimension = dimension; + this.updateCompositeSwitcher(); + } + + public store(): void { + this.storageService.store(this.options.storageId, JSON.stringify(this.pinnedComposites), StorageScope.GLOBAL); + } + + public dispose(): void { + this.toDispose = dispose(this.toDispose); + } +} diff --git a/src/vs/workbench/browser/compositeBarActions.ts b/src/vs/workbench/browser/compositeBarActions.ts new file mode 100644 index 00000000000..6b0986b6b0f --- /dev/null +++ b/src/vs/workbench/browser/compositeBarActions.ts @@ -0,0 +1,335 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import nls = require('vs/nls'); +import { Action } from 'vs/base/common/actions'; +import { TPromise } from 'vs/base/common/winjs.base'; +import * as dom from 'vs/base/browser/dom'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { dispose } from 'vs/base/common/lifecycle'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IActivityBarService, TextBadge, NumberBadge, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ActivityAction, ActivityActionItem } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; +import { ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; +import { DelayedDragHandler } from 'vs/base/browser/dnd'; +import { IActivity } from 'vs/workbench/common/activity'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; + +export interface ICompositeActivity { + badge: IBadge; + clazz: string; +} + +export class CompositeOverflowActivityAction extends ActivityAction { + + constructor( + private showMenu: () => void + ) { + super({ + id: 'activitybar.additionalComposites.action', + name: nls.localize('additionalViews', "Additional Views"), + cssClass: 'toggle-more' + }); + } + + public run(event: any): TPromise { + this.showMenu(); + + return TPromise.as(true); + } +} + +export class CompositeOverflowActivityActionItem extends ActivityActionItem { + private name: string; + private cssClass: string; + private actions: Action[]; + + constructor( + action: ActivityAction, + private getOverflowingComposites: () => { id: string, name: string }[], + private getActiveCompositeId: () => string, + private getBadge: (compositeId: string) => IBadge, + private getCompositeOpenAction: (compositeId: string) => Action, + @IInstantiationService private instantiationService: IInstantiationService, + @IContextMenuService private contextMenuService: IContextMenuService, + @IThemeService themeService: IThemeService + ) { + super(action, null, themeService); + + this.cssClass = action.class; + this.name = action.label; + } + + public showMenu(): void { + if (this.actions) { + dispose(this.actions); + } + + this.actions = this.getActions(); + + this.contextMenuService.showContextMenu({ + getAnchor: () => this.builder.getHTMLElement(), + getActions: () => TPromise.as(this.actions), + onHide: () => dispose(this.actions) + }); + } + + private getActions(): Action[] { + return this.getOverflowingComposites().map(composite => { + const action = this.getCompositeOpenAction(composite.id); + action.radio = this.getActiveCompositeId() === action.id; + + const badge = this.getBadge(composite.id); + let suffix: string | number; + if (badge instanceof NumberBadge) { + suffix = badge.number; + } else if (badge instanceof TextBadge) { + suffix = badge.text; + } + + if (suffix) { + action.label = nls.localize('numberBadge', "{0} ({1})", composite.name, suffix); + } else { + action.label = composite.name; + } + + return action; + }); + } + + public dispose(): void { + super.dispose(); + + this.actions = dispose(this.actions); + } +} + +class ManageExtensionAction extends Action { + + constructor( + @ICommandService private commandService: ICommandService + ) { + super('activitybar.manage.extension', nls.localize('manageExtension', "Manage Extension")); + } + + public run(id: string): TPromise { + return this.commandService.executeCommand('_extensions.manage', id); + } +} + +export class CompositeActionItem extends ActivityActionItem { + + private static manageExtensionAction: ManageExtensionAction; + private static draggedCompositeId: string; + + private compositeActivity: IActivity; + private cssClass: string; + + constructor( + private compositeActivityAction: ActivityAction, + private toggleCompositePinnedAction: Action, + @IContextMenuService private contextMenuService: IContextMenuService, + @IActivityBarService private activityBarService: IActivityBarService, + @IKeybindingService private keybindingService: IKeybindingService, + @IInstantiationService instantiationService: IInstantiationService, + @IThemeService themeService: IThemeService + ) { + super(compositeActivityAction, { draggable: true }, themeService); + + this.cssClass = compositeActivityAction.class; + + if (!CompositeActionItem.manageExtensionAction) { + CompositeActionItem.manageExtensionAction = instantiationService.createInstance(ManageExtensionAction); + } + } + + protected get activity(): IActivity { + if (!this.compositeActivity) { + let activityName: string; + + const keybinding = this.getKeybindingLabel(this.compositeActivityAction.activity.id); + if (keybinding) { + activityName = nls.localize('titleKeybinding', "{0} ({1})", this.compositeActivityAction.activity.name, keybinding); + } else { + activityName = this.compositeActivityAction.activity.name; + } + + this.compositeActivity = { + id: this.compositeActivityAction.activity.id, + cssClass: this.cssClass, + name: activityName + }; + } + + return this.compositeActivity; + } + + private getKeybindingLabel(id: string): string { + const kb = this.keybindingService.lookupKeybinding(id); + if (kb) { + return kb.getLabel(); + } + + return null; + } + + public render(container: HTMLElement): void { + super.render(container); + + this.$container.on('contextmenu', e => { + dom.EventHelper.stop(e, true); + + this.showContextMenu(container); + }); + + // Allow to drag + this.$container.on(dom.EventType.DRAG_START, (e: DragEvent) => { + e.dataTransfer.effectAllowed = 'move'; + this.setDraggedComposite(this.activity.id); + + // Trigger the action even on drag start to prevent clicks from failing that started a drag + if (!this.getAction().checked) { + this.getAction().run(); + } + }); + + // Drag enter + let counter = 0; // see https://github.com/Microsoft/vscode/issues/14470 + this.$container.on(dom.EventType.DRAG_ENTER, (e: DragEvent) => { + const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); + if (draggedCompositeId && draggedCompositeId !== this.activity.id) { + counter++; + this.updateFromDragging(container, true); + } + }); + + // Drag leave + this.$container.on(dom.EventType.DRAG_LEAVE, (e: DragEvent) => { + const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); + if (draggedCompositeId) { + counter--; + if (counter === 0) { + this.updateFromDragging(container, false); + } + } + }); + + // Drag end + this.$container.on(dom.EventType.DRAG_END, (e: DragEvent) => { + const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); + if (draggedCompositeId) { + counter = 0; + this.updateFromDragging(container, false); + + CompositeActionItem.clearDraggedComposite(); + } + }); + + // Drop + this.$container.on(dom.EventType.DROP, (e: DragEvent) => { + dom.EventHelper.stop(e, true); + + const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); + if (draggedCompositeId && draggedCompositeId !== this.activity.id) { + this.updateFromDragging(container, false); + CompositeActionItem.clearDraggedComposite(); + + this.activityBarService.move(draggedCompositeId, this.activity.id); + } + }); + + // Activate on drag over to reveal targets + [this.$badge, this.$label].forEach(b => new DelayedDragHandler(b.getHTMLElement(), () => { + if (!CompositeActionItem.getDraggedCompositeId() && !this.getAction().checked) { + this.getAction().run(); + } + })); + + this.updateStyles(); + } + + private updateFromDragging(element: HTMLElement, isDragging: boolean): void { + const theme = this.themeService.getTheme(); + const dragBackground = theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND); + + element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : null; + } + + public static getDraggedCompositeId(): string { + return CompositeActionItem.draggedCompositeId; + } + + private setDraggedComposite(compositeId: string): void { + CompositeActionItem.draggedCompositeId = compositeId; + } + + public static clearDraggedComposite(): void { + CompositeActionItem.draggedCompositeId = void 0; + } + + private showContextMenu(container: HTMLElement): void { + const actions: Action[] = [this.toggleCompositePinnedAction]; + if ((this.compositeActivityAction.activity).extensionId) { + actions.push(new Separator()); + actions.push(CompositeActionItem.manageExtensionAction); + } + + const isPinned = this.activityBarService.isPinned(this.activity.id); + if (isPinned) { + this.toggleCompositePinnedAction.label = nls.localize('removeFromActivityBar', "Hide from Activity Bar"); + this.toggleCompositePinnedAction.checked = false; + } else { + this.toggleCompositePinnedAction.label = nls.localize('keepInActivityBar', "Keep in Activity Bar"); + } + + this.contextMenuService.showContextMenu({ + getAnchor: () => container, + getActionsContext: () => this.activity.id, + getActions: () => TPromise.as(actions) + }); + } + + public focus(): void { + this.$container.domFocus(); + } + + protected _updateClass(): void { + if (this.cssClass) { + this.$badge.removeClass(this.cssClass); + } + + this.cssClass = this.getAction().class; + this.$badge.addClass(this.cssClass); + } + + protected _updateChecked(): void { + if (this.getAction().checked) { + this.$container.addClass('checked'); + } else { + this.$container.removeClass('checked'); + } + } + + protected _updateEnabled(): void { + if (this.getAction().enabled) { + this.builder.removeClass('disabled'); + } else { + this.builder.addClass('disabled'); + } + } + + public dispose(): void { + super.dispose(); + + CompositeActionItem.clearDraggedComposite(); + + this.$label.destroy(); + } +} diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 8add806cda5..69b532ccb46 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -10,32 +10,23 @@ import nls = require('vs/nls'); import DOM = require('vs/base/browser/dom'); import { TPromise } from 'vs/base/common/winjs.base'; import { Builder, $ } from 'vs/base/browser/builder'; -import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { Action } from 'vs/base/common/actions'; -import { BaseActionItem, Separator, IBaseActionItemOptions } from 'vs/base/browser/ui/actionbar/actionbar'; +import { BaseActionItem, IBaseActionItemOptions } from 'vs/base/browser/ui/actionbar/actionbar'; import { IActivityBarService, ProgressBadge, TextBadge, NumberBadge, IconBadge, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; import Event, { Emitter } from 'vs/base/common/event'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IActivity, IGlobalActivity } from 'vs/workbench/common/activity'; import { dispose } from 'vs/base/common/lifecycle'; import { IViewletService, } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { IThemeService, ITheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; -import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; +import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; import { contrastBorder, activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -export interface IViewletActivity { - badge: IBadge; - clazz: string; -} - export class ActivityAction extends Action { private badge: IBadge; private _onDidChangeBadge = new Emitter(); @@ -83,15 +74,11 @@ export class ViewletActivityAction extends ActivityAction { private lastRun: number = 0; constructor( - private viewlet: ViewletDescriptor, + activity: IActivity, @IViewletService private viewletService: IViewletService, @IPartService private partService: IPartService ) { - super(viewlet); - } - - public get descriptor(): ViewletDescriptor { - return this.viewlet; + super(activity); } public run(event: any): TPromise { @@ -110,11 +97,11 @@ export class ViewletActivityAction extends ActivityAction { const activeViewlet = this.viewletService.getActiveViewlet(); // Hide sidebar if selected viewlet already visible - if (sideBarVisible && activeViewlet && activeViewlet.getId() === this.viewlet.id) { + if (sideBarVisible && activeViewlet && activeViewlet.getId() === this.activity.id) { return this.partService.setSideBarHidden(true); } - return this.viewletService.openViewlet(this.viewlet.id, true).then(() => this.activate()); + return this.viewletService.openViewlet(this.activity.id, true).then(() => this.activate()); } } @@ -283,322 +270,7 @@ export class ActivityActionItem extends BaseActionItem { } } -export class ViewletActionItem extends ActivityActionItem { - - private static manageExtensionAction: ManageExtensionAction; - private static toggleViewletPinnedAction: ToggleViewletPinnedAction; - private static draggedViewlet: ViewletDescriptor; - - private viewletActivity: IActivity; - private cssClass: string; - - constructor( - private action: ViewletActivityAction, - @IContextMenuService private contextMenuService: IContextMenuService, - @IActivityBarService private activityBarService: IActivityBarService, - @IKeybindingService private keybindingService: IKeybindingService, - @IInstantiationService instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService - ) { - super(action, { draggable: true }, themeService); - - this.cssClass = action.class; - - if (!ViewletActionItem.manageExtensionAction) { - ViewletActionItem.manageExtensionAction = instantiationService.createInstance(ManageExtensionAction); - } - - if (!ViewletActionItem.toggleViewletPinnedAction) { - ViewletActionItem.toggleViewletPinnedAction = instantiationService.createInstance(ToggleViewletPinnedAction, void 0); - } - } - - protected get activity(): IActivity { - if (!this.viewletActivity) { - let activityName: string; - - const keybinding = this.getKeybindingLabel(this.viewlet.id); - if (keybinding) { - activityName = nls.localize('titleKeybinding', "{0} ({1})", this.viewlet.name, keybinding); - } else { - activityName = this.viewlet.name; - } - - this.viewletActivity = { - id: this.viewlet.id, - cssClass: this.cssClass, - name: activityName - }; - } - - return this.viewletActivity; - } - - private get viewlet(): ViewletDescriptor { - return this.action.descriptor; - } - - private getKeybindingLabel(id: string): string { - const kb = this.keybindingService.lookupKeybinding(id); - if (kb) { - return kb.getLabel(); - } - - return null; - } - - public render(container: HTMLElement): void { - super.render(container); - - this.$container.on('contextmenu', e => { - DOM.EventHelper.stop(e, true); - - this.showContextMenu(container); - }); - - // Allow to drag - this.$container.on(DOM.EventType.DRAG_START, (e: DragEvent) => { - e.dataTransfer.effectAllowed = 'move'; - this.setDraggedViewlet(this.viewlet); - - // Trigger the action even on drag start to prevent clicks from failing that started a drag - if (!this.getAction().checked) { - this.getAction().run(); - } - }); - - // Drag enter - let counter = 0; // see https://github.com/Microsoft/vscode/issues/14470 - this.$container.on(DOM.EventType.DRAG_ENTER, (e: DragEvent) => { - const draggedViewlet = ViewletActionItem.getDraggedViewlet(); - if (draggedViewlet && draggedViewlet.id !== this.viewlet.id) { - counter++; - this.updateFromDragging(container, true); - } - }); - - // Drag leave - this.$container.on(DOM.EventType.DRAG_LEAVE, (e: DragEvent) => { - const draggedViewlet = ViewletActionItem.getDraggedViewlet(); - if (draggedViewlet) { - counter--; - if (counter === 0) { - this.updateFromDragging(container, false); - } - } - }); - - // Drag end - this.$container.on(DOM.EventType.DRAG_END, (e: DragEvent) => { - const draggedViewlet = ViewletActionItem.getDraggedViewlet(); - if (draggedViewlet) { - counter = 0; - this.updateFromDragging(container, false); - - ViewletActionItem.clearDraggedViewlet(); - } - }); - - // Drop - this.$container.on(DOM.EventType.DROP, (e: DragEvent) => { - DOM.EventHelper.stop(e, true); - - const draggedViewlet = ViewletActionItem.getDraggedViewlet(); - if (draggedViewlet && draggedViewlet.id !== this.viewlet.id) { - this.updateFromDragging(container, false); - ViewletActionItem.clearDraggedViewlet(); - - this.activityBarService.move(draggedViewlet.id, this.viewlet.id); - } - }); - - // Activate on drag over to reveal targets - [this.$badge, this.$label].forEach(b => new DelayedDragHandler(b.getHTMLElement(), () => { - if (!ViewletActionItem.getDraggedViewlet() && !this.getAction().checked) { - this.getAction().run(); - } - })); - - this.updateStyles(); - } - - private updateFromDragging(element: HTMLElement, isDragging: boolean): void { - const theme = this.themeService.getTheme(); - const dragBackground = theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND); - - element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : null; - } - - public static getDraggedViewlet(): ViewletDescriptor { - return ViewletActionItem.draggedViewlet; - } - - private setDraggedViewlet(viewlet: ViewletDescriptor): void { - ViewletActionItem.draggedViewlet = viewlet; - } - - public static clearDraggedViewlet(): void { - ViewletActionItem.draggedViewlet = void 0; - } - - private showContextMenu(container: HTMLElement): void { - const actions: Action[] = [ViewletActionItem.toggleViewletPinnedAction]; - if (this.viewlet.extensionId) { - actions.push(new Separator()); - actions.push(ViewletActionItem.manageExtensionAction); - } - - const isPinned = this.activityBarService.isPinned(this.viewlet.id); - if (isPinned) { - ViewletActionItem.toggleViewletPinnedAction.label = nls.localize('removeFromActivityBar', "Hide from Activity Bar"); - } else { - ViewletActionItem.toggleViewletPinnedAction.label = nls.localize('keepInActivityBar', "Keep in Activity Bar"); - } - - this.contextMenuService.showContextMenu({ - getAnchor: () => container, - getActionsContext: () => this.viewlet, - getActions: () => TPromise.as(actions) - }); - } - - public focus(): void { - this.$container.domFocus(); - } - - protected _updateClass(): void { - if (this.cssClass) { - this.$badge.removeClass(this.cssClass); - } - - this.cssClass = this.getAction().class; - this.$badge.addClass(this.cssClass); - } - - protected _updateChecked(): void { - if (this.getAction().checked) { - this.$container.addClass('checked'); - } else { - this.$container.removeClass('checked'); - } - } - - protected _updateEnabled(): void { - if (this.getAction().enabled) { - this.builder.removeClass('disabled'); - } else { - this.builder.addClass('disabled'); - } - } - - public dispose(): void { - super.dispose(); - - ViewletActionItem.clearDraggedViewlet(); - - this.$label.destroy(); - } -} - -export class ViewletOverflowActivityAction extends ActivityAction { - - constructor( - private showMenu: () => void - ) { - super({ - id: 'activitybar.additionalViewlets.action', - name: nls.localize('additionalViews', "Additional Views"), - cssClass: 'toggle-more' - }); - } - - public run(event: any): TPromise { - this.showMenu(); - - return TPromise.as(true); - } -} - -export class ViewletOverflowActivityActionItem extends ActivityActionItem { - private name: string; - private cssClass: string; - private actions: OpenViewletAction[]; - - constructor( - action: ActivityAction, - private getOverflowingViewlets: () => ViewletDescriptor[], - private getBadge: (viewlet: ViewletDescriptor) => IBadge, - @IInstantiationService private instantiationService: IInstantiationService, - @IViewletService private viewletService: IViewletService, - @IContextMenuService private contextMenuService: IContextMenuService, - @IThemeService themeService: IThemeService - ) { - super(action, null, themeService); - - this.cssClass = action.class; - this.name = action.label; - } - - public showMenu(): void { - if (this.actions) { - dispose(this.actions); - } - - this.actions = this.getActions(); - - this.contextMenuService.showContextMenu({ - getAnchor: () => this.builder.getHTMLElement(), - getActions: () => TPromise.as(this.actions), - onHide: () => dispose(this.actions) - }); - } - - private getActions(): OpenViewletAction[] { - const activeViewlet = this.viewletService.getActiveViewlet(); - - return this.getOverflowingViewlets().map(viewlet => { - const action = this.instantiationService.createInstance(OpenViewletAction, viewlet); - action.radio = activeViewlet && activeViewlet.getId() === action.id; - - const badge = this.getBadge(action.viewlet); - let suffix: string | number; - if (badge instanceof NumberBadge) { - suffix = badge.number; - } else if (badge instanceof TextBadge) { - suffix = badge.text; - } - - if (suffix) { - action.label = nls.localize('numberBadge', "{0} ({1})", action.viewlet.name, suffix); - } else { - action.label = action.viewlet.name; - } - - return action; - }); - } - - public dispose(): void { - super.dispose(); - - this.actions = dispose(this.actions); - } -} - -class ManageExtensionAction extends Action { - - constructor( - @ICommandService private commandService: ICommandService - ) { - super('activitybar.manage.extension', nls.localize('manageExtension', "Manage Extension")); - } - - public run(viewlet: ViewletDescriptor): TPromise { - return this.commandService.executeCommand('_extensions.manage', viewlet.extensionId); - } -} - -class OpenViewletAction extends Action { +export class OpenViewletAction extends Action { constructor( private _viewlet: ViewletDescriptor, @@ -608,41 +280,37 @@ class OpenViewletAction extends Action { super(_viewlet.id, _viewlet.name); } - public get viewlet(): ViewletDescriptor { - return this._viewlet; - } - public run(): TPromise { const sideBarVisible = this.partService.isVisible(Parts.SIDEBAR_PART); const activeViewlet = this.viewletService.getActiveViewlet(); // Hide sidebar if selected viewlet already visible - if (sideBarVisible && activeViewlet && activeViewlet.getId() === this.viewlet.id) { + if (sideBarVisible && activeViewlet && activeViewlet.getId() === this._viewlet.id) { return this.partService.setSideBarHidden(true); } - return this.viewletService.openViewlet(this.viewlet.id, true); + return this.viewletService.openViewlet(this._viewlet.id, true); } } export class ToggleViewletPinnedAction extends Action { constructor( - private viewlet: ViewletDescriptor, + private activity: IActivity, @IActivityBarService private activityBarService: IActivityBarService ) { - super('activitybar.show.toggleViewletPinned', viewlet ? viewlet.name : nls.localize('toggle', "Toggle View Pinned")); + super('activitybar.show.toggleViewletPinned', activity ? activity.name : nls.localize('toggle', "Toggle View Pinned")); - this.checked = this.viewlet && this.activityBarService.isPinned(this.viewlet.id); + this.checked = this.activity && this.activityBarService.isPinned(this.activity.id); } - public run(context?: ViewletDescriptor): TPromise { - const viewlet = this.viewlet || context; + public run(context: string): TPromise { + const id = this.activity ? this.activity.id : context; - if (this.activityBarService.isPinned(viewlet.id)) { - this.activityBarService.unpin(viewlet.id); + if (this.activityBarService.isPinned(id)) { + this.activityBarService.unpin(id); } else { - this.activityBarService.pin(viewlet.id); + this.activityBarService.pin(id); } return TPromise.as(true); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 5afcced6e5c..035d1ad57b9 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -8,25 +8,20 @@ import 'vs/css!./media/activitybarpart'; import nls = require('vs/nls'); import { TPromise } from 'vs/base/common/winjs.base'; -import DOM = require('vs/base/browser/dom'); -import * as arrays from 'vs/base/common/arrays'; import { illegalArgument } from 'vs/base/common/errors'; import { Builder, $, Dimension } from 'vs/base/browser/builder'; import { Action } from 'vs/base/common/actions'; -import { ActionsOrientation, ActionBar, IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; -import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; +import { ActionsOrientation, ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity'; import { Registry } from 'vs/platform/registry/common/platform'; import { Part } from 'vs/workbench/browser/part'; -import { IViewlet } from 'vs/workbench/common/viewlet'; -import { ToggleViewletPinnedAction, ViewletActivityAction, ActivityAction, GlobalActivityActionItem, ViewletActionItem, ViewletOverflowActivityAction, ViewletOverflowActivityActionItem, GlobalActivityAction, IViewletActivity } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { ToggleViewletPinnedAction, GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, OpenViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IActivityBarService, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; import { IPartService, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { Scope as MementoScope } from 'vs/workbench/common/memento'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -34,6 +29,7 @@ import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { CompositeBar } from 'vs/workbench/browser/compositeBar'; export class ActivitybarPart extends Part implements IActivityBarService { @@ -47,17 +43,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private globalActionBar: ActionBar; private globalActivityIdToActions: { [globalActivityId: string]: GlobalActivityAction; }; - private viewletSwitcherBar: ActionBar; - private viewletOverflowAction: ViewletOverflowActivityAction; - private viewletOverflowActionItem: ViewletOverflowActivityActionItem; - - private viewletIdToActions: { [viewletId: string]: ActivityAction; }; - private viewletIdToActionItems: { [viewletId: string]: IActionItem; }; - private viewletIdToActivityStack: { [viewletId: string]: IViewletActivity[]; }; - - private memento: object; - private pinnedViewlets: string[]; - private activeUnpinnedViewlet: ViewletDescriptor; + private compositeBar: CompositeBar; constructor( id: string, @@ -72,58 +58,32 @@ export class ActivitybarPart extends Part implements IActivityBarService { super(id, { hasTitle: false }, themeService); this.globalActivityIdToActions = Object.create(null); - - this.viewletIdToActionItems = Object.create(null); - this.viewletIdToActions = Object.create(null); - this.viewletIdToActivityStack = Object.create(null); - - this.memento = this.getMemento(this.storageService, MementoScope.GLOBAL); - - const pinnedViewlets = this.memento[ActivitybarPart.PINNED_VIEWLETS] as string[]; - - if (pinnedViewlets) { - this.pinnedViewlets = pinnedViewlets; - } else { - this.pinnedViewlets = this.viewletService.getViewlets().map(v => v.id); - } - + this.compositeBar = this.instantiationService.createInstance(CompositeBar, { + label: 'icon', + storageId: ActivitybarPart.PINNED_VIEWLETS, + orientation: ActionsOrientation.VERTICAL, + composites: this.viewletService.getViewlets(), + getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)), + getCompositePinnedAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletPinnedAction, this.viewletService.getViewlet(compositeId)), + getOpenCompositeAction: (compositeId: string) => this.instantiationService.createInstance(OpenViewletAction, this.viewletService.getViewlet(compositeId)) + }); this.registerListeners(); } private registerListeners(): void { // Activate viewlet action on opening of a viewlet - this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.onDidViewletOpen(viewlet))); + this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.compositeBar.activateComposite(viewlet.getId()))); // Deactivate viewlet action on close - this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.onDidViewletClose(viewlet))); - } - - private onDidViewletOpen(viewlet: IViewlet): void { - const id = viewlet.getId(); - - if (this.viewletIdToActions[id]) { - this.viewletIdToActions[id].activate(); - } - - const activeUnpinnedViewletShouldClose = this.activeUnpinnedViewlet && this.activeUnpinnedViewlet.id !== viewlet.getId(); - const activeUnpinnedViewletShouldShow = !this.getPinnedViewlets().some(v => v.id === viewlet.getId()); - if (activeUnpinnedViewletShouldShow || activeUnpinnedViewletShouldClose) { - this.updateViewletSwitcher(); - } - } - - private onDidViewletClose(viewlet: IViewlet): void { - const id = viewlet.getId(); - - if (this.viewletIdToActions[id]) { - this.viewletIdToActions[id].deactivate(); - } + this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId()))); + this.toUnbind.push(this.compositeBar.onDidDropComposite(data => this.move(data.compositeId, data.toCompositeId))); + this.toUnbind.push(this.compositeBar.onDidContextMenu(e => this.showContextMenu(e))); } public showActivity(viewletOrActionId: string, badge: IBadge, clazz?: string): IDisposable { if (this.viewletService.getViewlet(viewletOrActionId)) { - return this.showViewletActivity(viewletOrActionId, badge, clazz); + return this.compositeBar.showActivity(viewletOrActionId, badge, clazz); } return this.showGlobalActivity(viewletOrActionId, badge); @@ -144,94 +104,16 @@ export class ActivitybarPart extends Part implements IActivityBarService { return toDisposable(() => action.setBadge(undefined)); } - private showViewletActivity(viewletId: string, badge: IBadge, clazz?: string): IDisposable { - if (!badge) { - throw illegalArgument('badge'); - } - - const activity = { badge, clazz }; - const stack = this.viewletIdToActivityStack[viewletId] || (this.viewletIdToActivityStack[viewletId] = []); - stack.unshift(activity); - - this.updateViewletActivity(viewletId); - - return { - dispose: () => { - const stack = this.viewletIdToActivityStack[viewletId]; - if (!stack) { - return; - } - - const idx = stack.indexOf(activity); - if (idx < 0) { - return; - } - - stack.splice(idx, 1); - if (stack.length === 0) { - delete this.viewletIdToActivityStack[viewletId]; - } - - this.updateViewletActivity(viewletId); - } - }; - } - - private updateViewletActivity(viewletId: string) { - const action = this.viewletIdToActions[viewletId]; - if (!action) { - return; - } - - const stack = this.viewletIdToActivityStack[viewletId]; - - // reset - if (!stack || !stack.length) { - action.setBadge(undefined); - } - - // update - else { - const [{ badge, clazz }] = stack; - action.setBadge(badge); - if (clazz) { - action.class = clazz; - } - } - } - public createContentArea(parent: Builder): Builder { const $el = $(parent); const $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action - this.createViewletSwitcher($result.clone()); + this.compositeBar.create($result.clone().getHTMLElement()); // Top Actionbar with action items for each viewlet action this.createGlobalActivityActionBar($result.getHTMLElement()); - // Contextmenu for viewlets - $(parent).on('contextmenu', (e: MouseEvent) => { - DOM.EventHelper.stop(e, true); - - this.showContextMenu(e); - }, this.toUnbind); - - // Allow to drop at the end to move viewlet to the end - $(parent).on(DOM.EventType.DROP, (e: DragEvent) => { - const draggedViewlet = ViewletActionItem.getDraggedViewlet(); - if (draggedViewlet) { - DOM.EventHelper.stop(e, true); - - ViewletActionItem.clearDraggedViewlet(); - - const targetId = this.pinnedViewlets[this.pinnedViewlets.length - 1]; - if (targetId !== draggedViewlet.id) { - this.move(draggedViewlet.id, this.pinnedViewlets[this.pinnedViewlets.length - 1]); - } - } - }); - return $result; } @@ -268,20 +150,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { }); } - private createViewletSwitcher(div: Builder): void { - this.viewletSwitcherBar = new ActionBar(div, { - actionItemProvider: (action: Action) => action instanceof ViewletOverflowActivityAction ? this.viewletOverflowActionItem : this.viewletIdToActionItems[action.id], - orientation: ActionsOrientation.VERTICAL, - ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher"), - animated: false - }); - - this.updateViewletSwitcher(); - - // Update viewlet switcher when external viewlets become ready - this.extensionService.onReady().then(() => this.updateViewletSwitcher()); - } - private createGlobalActivityActionBar(container: HTMLElement): void { const activityRegistry = Registry.as(GlobalActivityExtensions); const descriptors = activityRegistry.getActivities(); @@ -302,152 +170,18 @@ export class ActivitybarPart extends Part implements IActivityBarService { }); } - private updateViewletSwitcher() { - if (!this.viewletSwitcherBar) { - return; // We have not been rendered yet so there is nothing to update. - } - - let viewletsToShow = this.getPinnedViewlets(); - - // Always show the active viewlet even if it is marked to be hidden - const activeViewlet = this.viewletService.getActiveViewlet(); - if (activeViewlet && !viewletsToShow.some(viewlet => viewlet.id === activeViewlet.getId())) { - this.activeUnpinnedViewlet = this.viewletService.getViewlet(activeViewlet.getId()); - viewletsToShow.push(this.activeUnpinnedViewlet); - } else { - this.activeUnpinnedViewlet = void 0; - } - - // Ensure we are not showing more viewlets than we have height for - let overflows = false; - if (this.dimension) { - let availableHeight = this.dimension.height; - if (this.globalActionBar) { - availableHeight -= (this.globalActionBar.items.length * ActivitybarPart.ACTIVITY_ACTION_HEIGHT); // adjust for global actions showing - } - - const maxVisible = Math.floor(availableHeight / ActivitybarPart.ACTIVITY_ACTION_HEIGHT); - overflows = viewletsToShow.length > maxVisible; - - if (overflows) { - viewletsToShow = viewletsToShow.slice(0, maxVisible - 1 /* make room for overflow action */); - } - } - - const visibleViewlets = Object.keys(this.viewletIdToActions); - const visibleViewletsChange = !arrays.equals(viewletsToShow.map(viewlet => viewlet.id), visibleViewlets); - - // Pull out overflow action if there is a viewlet change so that we can add it to the end later - if (this.viewletOverflowAction && visibleViewletsChange) { - this.viewletSwitcherBar.pull(this.viewletSwitcherBar.length() - 1); - - this.viewletOverflowAction.dispose(); - this.viewletOverflowAction = null; - - this.viewletOverflowActionItem.dispose(); - this.viewletOverflowActionItem = null; - } - - // Pull out viewlets that overflow or got hidden - const viewletIdsToShow = viewletsToShow.map(v => v.id); - visibleViewlets.forEach(viewletId => { - if (viewletIdsToShow.indexOf(viewletId) === -1) { - this.pullViewlet(viewletId); - } - }); - - // Built actions for viewlets to show - const newViewletsToShow = viewletsToShow - .filter(viewlet => !this.viewletIdToActions[viewlet.id]) - .map(viewlet => this.toAction(viewlet)); - - // Update when we have new viewlets to show - if (newViewletsToShow.length) { - - // Add to viewlet switcher - this.viewletSwitcherBar.push(newViewletsToShow, { label: true, icon: true }); - - // Make sure to activate the active one - const activeViewlet = this.viewletService.getActiveViewlet(); - if (activeViewlet) { - const activeViewletEntry = this.viewletIdToActions[activeViewlet.getId()]; - if (activeViewletEntry) { - activeViewletEntry.activate(); - } - } - - // Make sure to restore activity - Object.keys(this.viewletIdToActions).forEach(viewletId => { - this.updateViewletActivity(viewletId); - }); - } - - // Add overflow action as needed - if (visibleViewletsChange && overflows) { - this.viewletOverflowAction = this.instantiationService.createInstance(ViewletOverflowActivityAction, () => this.viewletOverflowActionItem.showMenu()); - this.viewletOverflowActionItem = this.instantiationService.createInstance(ViewletOverflowActivityActionItem, this.viewletOverflowAction, () => this.getOverflowingViewlets(), (viewlet: ViewletDescriptor) => this.viewletIdToActivityStack[viewlet.id] && this.viewletIdToActivityStack[viewlet.id][0].badge); - - this.viewletSwitcherBar.push(this.viewletOverflowAction, { label: true, icon: true }); - } - } - - private getOverflowingViewlets(): ViewletDescriptor[] { - const viewlets = this.getPinnedViewlets(); - if (this.activeUnpinnedViewlet) { - viewlets.push(this.activeUnpinnedViewlet); - } - const visibleViewlets = Object.keys(this.viewletIdToActions); - - return viewlets.filter(viewlet => visibleViewlets.indexOf(viewlet.id) === -1); - } - - private getVisibleViewlets(): ViewletDescriptor[] { - const viewlets = this.viewletService.getViewlets(); - const visibleViewlets = Object.keys(this.viewletIdToActions); - - return viewlets.filter(viewlet => visibleViewlets.indexOf(viewlet.id) >= 0); - } - - private getPinnedViewlets(): ViewletDescriptor[] { - return this.pinnedViewlets.map(viewletId => this.viewletService.getViewlet(viewletId)).filter(v => !!v); // ensure to remove those that might no longer exist - } - - private pullViewlet(viewletId: string): void { - const index = Object.keys(this.viewletIdToActions).indexOf(viewletId); - if (index >= 0) { - this.viewletSwitcherBar.pull(index); - - const action = this.viewletIdToActions[viewletId]; - action.dispose(); - delete this.viewletIdToActions[viewletId]; - - const actionItem = this.viewletIdToActionItems[action.id]; - actionItem.dispose(); - delete this.viewletIdToActionItems[action.id]; - } - } - - private toAction(viewlet: ViewletDescriptor): ActivityAction { - const action = this.instantiationService.createInstance(ViewletActivityAction, viewlet); - - this.viewletIdToActionItems[action.id] = this.instantiationService.createInstance(ViewletActionItem, action); - this.viewletIdToActions[viewlet.id] = action; - - return action; - } - public getPinned(): string[] { - return this.pinnedViewlets; + return this.viewletService.getViewlets().map(v => v.id).filter(id => this.compositeBar.isPinned(id));; } public unpin(viewletId: string): void { - if (!this.isPinned(viewletId)) { + if (!this.compositeBar.isPinned(viewletId)) { return; } const activeViewlet = this.viewletService.getActiveViewlet(); const defaultViewletId = this.viewletService.getDefaultViewletId(); - const visibleViewlets = this.getVisibleViewlets(); + const visibleViewlets = this.compositeBar.getVisibleComposites(); let unpinPromise: TPromise; @@ -459,7 +193,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Case: viewlet is not the default viewlet and default viewlet is still showing // Solv: we open the default viewlet - else if (defaultViewletId !== viewletId && this.isPinned(defaultViewletId)) { + else if (defaultViewletId !== viewletId && this.compositeBar.isPinned(defaultViewletId)) { unpinPromise = this.viewletService.openViewlet(defaultViewletId, true); } @@ -472,21 +206,17 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Case: we closed the default viewlet // Solv: we open the next visible viewlet from top else { - unpinPromise = this.viewletService.openViewlet(visibleViewlets.filter(viewlet => viewlet.id !== viewletId)[0].id, true); + unpinPromise = this.viewletService.openViewlet(visibleViewlets.filter(viewletId => viewletId !== viewletId)[0], true); } unpinPromise.then(() => { - // then remove from pinned and update switcher - const index = this.pinnedViewlets.indexOf(viewletId); - this.pinnedViewlets.splice(index, 1); - - this.updateViewletSwitcher(); + this.compositeBar.unpin(viewletId); }); } public isPinned(viewletId: string): boolean { - return this.pinnedViewlets.indexOf(viewletId) >= 0; + return this.compositeBar.isPinned(viewletId); } public pin(viewletId: string, update = true): void { @@ -495,41 +225,17 @@ export class ActivitybarPart extends Part implements IActivityBarService { } // first open that viewlet - this.viewletService.openViewlet(viewletId, true).then(() => { - - // then update - this.pinnedViewlets.push(viewletId); - this.pinnedViewlets = arrays.distinct(this.pinnedViewlets); - - if (update) { - this.updateViewletSwitcher(); - } - }); + this.viewletService.openViewlet(viewletId, true) + .then(() => this.compositeBar.pin(viewletId, update)); } public move(viewletId: string, toViewletId: string): void { - // Make sure a moved viewlet gets pinned if (!this.isPinned(viewletId)) { this.pin(viewletId, false /* defer update, we take care of it */); } - const fromIndex = this.pinnedViewlets.indexOf(viewletId); - const toIndex = this.pinnedViewlets.indexOf(toViewletId); - - this.pinnedViewlets.splice(fromIndex, 1); - this.pinnedViewlets.splice(toIndex, 0, viewletId); - - // Clear viewlets that are impacted by the move - const visibleViewlets = Object.keys(this.viewletIdToActions); - for (let i = Math.min(fromIndex, toIndex); i < visibleViewlets.length; i++) { - this.pullViewlet(visibleViewlets[i]); - } - - // timeout helps to prevent artifacts from showing up - setTimeout(() => { - this.updateViewletSwitcher(); - }, 0); + this.compositeBar.move(viewletId, toViewletId); } /** @@ -542,16 +248,20 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.dimension = sizes[1]; - // Update switcher to handle overflow issues - this.updateViewletSwitcher(); + let availableHeight = this.dimension.height; + if (this.globalActionBar) { + // adjust height for global actions showing + availableHeight -= (this.globalActionBar.items.length * ActivitybarPart.ACTIVITY_ACTION_HEIGHT); + } + this.compositeBar.layout(new Dimension(dimension.width, availableHeight)); return sizes; } public dispose(): void { - if (this.viewletSwitcherBar) { - this.viewletSwitcherBar.dispose(); - this.viewletSwitcherBar = null; + if (this.compositeBar) { + this.compositeBar.dispose(); + this.compositeBar = null; } if (this.globalActionBar) { @@ -565,9 +275,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { public shutdown(): void { // Persist Hidden State - this.memento[ActivitybarPart.PINNED_VIEWLETS] = this.pinnedViewlets; + this.compositeBar.store(); // Pass to super super.shutdown(); } -} \ No newline at end of file +} From f0f2c909d4c0e13bcceb1733d5304db84c33bb6b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 13 Oct 2017 16:23:02 +0200 Subject: [PATCH 083/394] Open full settings editor when clicking on settings.json in explorer (fixes #35579) --- .../browser/parts/editor/editorPart.ts | 57 ++++--- src/vs/workbench/common/editor.ts | 39 ++++- .../browser/preferences.contribution.ts | 4 +- .../preferences/browser/preferencesService.ts | 36 ++--- .../parts/preferences/common/preferences.ts | 14 +- .../common/preferencesContentProvider.ts | 82 ---------- .../common/preferencesContribution.ts | 148 ++++++++++++++++++ .../services/editor/browser/editorService.ts | 17 +- .../services/group/common/groupService.ts | 7 +- .../textfile/common/textFileEditorModel.ts | 1 - .../workbench/test/workbenchTestServices.ts | 8 +- 11 files changed, 267 insertions(+), 146 deletions(-) delete mode 100644 src/vs/workbench/parts/preferences/common/preferencesContentProvider.ts create mode 100644 src/vs/workbench/parts/preferences/common/preferencesContribution.ts diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index f64bf88b532..25fcf62c102 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -21,14 +21,14 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Scope as MementoScope } from 'vs/workbench/common/memento'; import { Part } from 'vs/workbench/browser/part'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import { EditorInput, EditorOptions, ConfirmResult, IWorkbenchEditorConfiguration, TextEditorOptions, SideBySideEditorInput, TextCompareEditorVisible, TEXT_DIFF_EDITOR_ID } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, ConfirmResult, IWorkbenchEditorConfiguration, TextEditorOptions, SideBySideEditorInput, TextCompareEditorVisible, TEXT_DIFF_EDITOR_ID, EditorOpeningEvent, IEditorOpeningEvent } from 'vs/workbench/common/editor'; import { EditorGroupsControl, Rochade, IEditorGroupsControl, ProgressState } from 'vs/workbench/browser/parts/editor/editorGroupsControl'; import { WorkbenchProgressService } from 'vs/workbench/services/progress/browser/progressService'; import { IEditorGroupService, GroupOrientation, GroupArrangement, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEditorPart } from 'vs/workbench/services/editor/browser/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { Position, POSITIONS, Direction } from 'vs/platform/editor/common/editor'; +import { Position, POSITIONS, Direction, IEditor } from 'vs/platform/editor/common/editor'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -99,6 +99,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService private revealIfOpen: boolean; private _onEditorsChanged: Emitter; + private _onEditorOpening: Emitter; private _onEditorsMoved: Emitter; private _onEditorOpenFail: Emitter; private _onGroupOrientationChanged: Emitter; @@ -132,6 +133,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService super(id, { hasTitle: false }, themeService); this._onEditorsChanged = new Emitter(); + this._onEditorOpening = new Emitter(); this._onEditorsMoved = new Emitter(); this._onEditorOpenFail = new Emitter(); this._onGroupOrientationChanged = new Emitter(); @@ -289,6 +291,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return this._onEditorsChanged.event; } + public get onEditorOpening(): Event { + return this._onEditorOpening.event; + } + public get onEditorsMoved(): Event { return this._onEditorsMoved.event; } @@ -309,12 +315,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return this.tabOptions; } - public openEditor(input: EditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; - public openEditor(input: EditorInput, options?: EditorOptions, position?: Position, ratio?: number[]): TPromise; - public openEditor(input: EditorInput, options?: EditorOptions, arg3?: any, ratio?: number[]): TPromise { - - // Normalize some values - if (!options) { options = null; } + public openEditor(input: EditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; + public openEditor(input: EditorInput, options?: EditorOptions, position?: Position, ratio?: number[]): TPromise; + public openEditor(input: EditorInput, options?: EditorOptions, arg3?: any, ratio?: number[]): TPromise { + if (!options) { + options = null; + } // Determine position to open editor in (one, two, three) const position = this.findPosition(input, options, arg3, ratio); @@ -329,6 +335,20 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return TPromise.as(null); } + // Editor opening event (can be prevented and overridden) + const event = new EditorOpeningEvent(input, position); + this._onEditorOpening.fire(event); + const prevented = event.isPrevented(); + if (prevented) { + return prevented(); + } + + // Open through UI + return this.doOpenEditor(position, input, options, ratio); + } + + private doOpenEditor(position: Position, input: EditorInput, options: EditorOptions, ratio: number[]): TPromise { + // We need an editor descriptor for the input const descriptor = Registry.as(EditorExtensions.Editors).getEditor(input); if (!descriptor) { @@ -345,12 +365,6 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.telemetryService.publicLog('workbenchSideEditorOpened', { position: position }); } - // Open through UI - return this.doOpenEditor(position, descriptor, input, options, ratio); - } - - private doOpenEditor(position: Position, descriptor: IEditorDescriptor, input: EditorInput, options: EditorOptions, ratio: number[]): TPromise { - // Update stacks: We do this early on before the UI is there because we want our stacks model to have // a consistent view of the editor world and updating it later async after the UI is there will cause // issues (e.g. when a closeEditor call is made that expects the openEditor call to have updated the @@ -1007,7 +1021,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService } } - public replaceEditors(editors: { toReplace: EditorInput, replaceWith: EditorInput, options?: EditorOptions }[], position?: Position): TPromise { + public replaceEditors(editors: { toReplace: EditorInput, replaceWith: EditorInput, options?: EditorOptions }[], position?: Position): TPromise { const activeReplacements: IEditorReplacement[] = []; const hiddenReplacements: IEditorReplacement[] = []; @@ -1066,9 +1080,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return res; } - public openEditors(editors: { input: EditorInput, position: Position, options?: EditorOptions }[]): TPromise { + public openEditors(editors: { input: EditorInput, position: Position, options?: EditorOptions }[]): TPromise { if (!editors.length) { - return TPromise.as([]); + return TPromise.as([]); } let activePosition: Position; @@ -1085,7 +1099,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return this.stacks.groups.some(g => g.count > 0); } - public restoreEditors(): TPromise { + public restoreEditors(): TPromise { const editors = this.stacks.groups.map((group, index) => { return { input: group.activeEditor, @@ -1095,7 +1109,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService }); if (!editors.length) { - return TPromise.as([]); + return TPromise.as([]); } let activePosition: Position; @@ -1108,7 +1122,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return this.doOpenEditors(editors, activePosition, editorState && editorState.ratio); } - private doOpenEditors(editors: { input: EditorInput, position: Position, options?: EditorOptions }[], activePosition?: number, ratio?: number[]): TPromise { + private doOpenEditors(editors: { input: EditorInput, position: Position, options?: EditorOptions }[], activePosition?: number, ratio?: number[]): TPromise { const positionOneEditors = editors.filter(e => e.position === Position.ONE); const positionTwoEditors = editors.filter(e => e.position === Position.TWO); const positionThreeEditors = editors.filter(e => e.position === Position.THREE); @@ -1155,7 +1169,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Open each input respecting the options. Since there can only be one active editor in each // position, we have to pick the first input from each position and add the others as inactive - const promises: TPromise[] = []; + const promises: TPromise[] = []; [positionOneEditors.shift(), positionTwoEditors.shift(), positionThreeEditors.shift()].forEach((editor, position) => { if (!editor) { return; // unused position @@ -1343,6 +1357,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Emitters this._onEditorsChanged.dispose(); + this._onEditorOpening.dispose(); this._onEditorsMoved.dispose(); this._onEditorOpenFail.dispose(); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 440ef0a6265..0e2582432d6 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -11,7 +11,7 @@ import types = require('vs/base/common/types'); import URI from 'vs/base/common/uri'; import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, IModel, ScrollType } from 'vs/editor/common/editorCommon'; -import { IEditorInput, IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceInput, Position, Verbosity } from 'vs/platform/editor/common/editor'; +import { IEditorInput, IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceInput, Position, Verbosity, IEditor as IBaseEditor } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -260,6 +260,43 @@ export abstract class EditorInput implements IEditorInput { } } +export interface IEditorOpeningEvent { + input: IEditorInput; + position: Position; + + /** + * Allows to prevent the opening of an editor by providing a callback + * that will be executed instead. By returning another editor promise + * it is possible to override the opening with another editor. It is ok + * to return a promise that resolves to NULL to prevent the opening + * altogether. + */ + prevent(callback: () => TPromise): void; +} + +export class EditorOpeningEvent { + private override: () => TPromise; + + constructor(private _editorInput: IEditorInput, private _position: Position) { + } + + public get input(): IEditorInput { + return this._editorInput; + } + + public get position(): Position { + return this._position; + } + + public prevent(callback: () => TPromise): void { + this.override = callback; + } + + public isPrevented(): () => TPromise { + return this.override; + } +} + export enum EncodingMode { /** diff --git a/src/vs/workbench/parts/preferences/browser/preferences.contribution.ts b/src/vs/workbench/parts/preferences/browser/preferences.contribution.ts index a2007eb7622..d24ed6250c3 100644 --- a/src/vs/workbench/parts/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/parts/preferences/browser/preferences.contribution.ts @@ -24,7 +24,7 @@ import { import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { PreferencesContentProvider } from 'vs/workbench/parts/preferences/common/preferencesContentProvider'; +import { PreferencesContribution } from 'vs/workbench/parts/preferences/common/preferencesContribution'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -257,7 +257,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(PreferencesContentProvider); +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(PreferencesContribution); CommandsRegistry.registerCommand(OPEN_FOLDER_SETTINGS_COMMAND, function (accessor: ServicesAccessor, args?: IWorkspaceFolder) { const preferencesService = accessor.get(IPreferencesService); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 5e5597721c6..eea8fda7f35 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -8,7 +8,6 @@ import * as network from 'vs/base/common/network'; import { TPromise } from 'vs/base/common/winjs.base'; import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; -import * as paths from 'vs/base/common/paths'; import { ResourceMap } from 'vs/base/common/map'; import * as labels from 'vs/base/common/labels'; import * as strings from 'vs/base/common/strings'; @@ -28,7 +27,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences'; +import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel, defaultKeybindingsContents, WorkspaceConfigModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DefaultPreferencesEditorInput, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor'; @@ -42,15 +41,6 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; - -interface IWorkbenchSettingsConfiguration { - workbench: { - settings: { - openDefaultSettings: boolean; - } - }; -} - const emptyEditableSettingsContent = '{\n}'; export class PreferencesService extends Disposable implements IPreferencesService { @@ -186,20 +176,20 @@ export class PreferencesService extends Disposable implements IPreferencesServic return TPromise.wrap>(null); } - openGlobalSettings(): TPromise { - return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource); + openGlobalSettings(position?: EditorPosition): TPromise { + return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource, position); } - openWorkspaceSettings(): TPromise { + openWorkspaceSettings(position?: EditorPosition): TPromise { if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('openFolderFirst', "Open a folder first to create workspace settings")); return TPromise.as(null); } - return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource); + return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource, position); } - openFolderSettings(folder: URI): TPromise { - return this.doOpenSettings(ConfigurationTarget.FOLDER, this.getEditableSettingsURI(ConfigurationTarget.FOLDER, folder)); + openFolderSettings(folder: URI, position?: EditorPosition): TPromise { + return this.doOpenSettings(ConfigurationTarget.FOLDER, this.getEditableSettingsURI(ConfigurationTarget.FOLDER, folder), position); } switchSettings(target: ConfigurationTarget, resource: URI): TPromise { @@ -259,17 +249,17 @@ export class PreferencesService extends Disposable implements IPreferencesServic }); } - private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI): TPromise { - const openDefaultSettings = !!this.configurationService.getConfiguration().workbench.settings.openDefaultSettings; + private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, position?: EditorPosition): TPromise { + const openDefaultSettings = !!this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value; return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource) .then(editableSettingsEditorInput => { if (openDefaultSettings) { const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(configurationTarget)); const preferencesEditorInput = new PreferencesEditorInput(this.getPreferencesEditorInputName(configurationTarget, resource), editableSettingsEditorInput.getDescription(), defaultPreferencesEditorInput, editableSettingsEditorInput); this.lastOpenedSettingsInput = preferencesEditorInput; - return this.editorService.openEditor(preferencesEditorInput, { pinned: true }); + return this.editorService.openEditor(preferencesEditorInput, { pinned: true }, position); } - return this.editorService.openEditor(editableSettingsEditorInput, { pinned: true }); + return this.editorService.openEditor(editableSettingsEditorInput, { pinned: true }, position); }); } @@ -325,10 +315,10 @@ export class PreferencesService extends Disposable implements IPreferencesServic return null; } const workspace = this.contextService.getWorkspace(); - return workspace.configuration || workspace.folders[0].toResource(paths.join('.vscode', 'settings.json')); + return workspace.configuration || workspace.folders[0].toResource(FOLDER_SETTINGS_PATH); case ConfigurationTarget.FOLDER: const folder = this.contextService.getWorkspaceFolder(resource); - return folder ? folder.toResource(paths.join('.vscode', 'settings.json')) : null; + return folder ? folder.toResource(FOLDER_SETTINGS_PATH) : null; } return null; } diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index 1b7200927c9..ac93b8ec775 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -8,11 +8,12 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IEditor } from 'vs/platform/editor/common/editor'; +import { IEditor, Position } from 'vs/platform/editor/common/editor'; import { IKeybindingItemEntry } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel'; import { IRange } from 'vs/editor/common/core/range'; import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { join } from 'vs/base/common/paths'; export interface ISettingsGroup { id: string; @@ -76,9 +77,9 @@ export interface IPreferencesService { resolveContent(uri: URI): TPromise; createPreferencesEditorModel(uri: URI): TPromise>; - openGlobalSettings(): TPromise; - openWorkspaceSettings(): TPromise; - openFolderSettings(folder: URI): TPromise; + openGlobalSettings(position?: Position): TPromise; + openWorkspaceSettings(position?: Position): TPromise; + openFolderSettings(folder: URI, position?: Position): TPromise; switchSettings(target: ConfigurationTarget, resource: URI): TPromise; openGlobalKeybindingSettings(textual: boolean): TPromise; @@ -130,4 +131,7 @@ export const KEYBINDINGS_EDITOR_COMMAND_REMOVE = 'keybindings.editor.removeKeybi export const KEYBINDINGS_EDITOR_COMMAND_RESET = 'keybindings.editor.resetKeybinding'; export const KEYBINDINGS_EDITOR_COMMAND_COPY = 'keybindings.editor.copyKeybindingEntry'; export const KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS = 'keybindings.editor.showConflicts'; -export const KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS = 'keybindings.editor.focusKeybindings'; \ No newline at end of file +export const KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS = 'keybindings.editor.focusKeybindings'; + +export const FOLDER_SETTINGS_PATH = join('.vscode', 'settings.json'); +export const DEFAULT_SETTINGS_EDITOR_SETTING = 'workbench.settings.openDefaultSettings'; \ No newline at end of file diff --git a/src/vs/workbench/parts/preferences/common/preferencesContentProvider.ts b/src/vs/workbench/parts/preferences/common/preferencesContentProvider.ts deleted file mode 100644 index 33141c96052..00000000000 --- a/src/vs/workbench/parts/preferences/common/preferencesContentProvider.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { IModelService } from 'vs/editor/common/services/modelService'; -import { IModeService } from 'vs/editor/common/services/modeService'; -import URI from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { IModel } from 'vs/editor/common/editorCommon'; -import JSONContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); -import { Registry } from 'vs/platform/registry/common/platform'; -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; -import { dispose } from 'vs/base/common/lifecycle'; - -const schemaRegistry = Registry.as(JSONContributionRegistry.Extensions.JSONContribution); - -export class PreferencesContentProvider implements IWorkbenchContribution { - - constructor( - @IModelService private modelService: IModelService, - @ITextModelService private textModelResolverService: ITextModelService, - @IPreferencesService private preferencesService: IPreferencesService, - @IModeService private modeService: IModeService - ) { - this.start(); - } - - public getId(): string { - return 'vs.contentprovider'; - } - - private start(): void { - - this.textModelResolverService.registerTextModelContentProvider('vscode', { - provideTextContent: (uri: URI): TPromise => { - if (uri.scheme !== 'vscode') { - return null; - } - if (uri.authority === 'schemas') { - const schemaModel = this.getSchemaModel(uri); - if (schemaModel) { - return TPromise.as(schemaModel); - } - } - return this.preferencesService.resolveContent(uri) - .then(content => { - if (content !== null && content !== void 0) { - let mode = this.modeService.getOrCreateMode('json'); - const model = this.modelService.createModel(content, mode, uri); - return TPromise.as(model); - } - return null; - }); - } - }); - } - - private getSchemaModel(uri: URI): IModel { - let schema = schemaRegistry.getSchemaContributions().schemas[uri.toString()]; - if (schema) { - const modelContent = JSON.stringify(schema); - const mode = this.modeService.getOrCreateMode('json'); - const model = this.modelService.createModel(modelContent, mode, uri); - - let disposables = []; - disposables.push(schemaRegistry.onDidChangeSchema(schemaUri => { - if (schemaUri === uri.toString()) { - schema = schemaRegistry.getSchemaContributions().schemas[uri.toString()]; - model.setValue(JSON.stringify(schema)); - } - })); - disposables.push(model.onWillDispose(() => dispose(disposables))); - - return model; - } - return null; - } -} diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts new file mode 100644 index 00000000000..ac091d532ca --- /dev/null +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -0,0 +1,148 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { IModelService } from 'vs/editor/common/services/modelService'; +import { IModeService } from 'vs/editor/common/services/modeService'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IModel } from 'vs/editor/common/editorCommon'; +import JSONContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IPreferencesService, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; +import { endsWith } from 'vs/base/common/strings'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IEditorOpeningEvent } from 'vs/workbench/common/editor'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; + +const schemaRegistry = Registry.as(JSONContributionRegistry.Extensions.JSONContribution); + +export class PreferencesContribution implements IWorkbenchContribution { + private editorOpeningListener: IDisposable; + private settingsListener: IDisposable; + + constructor( + @IModelService private modelService: IModelService, + @ITextModelService private textModelResolverService: ITextModelService, + @IPreferencesService private preferencesService: IPreferencesService, + @IModeService private modeService: IModeService, + @IEditorGroupService private editorGroupService: IEditorGroupService, + @IEnvironmentService private environmentService: IEnvironmentService, + @IWorkspaceContextService private workspaceService: IWorkspaceContextService, + @IConfigurationService private configurationService: IConfigurationService + ) { + this.settingsListener = this.configurationService.onDidUpdateConfiguration(() => this.handleSettingsEditorOverride()); + this.handleSettingsEditorOverride(); + + this.start(); + } + + private handleSettingsEditorOverride(): void { + + // dispose any old listener we had + this.editorOpeningListener = dispose(this.editorOpeningListener); + + // install editor opening listener unless user has disabled this + if (!!this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value) { + this.editorOpeningListener = this.editorGroupService.onEditorOpening(e => this.onEditorOpening(e)); + } + } + + private onEditorOpening(event: IEditorOpeningEvent): void { + const resource = event.input.getResource(); + if ( + !resource || resource.scheme !== 'file' || // require a file path opening + !endsWith(resource.fsPath, 'settings.json') || // file must end in settings.json + !this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value // user has not disabled default settings editor + ) { + return; + } + + // Global User Settings File + if (resource.fsPath === this.environmentService.appSettingsPath) { + return event.prevent(() => this.preferencesService.openGlobalSettings(event.position)); + } + + // Single Folder Workspace Settings File + const state = this.workspaceService.getWorkbenchState(); + if (state === WorkbenchState.FOLDER) { + const folders = this.workspaceService.getWorkspace().folders; + if (resource.fsPath === folders[0].toResource(FOLDER_SETTINGS_PATH).fsPath) { + return event.prevent(() => this.preferencesService.openWorkspaceSettings(event.position)); + } + } + + // Multi Folder Workspace Settings File + else if (state === WorkbenchState.WORKSPACE) { + const folders = this.workspaceService.getWorkspace().folders; + for (let i = 0; i < folders.length; i++) { + if (resource.fsPath === folders[i].toResource(FOLDER_SETTINGS_PATH).fsPath) { + return event.prevent(() => this.preferencesService.openFolderSettings(folders[i].uri, event.position)); + } + } + } + } + + public getId(): string { + return 'vs.contentprovider'; + } + + private start(): void { + + this.textModelResolverService.registerTextModelContentProvider('vscode', { + provideTextContent: (uri: URI): TPromise => { + if (uri.scheme !== 'vscode') { + return null; + } + if (uri.authority === 'schemas') { + const schemaModel = this.getSchemaModel(uri); + if (schemaModel) { + return TPromise.as(schemaModel); + } + } + return this.preferencesService.resolveContent(uri) + .then(content => { + if (content !== null && content !== void 0) { + let mode = this.modeService.getOrCreateMode('json'); + const model = this.modelService.createModel(content, mode, uri); + return TPromise.as(model); + } + return null; + }); + } + }); + } + + private getSchemaModel(uri: URI): IModel { + let schema = schemaRegistry.getSchemaContributions().schemas[uri.toString()]; + if (schema) { + const modelContent = JSON.stringify(schema); + const mode = this.modeService.getOrCreateMode('json'); + const model = this.modelService.createModel(modelContent, mode, uri); + + let disposables = []; + disposables.push(schemaRegistry.onDidChangeSchema(schemaUri => { + if (schemaUri === uri.toString()) { + schema = schemaRegistry.getSchemaContributions().schemas[uri.toString()]; + model.setValue(JSON.stringify(schema)); + } + })); + disposables.push(model.onWillDispose(() => dispose(disposables))); + + return model; + } + return null; + } + + public dispose(): void { + this.editorOpeningListener = dispose(this.editorOpeningListener); + this.settingsListener = dispose(this.settingsListener); + } +} diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index df0ec9e78cb..2cabe8935ca 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -9,7 +9,6 @@ import URI from 'vs/base/common/uri'; import network = require('vs/base/common/network'); import { Registry } from 'vs/platform/registry/common/platform'; import { basename, dirname } from 'vs/base/common/paths'; -import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { EditorInput, EditorOptions, TextEditorOptions, Extensions as EditorExtensions, SideBySideEditorInput, IFileEditorInput, IFileInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { IUntitledEditorService, UNTITLED_SCHEMA } from 'vs/workbench/services/untitled/common/untitledEditorService'; @@ -26,14 +25,14 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IFileService } from 'vs/platform/files/common/files'; export interface IEditorPart { - openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, sideBySide?: boolean): TPromise; - openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, position?: Position): TPromise; - openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions | ITextEditorOptions }[]): TPromise; - replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions | ITextEditorOptions }[], position?: Position): TPromise; + openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, sideBySide?: boolean): TPromise; + openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, position?: Position): TPromise; + openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions | ITextEditorOptions }[]): TPromise; + replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions | ITextEditorOptions }[], position?: Position): TPromise; closeEditor(position: Position, input: IEditorInput): TPromise; closeEditors(position: Position, filter?: { except?: IEditorInput, direction?: Direction, unmodifiedOnly?: boolean }): TPromise; closeAllEditors(except?: Position): TPromise; - getActiveEditor(): BaseEditor; + getActiveEditor(): IEditor; getVisibleEditors(): IEditor[]; getActiveEditorInput(): IEditorInput; } @@ -298,8 +297,8 @@ export class WorkbenchEditorService implements IWorkbenchEditorService { } export interface IEditorOpenHandler { - (input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; - (input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; + (input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; + (input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; } export interface IEditorCloseHandler { @@ -349,7 +348,7 @@ export class DelegatingWorkbenchEditorService extends WorkbenchEditorService { return handleOpen.then(editor => { if (editor) { - return TPromise.as(editor); + return TPromise.as(editor); } return super.doOpenEditor(input, options, arg3); diff --git a/src/vs/workbench/services/group/common/groupService.ts b/src/vs/workbench/services/group/common/groupService.ts index 12820ea98ea..1cdeceef1ff 100644 --- a/src/vs/workbench/services/group/common/groupService.ts +++ b/src/vs/workbench/services/group/common/groupService.ts @@ -7,7 +7,7 @@ import { createDecorator, ServiceIdentifier, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Position, IEditorInput } from 'vs/platform/editor/common/editor'; -import { IEditorStacksModel, IEditorGroup } from 'vs/workbench/common/editor'; +import { IEditorStacksModel, IEditorGroup, IEditorOpeningEvent } from 'vs/workbench/common/editor'; import Event from 'vs/base/common/event'; export enum GroupArrangement { @@ -45,6 +45,11 @@ export interface IEditorGroupService { */ onEditorsChanged: Event; + /** + * Emitted when an editor is opening. Allows to prevent/replace the opening via the event method. + */ + onEditorOpening: Event; + /** * Emitted when opening an editor fails. */ diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 3267637c435..90b96f490d5 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -765,7 +765,6 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return this.contextService.getWorkspace().folders.some(folder => { return paths.isEqualOrParent(this.resource.fsPath, path.join(folder.uri.fsPath, '.vscode')); }); - } private doTouch(): TPromise { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 18d72e4d754..b07ab0b7f95 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -15,7 +15,7 @@ import URI from 'vs/base/common/uri'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; -import { IEditorGroup, ConfirmResult } from 'vs/workbench/common/editor'; +import { IEditorGroup, ConfirmResult, IEditorOpeningEvent } from 'vs/workbench/common/editor'; import Event, { Emitter } from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -453,6 +453,7 @@ export class TestEditorGroupService implements IEditorGroupService { private stacksModel: EditorStacksModel; private _onEditorsChanged: Emitter; + private _onEditorOpening: Emitter; private _onEditorOpenFail: Emitter; private _onEditorsMoved: Emitter; private _onGroupOrientationChanged: Emitter; @@ -461,6 +462,7 @@ export class TestEditorGroupService implements IEditorGroupService { constructor(callback?: (method: string) => void) { this._onEditorsMoved = new Emitter(); this._onEditorsChanged = new Emitter(); + this._onEditorOpening = new Emitter(); this._onGroupOrientationChanged = new Emitter(); this._onEditorOpenFail = new Emitter(); this._onTabOptionsChanged = new Emitter(); @@ -487,6 +489,10 @@ export class TestEditorGroupService implements IEditorGroupService { return this._onEditorsChanged.event; } + public get onEditorOpening(): Event { + return this._onEditorOpening.event; + } + public get onEditorOpenFail(): Event { return this._onEditorOpenFail.event; } From 452e0ed86525decb6080736347a3b9486c6106be Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 Oct 2017 16:39:52 +0200 Subject: [PATCH 084/394] Reduce usage of `Interval` --- src/vs/editor/common/model/intervalTree.ts | 4 ++-- src/vs/editor/test/common/model/intervalTree.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index d89868bc61a..2744c6416bf 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -120,12 +120,12 @@ export class IntervalTree { this.root = SENTINEL; } - public intervalSearch(interval: Interval, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { + public intervalSearch(start: number, end: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { if (this.root === SENTINEL) { return []; } let result: IntervalNode[] = []; - intervalSearchRecursive(this.root, 0, interval.start, interval.end, filterOwnerId, filterOutValidation, cachedVersionId, result); + intervalSearchRecursive(this.root, 0, start, end, filterOwnerId, filterOutValidation, cachedVersionId, result); return result; } diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index 7df8a19e0e3..cc12118fee5 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -83,7 +83,7 @@ suite('IntervalTree', () => { this._treeNodes[op.id] = null; this._oracleNodes[op.id] = null; } else { - let actualNodes = this._tree.intervalSearch(new Interval(op.begin, op.end), 0, false, 0); + let actualNodes = this._tree.intervalSearch(op.begin, op.end, 0, false, 0); let actual = actualNodes.map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd)); let expected = this._oracle.search(new Interval(op.begin, op.end)); assert.deepEqual(actual, expected); @@ -426,7 +426,7 @@ suite('IntervalTree', () => { const T = createCormenTree(); function assertIntervalSearch(start: number, end: number, expected: [number, number][]): void { - let actualNodes = T.intervalSearch(new Interval(start, end), 0, false, 0); + let actualNodes = T.intervalSearch(start, end, 0, false, 0); let actual = actualNodes.map((n) => <[number, number]>[n.cachedAbsoluteStart, n.cachedAbsoluteEnd]); assert.deepEqual(actual, expected); } From 90ca93fdbe6f850dcd692df9cf694e913f6764a8 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Fri, 13 Oct 2017 07:46:56 -0700 Subject: [PATCH 085/394] More tests (#35236) --- .../services/search/test/node/search.test.ts | 47 +++++++++++++++++++ .../search/test/node/searchService.test.ts | 46 +++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index f7fbebd6835..c2ce634c8d1 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -220,6 +220,53 @@ suite('FileSearchEngine', () => { }); }); + test('Files: multiroot with includePattern and maxResults', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: MULTIROOT_QUERIES, + maxResults: 1, + includePattern: { + '*.txt': true, + '*.js': true + }, + useRipgrep: true + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error, complete) => { + assert.ok(!error); + assert.equal(count, 1); + done(); + }); + }); + + test('Files: multiroot with includePattern and exists', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: MULTIROOT_QUERIES, + exists: true, + includePattern: { + '*.txt': true, + '*.js': true + }, + useRipgrep: true + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error, complete) => { + assert.ok(!error); + assert.equal(count, 0); + assert.ok(complete.limitHit); + done(); + }); + }); + test('Files: NPE (CamelCase)', function (done: () => void) { let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, diff --git a/src/vs/workbench/services/search/test/node/searchService.test.ts b/src/vs/workbench/services/search/test/node/searchService.test.ts index 36935227c65..7fd40591eef 100644 --- a/src/vs/workbench/services/search/test/node/searchService.test.ts +++ b/src/vs/workbench/services/search/test/node/searchService.test.ts @@ -7,9 +7,10 @@ import * as assert from 'assert'; import { normalize } from 'path'; +import path = require('path'); import { IProgress, IUncachedSearchStats } from 'vs/platform/search/common/search'; -import { ISearchEngine, IRawSearch, IRawFileMatch, ISerializedFileMatch, ISerializedSearchComplete } from 'vs/workbench/services/search/node/search'; +import { ISearchEngine, IRawSearch, IRawFileMatch, ISerializedFileMatch, ISerializedSearchComplete, IFolderSearch } from 'vs/workbench/services/search/node/search'; import { SearchService as RawSearchService } from 'vs/workbench/services/search/node/rawSearchService'; import { DiskSearch } from 'vs/workbench/services/search/node/searchService'; @@ -17,6 +18,12 @@ const TEST_FOLDER_QUERIES = [ { folder: normalize('/some/where') } ]; +const TEST_FIXTURES = path.normalize(require.toUrl('./fixtures')); +const MULTIROOT_QUERIES: IFolderSearch[] = [ + { folder: path.join(TEST_FIXTURES, 'examples') }, + { folder: path.join(TEST_FIXTURES, 'more') } +]; + const stats: IUncachedSearchStats = { fromCache: false, resultCount: 4, @@ -143,6 +150,43 @@ suite('SearchService', () => { }); }); + test('Multi-root with include pattern and maxResults', function () { + const service = new RawSearchService(); + + const query: IRawSearch = { + folderQueries: MULTIROOT_QUERIES, + maxResults: 1, + includePattern: { + '*.txt': true, + '*.js': true + }, + }; + + return DiskSearch.collectResults(service.fileSearch(query)) + .then(result => { + assert.strictEqual(result.results.length, 1, 'Result'); + }); + }); + + test('Multi-root with include pattern and exists', function () { + const service = new RawSearchService(); + + const query: IRawSearch = { + folderQueries: MULTIROOT_QUERIES, + exists: true, + includePattern: { + '*.txt': true, + '*.js': true + }, + }; + + return DiskSearch.collectResults(service.fileSearch(query)) + .then(result => { + assert.strictEqual(result.results.length, 0, 'Result'); + assert.ok(result.limitHit); + }); + }); + test('Sorted results', function () { const paths = ['bab', 'bbc', 'abb']; const matches: IRawFileMatch[] = paths.map(relativePath => ({ From b86c935551664d84b2b31aa1aeb885c3c689fabe Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Fri, 13 Oct 2017 07:58:08 -0700 Subject: [PATCH 086/394] guard against empty tooltip fixes JS error "Cannot read property 'charAt' of undefined" --- .../workbench/parts/scm/electron-browser/scmFileDecorations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index dea57c82381..97c1c66a212 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -62,7 +62,7 @@ class SCMDecorationsProvider implements IDecorationsProvider { provideDecorations(uri: URI): IResourceDecorationData { const resource = this._data.get(uri.toString()); - if (!resource || !resource.decorations.color) { + if (!resource || !resource.decorations.color || !resource.decorations.tooltip) { return undefined; } return { From d17e3ddbc364e43fba80f526b0a3d140e0863bd9 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 13 Oct 2017 17:20:15 +0200 Subject: [PATCH 087/394] Write tests for ConfigurationModel --- .../configuration/common/configuration.ts | 24 ++ .../common/configurationModels.ts | 51 ++- .../test/common/configuration.model.test.ts | 87 ---- .../test/common/configuration.test.ts | 89 +++- .../test/common/configurationModel.test.ts | 148 ------- .../test/common/configurationModels.test.ts | 399 ++++++++++++++++++ .../node/configurationService.ts | 4 +- 7 files changed, 546 insertions(+), 256 deletions(-) delete mode 100644 src/vs/platform/configuration/test/common/configuration.model.test.ts delete mode 100644 src/vs/platform/configuration/test/common/configurationModel.test.ts create mode 100644 src/vs/platform/configuration/test/common/configurationModels.test.ts diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index a2132efea12..8a1daa65929 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -151,6 +151,30 @@ export function addToValueTree(settingsTreeRoot: any, key: string, value: any, c } } +export function removeFromValueTree(valueTree: any, key: string): void { + const segments = key.split('.'); + doRemoveFromValueTree(valueTree, segments); +} + +function doRemoveFromValueTree(valueTree: any, segments: string[]): void { + const first = segments.shift(); + if (segments.length === 0) { + // Reached last segment + delete valueTree[first]; + return; + } + + if (Object.keys(valueTree).indexOf(first) !== -1) { + const value = valueTree[first]; + if (typeof value === 'object' && !Array.isArray(value)) { + doRemoveFromValueTree(value, segments); + if (Object.keys(value).length === 0) { + delete valueTree[first]; + } + } + } +} + /** * A helper function to get the configuration value with a specific settings path (e.g. config.some.setting) */ diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 7e5751fcdd4..7acaca42472 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -11,7 +11,7 @@ import * as objects from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree } from 'vs/platform/configuration/common/configuration'; import { Workspace } from 'vs/platform/workspace/common/workspace'; export class ConfigurationModel implements IConfiguraionModel { @@ -36,9 +36,13 @@ export class ConfigurationModel implements IConfiguraionModel { } public setValue(key: string, value: any) { + this.addKey(key); addToValueTree(this._contents, key, value, e => { throw new Error(e); }); - if (this._keys.indexOf(key) === -1) { - this._keys.push(key); + } + + public removeValue(key: string): void { + if (this.removeKey(key)) { + removeFromValueTree(this._contents, key); } } @@ -51,33 +55,25 @@ export class ConfigurationModel implements IConfiguraionModel { addToValueTree(override.contents, key, value, e => { throw new Error(e); }); } - public removeValue(key: string) { - // Remove key from the value tree - const index = this._keys.indexOf(key); - if (index !== -1) { - this._keys.splice(index, 1); - } - } - public override(identifier: string): ConfigurationModel { const overrideContents = this.getContentsForOverrideIdentifer(identifier); - if (!overrideContents) { - // If there are no overrides, use base contents + if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) { + // If there are no valid overrides, use base contents return new ConfigurationModel(this._contents); } let contents = {}; - for (const key of Object.keys(this._contents)) { + for (const key of arrays.distinct([...Object.keys(this._contents), ...Object.keys(overrideContents)])) { let contentsForKey = this._contents[key]; let overrideContentsForKey = overrideContents[key]; - // If there are override contents for the key clone and merge otherwise use base contents + // If there are override contents for the key, clone and merge otherwise use base contents if (overrideContentsForKey) { - // Clone and merge only if base contents is of type object otherwise just override - if (typeof contentsForKey === 'object') { - contentsForKey = objects.clone(contents[key]); + // Clone and merge only if base contents and override contents are of type object otherwise just override + if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') { + contentsForKey = objects.clone(contentsForKey); merge(contentsForKey, overrideContentsForKey, true); } else { contentsForKey = overrideContentsForKey; @@ -118,6 +114,25 @@ export class ConfigurationModel implements IConfiguraionModel { } return null; } + + private addKey(key: string): void { + let index = this._keys.length; + for (let i = 0; i < index; i++) { + if (key.indexOf(this._keys[i]) === 0) { + index = i; + } + } + this._keys.splice(index, 1, key); + } + + private removeKey(key: string): boolean { + let index = this._keys.indexOf(key); + if (index !== -1) { + this._keys.splice(index, 1); + return true; + } + return false; + } } export class DefaultConfigurationModel extends ConfigurationModel { diff --git a/src/vs/platform/configuration/test/common/configuration.model.test.ts b/src/vs/platform/configuration/test/common/configuration.model.test.ts deleted file mode 100644 index ea0266bd500..00000000000 --- a/src/vs/platform/configuration/test/common/configuration.model.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as assert from 'assert'; -import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; -import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { Registry } from 'vs/platform/registry/common/platform'; - -suite('Configuration', () => { - - suiteSetup(() => { - Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': 'a', - 'order': 1, - 'title': 'a', - 'type': 'object', - 'properties': { - 'a': { - 'description': 'a', - 'type': 'boolean', - 'default': true, - 'overridable': true - } - } - }); - }); - - test('simple merge', () => { - let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); - let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 }); - }); - - test('recursive merge', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); - }); - - test('simple merge overrides', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': 2 } }]); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'b': 2 } }]); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); - assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': 2, 'b': 2 } }]); - }); - - test('recursive merge overrides', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); - assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': { 'd': 1, 'e': 2 } } }]); - }); - - test('merge ignore keys', () => { - let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); - let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); - let result = base.merge(add); - assert.deepEqual(result.keys, []); - }); - - test('Test contents while getting an existing property', () => { - let testObject = new ConfigurationModel({ 'a': 1 }); - assert.deepEqual(testObject.getSectionContents('a'), 1); - - testObject = new ConfigurationModel({ 'a': { 'b': 1 } }); - assert.deepEqual(testObject.getSectionContents('a'), { 'b': 1 }); - }); - - test('Test contents are undefined for non existing properties', () => { - const testObject = new ConfigurationModel({ awesome: true }); - - assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); - }); - - test('Test override gives all content merged with overrides', () => { - const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, [], [{ identifiers: ['b'], contents: { 'a': 2 } }]); - - assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1 }); - }); -}); \ No newline at end of file diff --git a/src/vs/platform/configuration/test/common/configuration.test.ts b/src/vs/platform/configuration/test/common/configuration.test.ts index 11024298132..456df853e01 100644 --- a/src/vs/platform/configuration/test/common/configuration.test.ts +++ b/src/vs/platform/configuration/test/common/configuration.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { merge } from 'vs/platform/configuration/common/configuration'; +import { merge, removeFromValueTree } from 'vs/platform/configuration/common/configuration'; suite('Configuration', () => { @@ -18,5 +18,92 @@ suite('Configuration', () => { assert.deepEqual(base, { 'a': 1, 'b': 2, 'c': 4 }); }); + test('removeFromValueTree: remove a non existing key', () => { + let target = { 'a': { 'b': 2 } }; + + removeFromValueTree(target, 'c'); + + assert.deepEqual(target, { 'a': { 'b': 2 } }); + }); + + test('removeFromValueTree: remove a multi segmented key from an object that has only sub sections of the key', () => { + let target = { 'a': { 'b': 2 } }; + + removeFromValueTree(target, 'a.b.c'); + + assert.deepEqual(target, { 'a': { 'b': 2 } }); + }); + + test('removeFromValueTree: remove a single segemented key', () => { + let target = { 'a': 1 }; + + removeFromValueTree(target, 'a'); + + assert.deepEqual(target, {}); + }); + + test('removeFromValueTree: remove a single segemented key when its value is undefined', () => { + let target = { 'a': void 0 }; + + removeFromValueTree(target, 'a'); + + assert.deepEqual(target, {}); + }); + + test('removeFromValueTree: remove a multi segemented key when its value is undefined', () => { + let target = { 'a': { 'b': 1 } }; + + removeFromValueTree(target, 'a.b'); + + assert.deepEqual(target, {}); + }); + + test('removeFromValueTree: remove a multi segemented key when its value is array', () => { + let target = { 'a': { 'b': [1] } }; + + removeFromValueTree(target, 'a.b'); + + assert.deepEqual(target, {}); + }); + + test('removeFromValueTree: remove a multi segemented key first segment value is array', () => { + let target = { 'a': [1] }; + + removeFromValueTree(target, 'a.0'); + + assert.deepEqual(target, { 'a': [1] }); + }); + + test('removeFromValueTree: remove when key is the first segmenet', () => { + let target = { 'a': { 'b': 1 } }; + + removeFromValueTree(target, 'a'); + + assert.deepEqual(target, {}); + }); + + test('removeFromValueTree: remove a multi segemented key when the first node has more values', () => { + let target = { 'a': { 'b': { 'c': 1 }, 'd': 1 } }; + + removeFromValueTree(target, 'a.b.c'); + + assert.deepEqual(target, { 'a': { 'd': 1 } }); + }); + + test('removeFromValueTree: remove a multi segemented key when in between node has more values', () => { + let target = { 'a': { 'b': { 'c': { 'd': 1 }, 'd': 1 } } }; + + removeFromValueTree(target, 'a.b.c.d'); + + assert.deepEqual(target, { 'a': { 'b': { 'd': 1 } } }); + }); + + test('removeFromValueTree: remove a multi segemented key when the last but one node has more values', () => { + let target = { 'a': { 'b': { 'c': 1, 'd': 1 } } }; + + removeFromValueTree(target, 'a.b.c'); + + assert.deepEqual(target, { 'a': { 'b': { 'd': 1 } } }); + }); }); \ No newline at end of file diff --git a/src/vs/platform/configuration/test/common/configurationModel.test.ts b/src/vs/platform/configuration/test/common/configurationModel.test.ts deleted file mode 100644 index b79b8cbadcf..00000000000 --- a/src/vs/platform/configuration/test/common/configurationModel.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as assert from 'assert'; -import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; -import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { Registry } from 'vs/platform/registry/common/platform'; - -suite('Configuration', () => { - - suiteSetup(() => { - Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': 'a', - 'order': 1, - 'title': 'a', - 'type': 'object', - 'properties': { - 'a': { - 'description': 'a', - 'type': 'boolean', - 'default': true, - 'overridable': true - } - } - }); - }); - - test('simple merge using models', () => { - let base = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 })); - let add = new CustomConfigurationModel(JSON.stringify({ 'a': 3, 'c': 4 })); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 }); - }); - - test('simple merge with an undefined contents', () => { - let base = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 })); - let add = new CustomConfigurationModel(null); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': 1, 'b': 2 }); - - base = new CustomConfigurationModel(null); - add = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 })); - result = base.merge(add); - assert.deepEqual(result.contents, { 'a': 1, 'b': 2 }); - - base = new CustomConfigurationModel(null); - add = new CustomConfigurationModel(null); - result = base.merge(add); - assert.deepEqual(result.contents, {}); - }); - - test('Recursive merge using config models', () => { - let base = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } })); - let add = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 2 } })); - let result = base.merge(add); - assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); - }); - - test('Test contents while getting an existing property', () => { - let testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1 })); - assert.deepEqual(testObject.getSectionContents('a'), 1); - - testObject = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } })); - assert.deepEqual(testObject.getSectionContents('a'), { 'b': 1 }); - }); - - test('Test contents are undefined for non existing properties', () => { - const testObject = new CustomConfigurationModel(JSON.stringify({ - awesome: true - })); - - assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); - }); - - test('Test contents are undefined for undefined config', () => { - const testObject = new CustomConfigurationModel(null); - - assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); - }); - - test('Test configWithOverrides gives all content merged with overrides', () => { - const testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'c': 1, '[b]': { 'a': 2 } })); - - assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1, '[b]': { 'a': 2 } }); - }); - - test('Test configWithOverrides gives empty contents', () => { - const testObject = new CustomConfigurationModel(null); - - assert.deepEqual(testObject.override('b').contents, {}); - }); - - test('Test update with empty data', () => { - const testObject = new CustomConfigurationModel(); - testObject.update(''); - - assert.deepEqual(testObject.contents, {}); - assert.deepEqual(testObject.keys, []); - - testObject.update(null); - - assert.deepEqual(testObject.contents, {}); - assert.deepEqual(testObject.keys, []); - - testObject.update(undefined); - - assert.deepEqual(testObject.contents, {}); - assert.deepEqual(testObject.keys, []); - }); - - test('Test registering the same property again', () => { - Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': 'a', - 'order': 1, - 'title': 'a', - 'type': 'object', - 'properties': { - 'a': { - 'description': 'a', - 'type': 'boolean', - 'default': false, - } - } - }); - assert.equal(true, new DefaultConfigurationModel().getSectionContents('a')); - }); - - test('Test registering the language property', () => { - Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': '[a]', - 'order': 1, - 'title': 'a', - 'type': 'object', - 'properties': { - '[a]': { - 'description': 'a', - 'type': 'boolean', - 'default': false, - } - } - }); - assert.equal(undefined, new DefaultConfigurationModel().getSectionContents('[a]')); - }); - -}); \ No newline at end of file diff --git a/src/vs/platform/configuration/test/common/configurationModels.test.ts b/src/vs/platform/configuration/test/common/configurationModels.test.ts new file mode 100644 index 00000000000..b4cc2a1d476 --- /dev/null +++ b/src/vs/platform/configuration/test/common/configurationModels.test.ts @@ -0,0 +1,399 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import { ConfigurationModel, CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; +import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; +import { Registry } from 'vs/platform/registry/common/platform'; + +suite('ConfigurationModel', () => { + + test('setValue for a key that has no sections and not defined', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1 } }, ['a.b']); + + testObject.setValue('f', 1); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 1 }, 'f': 1 }); + assert.deepEqual(testObject.keys, ['a.b', 'f']); + }); + + test('setValue for a key that has no sections and defined', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, ['a.b', 'f']); + + testObject.setValue('f', 3); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 1 }, 'f': 3 }); + assert.deepEqual(testObject.keys, ['a.b', 'f']); + }); + + test('setValue for a key that has sections and not defined', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, ['a.b', 'f']); + + testObject.setValue('b.c', 1); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 1 }, 'b': { 'c': 1 }, 'f': 1 }); + assert.deepEqual(testObject.keys, ['a.b', 'f', 'b.c']); + }); + + test('setValue for a key that has sections and defined', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1 }, 'b': { 'c': 1 }, 'f': 1 }, ['a.b', 'b.c', 'f']); + + testObject.setValue('b.c', 3); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 1 }, 'b': { 'c': 3 }, 'f': 1 }); + assert.deepEqual(testObject.keys, ['a.b', 'b.c', 'f']); + }); + + test('setValue for a key that has sections and sub section not defined', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, ['a.b', 'f']); + + testObject.setValue('a.c', 1); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 1, 'c': 1 }, 'f': 1 }); + assert.deepEqual(testObject.keys, ['a.b', 'f', 'a.c']); + }); + + test('setValue for a key that has sections and sub section defined', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1, 'c': 1 }, 'f': 1 }, ['a.b', 'a.c', 'f']); + + testObject.setValue('a.c', 3); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 1, 'c': 3 }, 'f': 1 }); + assert.deepEqual(testObject.keys, ['a.b', 'a.c', 'f']); + }); + + test('setValue for a key that has sections and last section is added', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': {} }, 'f': 1 }, ['a.b', 'f']); + + testObject.setValue('a.b.c', 1); + + assert.deepEqual(testObject.contents, { 'a': { 'b': { 'c': 1 } }, 'f': 1 }); + assert.deepEqual(testObject.keys, ['a.b.c', 'f']); + }); + + test('removeValue: remove a non existing key', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 2 } }, ['a.b']); + + testObject.removeValue('a.b.c'); + + assert.deepEqual(testObject.contents, { 'a': { 'b': 2 } }); + assert.deepEqual(testObject.keys, ['a.b']); + }); + + test('removeValue: remove a single segemented key', () => { + let testObject = new ConfigurationModel({ 'a': 1 }, ['a']); + + testObject.removeValue('a'); + + assert.deepEqual(testObject.contents, {}); + assert.deepEqual(testObject.keys, []); + }); + + test('removeValue: remove a multi segemented key', () => { + let testObject = new ConfigurationModel({ 'a': { 'b': 1 } }, ['a.b']); + + testObject.removeValue('a.b'); + + assert.deepEqual(testObject.contents, {}); + assert.deepEqual(testObject.keys, []); + }); + + test('setValueInOverrides adds to overrides if does not exist', () => { + let testObject = new ConfigurationModel({ 'a': 1, 'b': 1 }, ['a']); + + testObject.setValueInOverrides('or', 'a', 2); + + assert.deepEqual(testObject.overrides[0].contents, { 'a': 2 }); + assert.deepEqual(testObject.override('or').contents, { 'a': 2, 'b': 1 }); + }); + + test('setValueInOverrides adds to overrides if exist', () => { + let testObject = new ConfigurationModel({ 'a': 1, 'b': 1 }, ['a'], [{ identifiers: ['or'], contents: { 'a': 2 } }]); + + testObject.setValueInOverrides('or', 'a', 3); + + assert.deepEqual(testObject.overrides[0].contents, { 'a': 3 }); + assert.deepEqual(testObject.override('or').contents, { 'a': 3, 'b': 1 }); + }); + + test('setValueInOverrides adds a nested key to overrides if exist', () => { + let testObject = new ConfigurationModel({ 'a': 1, 'b': 1 }, ['a'], [{ identifiers: ['or'], contents: { 'a': { 'c': 1 } } }]); + + testObject.setValueInOverrides('or', 'a.c', 2); + + assert.deepEqual(testObject.overrides[0].contents, { 'a': { 'c': 2 } }); + assert.deepEqual(testObject.override('or').contents, { 'a': { 'c': 2 }, 'b': 1 }); + }); + + test('setValueInOverrides adds new overrides if exist', () => { + let testObject = new ConfigurationModel({ 'a': 1, 'b': 1 }, ['a'], [{ identifiers: ['or1'], contents: { 'a': 2 } }]); + + testObject.setValueInOverrides('or2', 'b', 2); + + assert.deepEqual(testObject.overrides[0].contents, { 'a': 2 }); + assert.deepEqual(testObject.overrides[1].contents, { 'b': 2 }); + assert.deepEqual(testObject.override('or1').contents, { 'a': 2, 'b': 1 }); + assert.deepEqual(testObject.override('or2').contents, { 'a': 1, 'b': 2 }); + }); + + test('get overriding configuration model for an existing identifier', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': 1 }, [], + [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); + + assert.deepEqual(testObject.override('c').contents, { 'a': { 'b': 1, 'd': 1 }, 'f': 1 }); + }); + + test('get overriding configuration model for an identifier that does not exist', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': 1 }, [], + [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); + + assert.deepEqual(testObject.override('xyz').contents, { 'a': { 'b': 1 }, 'f': 1 }); + }); + + test('get overriding configuration when one of the keys does not exist in base', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': 1 }, [], + [{ identifiers: ['c'], contents: { 'a': { 'd': 1 }, 'g': 1 } }]); + + assert.deepEqual(testObject.override('c').contents, { 'a': { 'b': 1, 'd': 1 }, 'f': 1, 'g': 1 }); + }); + + test('get overriding configuration when one of the key in base is not of object type', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': 1 }, [], + [{ identifiers: ['c'], contents: { 'a': { 'd': 1 }, 'f': { 'g': 1 } } }]); + + assert.deepEqual(testObject.override('c').contents, { 'a': { 'b': 1, 'd': 1 }, 'f': { 'g': 1 } }); + }); + + test('get overriding configuration when one of the key in overriding contents is not of object type', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': { 'g': 1 } }, [], + [{ identifiers: ['c'], contents: { 'a': { 'd': 1 }, 'f': 1 } }]); + + assert.deepEqual(testObject.override('c').contents, { 'a': { 'b': 1, 'd': 1 }, 'f': 1 }); + }); + + test('get overriding configuration if the value of overriding identifier is not object', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': { 'g': 1 } }, [], + [{ identifiers: ['c'], contents: 'abc' }]); + + assert.deepEqual(testObject.override('c').contents, { 'a': { 'b': 1 }, 'f': { 'g': 1 } }); + }); + + test('get overriding configuration if the value of overriding identifier is an empty object', () => { + let testObject = new ConfigurationModel( + { 'a': { 'b': 1 }, 'f': { 'g': 1 } }, [], + [{ identifiers: ['c'], contents: {} }]); + + assert.deepEqual(testObject.override('c').contents, { 'a': { 'b': 1 }, 'f': { 'g': 1 } }); + }); + + test('simple merge', () => { + let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); + let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); + let result = base.merge(add); + + assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 }); + }); + + test('recursive merge', () => { + let base = new ConfigurationModel({ 'a': { 'b': 1 } }); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }); + let result = base.merge(add); + + assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); + assert.deepEqual(result.getSectionContents('a'), { 'b': 2 }); + }); + + test('simple merge overrides', () => { + let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': 2 } }]); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'b': 2 } }]); + let result = base.merge(add); + + assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); + assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': 2, 'b': 2 } }]); + assert.deepEqual(result.override('c').contents, { 'a': 2, 'b': 2 }); + }); + + test('recursive merge overrides', () => { + let base = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, [], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]); + let result = base.merge(add); + + assert.deepEqual(result.contents, { 'a': { 'b': 2 }, 'f': 1 }); + assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': { 'd': 1, 'e': 2 } } }]); + assert.deepEqual(result.override('c').contents, { 'a': { 'b': 2, 'd': 1, 'e': 2 }, 'f': 1 }); + }); + + test('merge ignore keys', () => { + let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); + let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); + let result = base.merge(add); + assert.deepEqual(result.keys, []); + }); + + test('Test contents while getting an existing property', () => { + let testObject = new ConfigurationModel({ 'a': 1 }); + assert.deepEqual(testObject.getSectionContents('a'), 1); + + testObject = new ConfigurationModel({ 'a': { 'b': 1 } }); + assert.deepEqual(testObject.getSectionContents('a'), { 'b': 1 }); + }); + + test('Test contents are undefined for non existing properties', () => { + const testObject = new ConfigurationModel({ awesome: true }); + + assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); + }); + + test('Test override gives all content merged with overrides', () => { + const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, [], [{ identifiers: ['b'], contents: { 'a': 2 } }]); + + assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1 }); + }); +}); + +suite('CustomConfigurationModel', () => { + + suiteSetup(() => { + Registry.as(Extensions.Configuration).registerConfiguration({ + 'id': 'a', + 'order': 1, + 'title': 'a', + 'type': 'object', + 'properties': { + 'a': { + 'description': 'a', + 'type': 'boolean', + 'default': true, + 'overridable': true + } + } + }); + }); + + test('simple merge using models', () => { + let base = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 })); + let add = new CustomConfigurationModel(JSON.stringify({ 'a': 3, 'c': 4 })); + let result = base.merge(add); + assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 }); + }); + + test('simple merge with an undefined contents', () => { + let base = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 })); + let add = new CustomConfigurationModel(null); + let result = base.merge(add); + assert.deepEqual(result.contents, { 'a': 1, 'b': 2 }); + + base = new CustomConfigurationModel(null); + add = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 })); + result = base.merge(add); + assert.deepEqual(result.contents, { 'a': 1, 'b': 2 }); + + base = new CustomConfigurationModel(null); + add = new CustomConfigurationModel(null); + result = base.merge(add); + assert.deepEqual(result.contents, {}); + }); + + test('Recursive merge using config models', () => { + let base = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } })); + let add = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 2 } })); + let result = base.merge(add); + assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); + }); + + test('Test contents while getting an existing property', () => { + let testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1 })); + assert.deepEqual(testObject.getSectionContents('a'), 1); + + testObject = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } })); + assert.deepEqual(testObject.getSectionContents('a'), { 'b': 1 }); + }); + + test('Test contents are undefined for non existing properties', () => { + const testObject = new CustomConfigurationModel(JSON.stringify({ + awesome: true + })); + + assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); + }); + + test('Test contents are undefined for undefined config', () => { + const testObject = new CustomConfigurationModel(null); + + assert.deepEqual(testObject.getSectionContents('unknownproperty'), undefined); + }); + + test('Test configWithOverrides gives all content merged with overrides', () => { + const testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'c': 1, '[b]': { 'a': 2 } })); + + assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1, '[b]': { 'a': 2 } }); + }); + + test('Test configWithOverrides gives empty contents', () => { + const testObject = new CustomConfigurationModel(null); + + assert.deepEqual(testObject.override('b').contents, {}); + }); + + test('Test update with empty data', () => { + const testObject = new CustomConfigurationModel(); + testObject.update(''); + + assert.deepEqual(testObject.contents, {}); + assert.deepEqual(testObject.keys, []); + + testObject.update(null); + + assert.deepEqual(testObject.contents, {}); + assert.deepEqual(testObject.keys, []); + + testObject.update(undefined); + + assert.deepEqual(testObject.contents, {}); + assert.deepEqual(testObject.keys, []); + }); + + test('Test registering the same property again', () => { + Registry.as(Extensions.Configuration).registerConfiguration({ + 'id': 'a', + 'order': 1, + 'title': 'a', + 'type': 'object', + 'properties': { + 'a': { + 'description': 'a', + 'type': 'boolean', + 'default': false, + } + } + }); + assert.equal(true, new DefaultConfigurationModel().getSectionContents('a')); + }); + + test('Test registering the language property', () => { + Registry.as(Extensions.Configuration).registerConfiguration({ + 'id': '[a]', + 'order': 1, + 'title': 'a', + 'type': 'object', + 'properties': { + '[a]': { + 'description': 'a', + 'type': 'boolean', + 'default': false, + } + } + }); + assert.equal(undefined, new DefaultConfigurationModel().getSectionContents('[a]')); + }); + +}); \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 3cccaa1e6b2..f2ed3e415dc 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -322,8 +322,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat const folderConfigurationModels = new StrictResourceMap(); folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration)); - this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: @Sandy Avoid passing null - // TODO: compare with old values?? + this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null + // TODO Sandy: compare with old values?? const keys = this._configuration.keys(); this._onDidUpdateConfiguration.fire(new AllKeysConfigurationChangeEvent([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE))); From 6b374f36a19c0399efa7a62542e9be144396f358 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 Oct 2017 17:27:16 +0200 Subject: [PATCH 088/394] Implement interval searching to be non recursive and not use a stack --- src/vs/editor/common/model/intervalTree.ts | 119 ++++++++++++------ .../test/common/model/intervalTree.test.ts | 9 ++ 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 2744c6416bf..62888a2f05c 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -58,6 +58,8 @@ export class IntervalNode implements IModelDecoration { public cachedAbsoluteEnd: number; public range: Range; + public visited: boolean; + constructor(id: string, start: number, end: number) { this.parent = null; this.left = null; @@ -78,6 +80,8 @@ export class IntervalNode implements IModelDecoration { this.cachedAbsoluteStart = start; this.cachedAbsoluteEnd = end; this.range = null; + + this.visited = false; } public setOptions(options: ModelDecorationOptions) { @@ -124,9 +128,7 @@ export class IntervalTree { if (this.root === SENTINEL) { return []; } - let result: IntervalNode[] = []; - intervalSearchRecursive(this.root, 0, start, end, filterOwnerId, filterOutValidation, cachedVersionId, result); - return result; + return intervalSearch(this, start, end, filterOwnerId, filterOutValidation, cachedVersionId); } public insert(node: IntervalNode): void { @@ -159,6 +161,7 @@ export class IntervalTree { assert(SENTINEL.start === 0); assert(SENTINEL.end === 0); assert(SENTINEL.delta === 0); + assert(this.root.parent === SENTINEL); assertValidTree(this); } @@ -210,7 +213,8 @@ export class IntervalTree { } //#region Searching -function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStart: number, intervalEnd: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number, result: IntervalNode[]): void { + +function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree // Now, it is known that two intervals A and B overlap only when both // A.low <= B.high and A.high >= B.low. When searching the trees for @@ -218,45 +222,87 @@ function intervalSearchRecursive(node: IntervalNode, delta: number, intervalStar // a) all nodes to the right of nodes whose low value is past the end of the given interval. // b) all nodes that have their maximum 'high' value below the start of the given interval. - const nodeMaxEnd = delta + node.maxEnd; - if (nodeMaxEnd < intervalStart) { - // Cover b) from above - return; - } - - if (node.left !== SENTINEL) { - intervalSearchRecursive(node.left, delta, intervalStart, intervalEnd, filterOwnerId, filterOutValidation, cachedVersionId, result); - } - - const nodeStart = delta + node.start; - - if (nodeStart > intervalEnd) { - // Cover a) from above - return; - } - - const nodeEnd = delta + node.end; - if (nodeEnd >= intervalStart) { - // There is overlap - node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); - - let include = true; - if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) { - include = false; - } - if (filterOutValidation && node.isForValidation) { - include = false; + let node = T.root; + let delta = 0; + let nodeMaxEnd = 0; + let nodeStart = 0; + let nodeEnd = 0; + let result: IntervalNode[] = []; + let resultLen = 0; + while (node !== SENTINEL) { + if (node.visited) { + // going up from this node + node.left.visited = false; + node.right.visited = false; + if (node === node.parent.right) { + delta -= node.parent.delta; + } + node = node.parent; + continue; } - if (include) { - result.push(node); + if (!node.left.visited) { + // first time seeing this node + nodeMaxEnd = delta + node.maxEnd; + if (nodeMaxEnd < intervalStart) { + // cover case b) from above + // there is no need to search this node or its children + node.visited = true; + continue; + } + + if (node.left !== SENTINEL) { + // go left + node = node.left; + continue; + } + } + + // handle current node + nodeStart = delta + node.start; + if (nodeStart > intervalEnd) { + // cover case a) from above + // there is no need to search this node or its right subtree + node.visited = true; + continue; + } + + nodeEnd = delta + node.end; + + if (nodeEnd >= intervalStart) { + // There is overlap + node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); + + let include = true; + if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) { + include = false; + } + if (filterOutValidation && node.isForValidation) { + include = false; + } + + if (include) { + result[resultLen++] = node; + } + } + + node.visited = true; + + if (node.right !== SENTINEL && !node.right.visited) { + // go right + delta += node.delta; + node = node.right; + continue; } } - if (node.right !== SENTINEL) { - intervalSearchRecursive(node.right, delta + node.delta, intervalStart, intervalEnd, filterOwnerId, filterOutValidation, cachedVersionId, result); + if (T.root) { + T.root.visited = false; } + + return result; } + //#endregion //#region Insertion @@ -406,6 +452,7 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { z.detach(); resetSentinel(); recomputeMaxEnd(x); + T.root.parent = SENTINEL; return; } diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index cc12118fee5..1ece94f8b43 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -380,6 +380,15 @@ suite('IntervalTree', () => { { type: 'delete', id: 6 } ]); }); + + test('gen18', () => { + testIntervalTree([ + { type: 'insert', begin: 25, end: 25 }, + { type: 'insert', begin: 67, end: 79 }, + { type: 'delete', id: 0 }, + { type: 'search', begin: 65, end: 75 } + ]); + }); }); // TEST_COUNT = 0; From ed40c15f495215437e740b9c698b076c42563de9 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 13 Oct 2017 17:38:21 +0200 Subject: [PATCH 089/394] getCompositeSize dynamicaly --- src/vs/workbench/browser/compositeBar.ts | 14 +++++++++++--- .../browser/parts/activitybar/activitybarPart.ts | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/compositeBar.ts b/src/vs/workbench/browser/compositeBar.ts index 0fc8b7b53ee..c8ab4d6a87a 100644 --- a/src/vs/workbench/browser/compositeBar.ts +++ b/src/vs/workbench/browser/compositeBar.ts @@ -35,6 +35,7 @@ export interface ICompositeBarOptions { getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; getOpenCompositeAction: (compositeId: string) => Action; + getCompositeSize: (compositeId: string) => number; } export class CompositeBar { @@ -204,7 +205,7 @@ export class CompositeBar { // Always show the active composite even if it is marked to be hidden if (this.activeCompositeId && !compositesToShow.some(id => id === this.activeCompositeId)) { this.activeUnpinnedCompositeId = this.activeCompositeId; - compositesToShow.push(this.activeUnpinnedCompositeId); + compositesToShow = compositesToShow.concat(this.activeUnpinnedCompositeId); } else { this.activeUnpinnedCompositeId = void 0; } @@ -212,8 +213,15 @@ export class CompositeBar { // Ensure we are not showing more composites than we have height for let overflows = false; if (this.dimension) { - // TODO@Isidor change this maxVisible computation to be dynamic - const maxVisible = Math.floor(this.dimension.height / 50); + let maxVisible = compositesToShow.length; + let size = 0; + const limit = this.options.orientation === ActionsOrientation.VERTICAL ? this.dimension.height : this.dimension.width; + for (let i = 0; i < compositesToShow.length && size <= limit; i++) { + size += this.options.getCompositeSize(compositesToShow[i]); + if (size > limit) { + maxVisible = i; + } + } overflows = compositesToShow.length > maxVisible; if (overflows) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 035d1ad57b9..2130ea88179 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -63,6 +63,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { storageId: ActivitybarPart.PINNED_VIEWLETS, orientation: ActionsOrientation.VERTICAL, composites: this.viewletService.getViewlets(), + getCompositeSize: (compositeId: string) => ActivitybarPart.ACTIVITY_ACTION_HEIGHT, getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)), getCompositePinnedAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletPinnedAction, this.viewletService.getViewlet(compositeId)), getOpenCompositeAction: (compositeId: string) => this.instantiationService.createInstance(OpenViewletAction, this.viewletService.getViewlet(compositeId)) From b5a874488f6ed87b00029c9d3e790b05d55f7a0d Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 13 Oct 2017 17:42:14 +0200 Subject: [PATCH 090/394] remove todo comments --- src/vs/workbench/browser/compositeBar.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/browser/compositeBar.ts b/src/vs/workbench/browser/compositeBar.ts index c8ab4d6a87a..5320747811c 100644 --- a/src/vs/workbench/browser/compositeBar.ts +++ b/src/vs/workbench/browser/compositeBar.ts @@ -23,10 +23,6 @@ import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/a import Event, { Emitter } from 'vs/base/common/event'; import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem } from 'vs/workbench/browser/compositeBarActions'; -// first goal make the activity bar depend on the composite bar and everything works as before -// after that think about how to plug this into the panel part and the overflow nicely wokring (composite bar in panel will need overflow: hidden) -// on the action bar offsetWidth = gets the width of every child (on the first layout need to check if it is still in the constraints) - export interface ICompositeBarOptions { label: 'icon' | 'name'; storageId: string; From 8f1b989c36b5448e12c9f68378fc44de6e5802b1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 13 Oct 2017 17:43:00 +0200 Subject: [PATCH 091/394] move editor service into common --- .../browser/parts/editor/editorPart.ts | 2 +- .../browser/parts/editor/tabsTitleControl.ts | 3 +- .../browser/parts/editor/textDiffEditor.ts | 3 +- .../workbench/electron-browser/workbench.ts | 3 +- .../parts/files/browser/explorerViewlet.ts | 3 +- .../services/editor/browser/editorService.ts | 365 ------------------ .../services/editor/common/editorService.ts | 359 ++++++++++++++++- .../editor/test/browser/editorService.test.ts | 2 +- 8 files changed, 363 insertions(+), 377 deletions(-) delete mode 100644 src/vs/workbench/services/editor/browser/editorService.ts diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 25fcf62c102..15ce8ce3eb0 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -26,7 +26,7 @@ import { EditorGroupsControl, Rochade, IEditorGroupsControl, ProgressState } fro import { WorkbenchProgressService } from 'vs/workbench/services/progress/browser/progressService'; import { IEditorGroupService, GroupOrientation, GroupArrangement, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IEditorPart } from 'vs/workbench/services/editor/browser/editorService'; +import { IEditorPart } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { Position, POSITIONS, Direction, IEditor } from 'vs/platform/editor/common/editor'; import { IStorageService } from 'vs/platform/storage/common/storage'; diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 3a12c2226cf..e598d3383e3 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -20,7 +20,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { ResourceLabel } from 'vs/workbench/browser/labels'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IWorkbenchEditorService, DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IMessageService } from 'vs/platform/message/common/message'; @@ -37,7 +37,6 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { extractResources } from 'vs/base/browser/dnd'; import { getOrSet } from 'vs/base/common/map'; -import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER } from 'vs/workbench/common/theme'; diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 7143b5a9fa2..641e62414b7 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -22,14 +22,13 @@ import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel'; -import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IWorkbenchEditorService, DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IModeService } from 'vs/editor/common/services/modeService'; diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index f6bdc8d057f..c88d5d05d54 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -39,7 +39,6 @@ import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbe import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController'; import { getServices } from 'vs/platform/instantiation/common/extensions'; -import { WorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { Position, Parts, IPartService, ILayoutOptions } from 'vs/workbench/services/part/common/partService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -66,7 +65,7 @@ import { ConfigurationResolverService } from 'vs/workbench/services/configuratio import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ITitleService } from 'vs/workbench/services/title/common/titleService'; import { WorkbenchMessageService } from 'vs/workbench/services/message/browser/messageService'; -import { IWorkbenchEditorService, IResourceInputType } from 'vs/workbench/services/editor/common/editorService'; +import { IWorkbenchEditorService, IResourceInputType, WorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService'; diff --git a/src/vs/workbench/parts/files/browser/explorerViewlet.ts b/src/vs/workbench/parts/files/browser/explorerViewlet.ts index 44cac3254e1..74da9b16cd4 100644 --- a/src/vs/workbench/parts/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/browser/explorerViewlet.ts @@ -24,11 +24,10 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IWorkbenchEditorService, DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts deleted file mode 100644 index 2cabe8935ca..00000000000 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ /dev/null @@ -1,365 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { TPromise } from 'vs/base/common/winjs.base'; -import URI from 'vs/base/common/uri'; -import network = require('vs/base/common/network'); -import { Registry } from 'vs/platform/registry/common/platform'; -import { basename, dirname } from 'vs/base/common/paths'; -import { EditorInput, EditorOptions, TextEditorOptions, Extensions as EditorExtensions, SideBySideEditorInput, IFileEditorInput, IFileInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; -import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; -import { IUntitledEditorService, UNTITLED_SCHEMA } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import { IWorkbenchEditorService, IResourceInputType } from 'vs/workbench/services/editor/common/editorService'; -import { IEditorInput, IEditorOptions, ITextEditorOptions, Position, Direction, IEditor, IResourceInput, IResourceDiffInput, IResourceSideBySideInput, IUntitledResourceInput } from 'vs/platform/editor/common/editor'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import nls = require('vs/nls'); -import { getPathLabel } from 'vs/base/common/labels'; -import { ResourceMap } from 'vs/base/common/map'; -import { once } from 'vs/base/common/event'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IFileService } from 'vs/platform/files/common/files'; - -export interface IEditorPart { - openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, sideBySide?: boolean): TPromise; - openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, position?: Position): TPromise; - openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions | ITextEditorOptions }[]): TPromise; - replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions | ITextEditorOptions }[], position?: Position): TPromise; - closeEditor(position: Position, input: IEditorInput): TPromise; - closeEditors(position: Position, filter?: { except?: IEditorInput, direction?: Direction, unmodifiedOnly?: boolean }): TPromise; - closeAllEditors(except?: Position): TPromise; - getActiveEditor(): IEditor; - getVisibleEditors(): IEditor[]; - getActiveEditorInput(): IEditorInput; -} - -type ICachedEditorInput = ResourceEditorInput | IFileEditorInput; - -export class WorkbenchEditorService implements IWorkbenchEditorService { - - public _serviceBrand: any; - - private static CACHE: ResourceMap = new ResourceMap(); - - private editorPart: IEditorPart | IWorkbenchEditorService; - private fileInputFactory: IFileInputFactory; - - constructor( - editorPart: IEditorPart | IWorkbenchEditorService, - @IUntitledEditorService private untitledEditorService: IUntitledEditorService, - @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, - @IInstantiationService private instantiationService: IInstantiationService, - @IEnvironmentService private environmentService: IEnvironmentService, - @IFileService private fileService: IFileService - ) { - this.editorPart = editorPart; - this.fileInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileInputFactory(); - } - - public getActiveEditor(): IEditor { - return this.editorPart.getActiveEditor(); - } - - public getActiveEditorInput(): IEditorInput { - return this.editorPart.getActiveEditorInput(); - } - - public getVisibleEditors(): IEditor[] { - return this.editorPart.getVisibleEditors(); - } - - public isVisible(input: IEditorInput, includeSideBySide: boolean): boolean { - if (!input) { - return false; - } - - return this.getVisibleEditors().some(editor => { - if (!editor.input) { - return false; - } - - if (input.matches(editor.input)) { - return true; - } - - if (includeSideBySide && editor.input instanceof SideBySideEditorInput) { - const sideBySideInput = editor.input; - return input.matches(sideBySideInput.master) || input.matches(sideBySideInput.details); - } - - return false; - }); - } - - public openEditor(input: IEditorInput, options?: IEditorOptions, sideBySide?: boolean): TPromise; - public openEditor(input: IEditorInput, options?: IEditorOptions, position?: Position): TPromise; - public openEditor(input: IResourceInputType, position?: Position): TPromise; - public openEditor(input: IResourceInputType, sideBySide?: boolean): TPromise; - public openEditor(input: any, arg2?: any, arg3?: any): TPromise { - if (!input) { - return TPromise.as(null); - } - - // Workbench Input Support - if (input instanceof EditorInput) { - return this.doOpenEditor(input, this.toOptions(arg2), arg3); - } - - // Support opening foreign resources (such as a http link that points outside of the workbench) - const resourceInput = input; - if (resourceInput.resource instanceof URI) { - const schema = resourceInput.resource.scheme; - if (schema === network.Schemas.http || schema === network.Schemas.https) { - window.open(resourceInput.resource.toString(true)); - - return TPromise.as(null); - } - } - - // Untyped Text Editor Support (required for code that uses this service below workbench level) - const textInput = input; - const typedInput = this.createInput(textInput); - if (typedInput) { - return this.doOpenEditor(typedInput, TextEditorOptions.from(textInput), arg2); - } - - return TPromise.as(null); - } - - private toOptions(options?: IEditorOptions | EditorOptions): EditorOptions { - if (!options || options instanceof EditorOptions) { - return options as EditorOptions; - } - - const textOptions: ITextEditorOptions = options; - if (!!textOptions.selection) { - return TextEditorOptions.create(options); - } - - return EditorOptions.create(options); - } - - /** - * Allow subclasses to implement their own behavior for opening editor (see below). - */ - protected doOpenEditor(input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; - protected doOpenEditor(input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; - protected doOpenEditor(input: IEditorInput, options?: EditorOptions, arg3?: any): TPromise { - return this.editorPart.openEditor(input, options, arg3); - } - - public openEditors(editors: { input: IResourceInputType, position: Position }[]): TPromise; - public openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions }[]): TPromise; - public openEditors(editors: any[]): TPromise { - const inputs = editors.map(editor => this.createInput(editor.input)); - const typedInputs: { input: IEditorInput, position: Position, options?: EditorOptions }[] = inputs.map((input, index) => { - const options = editors[index].input instanceof EditorInput ? this.toOptions(editors[index].options) : TextEditorOptions.from(editors[index].input); - - return { - input, - options, - position: editors[index].position - }; - }); - - return this.editorPart.openEditors(typedInputs); - } - - public replaceEditors(editors: { toReplace: IResourceInputType, replaceWith: IResourceInputType }[], position?: Position): TPromise; - public replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions }[], position?: Position): TPromise; - public replaceEditors(editors: any[], position?: Position): TPromise { - const toReplaceInputs = editors.map(editor => this.createInput(editor.toReplace)); - const replaceWithInputs = editors.map(editor => this.createInput(editor.replaceWith)); - const typedReplacements: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: EditorOptions }[] = editors.map((editor, index) => { - const options = editor.toReplace instanceof EditorInput ? this.toOptions(editor.options) : TextEditorOptions.from(editor.replaceWith); - - return { - toReplace: toReplaceInputs[index], - replaceWith: replaceWithInputs[index], - options - }; - }); - - return this.editorPart.replaceEditors(typedReplacements, position); - } - - public closeEditor(position: Position, input: IEditorInput): TPromise { - return this.doCloseEditor(position, input); - } - - protected doCloseEditor(position: Position, input: IEditorInput): TPromise { - return this.editorPart.closeEditor(position, input); - } - - public closeEditors(position: Position, filter?: { except?: IEditorInput, direction?: Direction, unmodifiedOnly?: boolean }): TPromise { - return this.editorPart.closeEditors(position, filter); - } - - public closeAllEditors(except?: Position): TPromise { - return this.editorPart.closeAllEditors(except); - } - - public createInput(input: IEditorInput): EditorInput; - public createInput(input: IResourceInputType): EditorInput; - public createInput(input: any): IEditorInput { - - // Workbench Input Support - if (input instanceof EditorInput) { - return input; - } - - // Side by Side Support - const resourceSideBySideInput = input; - if (resourceSideBySideInput.masterResource && resourceSideBySideInput.detailResource) { - const masterInput = this.createInput({ resource: resourceSideBySideInput.masterResource }); - const detailInput = this.createInput({ resource: resourceSideBySideInput.detailResource }); - - return new SideBySideEditorInput(resourceSideBySideInput.label || masterInput.getName(), typeof resourceSideBySideInput.description === 'string' ? resourceSideBySideInput.description : masterInput.getDescription(), detailInput, masterInput); - } - - // Diff Editor Support - const resourceDiffInput = input; - if (resourceDiffInput.leftResource && resourceDiffInput.rightResource) { - const leftInput = this.createInput({ resource: resourceDiffInput.leftResource }); - const rightInput = this.createInput({ resource: resourceDiffInput.rightResource }); - const label = resourceDiffInput.label || this.toDiffLabel(resourceDiffInput.leftResource, resourceDiffInput.rightResource, this.workspaceContextService, this.environmentService); - - return new DiffEditorInput(label, resourceDiffInput.description, leftInput, rightInput); - } - - // Untitled file support - const untitledInput = input; - if (!untitledInput.resource || typeof untitledInput.filePath === 'string' || (untitledInput.resource instanceof URI && untitledInput.resource.scheme === UNTITLED_SCHEMA)) { - return this.untitledEditorService.createOrGet(untitledInput.filePath ? URI.file(untitledInput.filePath) : untitledInput.resource, untitledInput.language, untitledInput.contents, untitledInput.encoding); - } - - const resourceInput = input; - - // Files support - if (resourceInput.resource instanceof URI && resourceInput.resource.scheme === network.Schemas.file) { - return this.createOrGet(resourceInput.resource, this.instantiationService, resourceInput.label, resourceInput.description, resourceInput.encoding); - } - - // Any other resource - else if (resourceInput.resource instanceof URI) { - const label = resourceInput.label || basename(resourceInput.resource.fsPath); - let description: string; - if (typeof resourceInput.description === 'string') { - description = resourceInput.description; - } else if (resourceInput.resource.scheme === network.Schemas.file) { - description = dirname(resourceInput.resource.fsPath); - } - - return this.createOrGet(resourceInput.resource, this.instantiationService, label, description); - } - - return null; - } - - private createOrGet(resource: URI, instantiationService: IInstantiationService, label: string, description: string, encoding?: string): ICachedEditorInput { - if (WorkbenchEditorService.CACHE.has(resource)) { - const input = WorkbenchEditorService.CACHE.get(resource); - if (input instanceof ResourceEditorInput) { - input.setName(label); - input.setDescription(description); - } else { - input.setPreferredEncoding(encoding); - } - - return input; - } - - let input: ICachedEditorInput; - if (resource.scheme === network.Schemas.file || this.fileService.canHandleResource && this.fileService.canHandleResource(resource)) { - input = this.fileInputFactory.createFileInput(resource, encoding, instantiationService); - } else { - input = instantiationService.createInstance(ResourceEditorInput, label, description, resource); - } - - WorkbenchEditorService.CACHE.set(resource, input); - once(input.onDispose)(() => { - WorkbenchEditorService.CACHE.delete(resource); - }); - - return input; - } - - private toDiffLabel(res1: URI, res2: URI, context: IWorkspaceContextService, environment: IEnvironmentService): string { - const leftName = getPathLabel(res1.fsPath, context, environment); - const rightName = getPathLabel(res2.fsPath, context, environment); - - return nls.localize('compareLabels', "{0} ↔ {1}", leftName, rightName); - } -} - -export interface IEditorOpenHandler { - (input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; - (input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; -} - -export interface IEditorCloseHandler { - (position: Position, input: IEditorInput): TPromise; -} - -/** - * Subclass of workbench editor service that delegates all calls to the provided editor service. Subclasses can choose to override the behavior - * of openEditor() and closeEditor() by providing a handler. - * - * This gives clients a chance to override the behavior of openEditor() and closeEditor(). - */ -export class DelegatingWorkbenchEditorService extends WorkbenchEditorService { - private editorOpenHandler: IEditorOpenHandler; - private editorCloseHandler: IEditorCloseHandler; - - constructor( - @IUntitledEditorService untitledEditorService: IUntitledEditorService, - @IInstantiationService instantiationService: IInstantiationService, - @IWorkspaceContextService workspaceContextService: IWorkspaceContextService, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, - @IEnvironmentService environmentService: IEnvironmentService, - @IFileService fileService: IFileService - ) { - super( - editorService, - untitledEditorService, - workspaceContextService, - instantiationService, - environmentService, - fileService - ); - } - - public setEditorOpenHandler(handler: IEditorOpenHandler): void { - this.editorOpenHandler = handler; - } - - public setEditorCloseHandler(handler: IEditorCloseHandler): void { - this.editorCloseHandler = handler; - } - - protected doOpenEditor(input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; - protected doOpenEditor(input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; - protected doOpenEditor(input: IEditorInput, options?: EditorOptions, arg3?: any): TPromise { - const handleOpen = this.editorOpenHandler ? this.editorOpenHandler(input, options, arg3) : TPromise.as(void 0); - - return handleOpen.then(editor => { - if (editor) { - return TPromise.as(editor); - } - - return super.doOpenEditor(input, options, arg3); - }); - } - - protected doCloseEditor(position: Position, input: IEditorInput): TPromise { - const handleClose = this.editorCloseHandler ? this.editorCloseHandler(position, input) : TPromise.as(void 0); - - return handleClose.then(() => { - return super.doCloseEditor(position, input); - }); - } -} diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 05f2ae36cc2..8100a8cd551 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -6,8 +6,23 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; +import { createDecorator, ServiceIdentifier, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IEditorService, IEditor, IEditorInput, IEditorOptions, ITextEditorOptions, Position, Direction, IResourceInput, IResourceDiffInput, IResourceSideBySideInput, IUntitledResourceInput } from 'vs/platform/editor/common/editor'; +import URI from 'vs/base/common/uri'; +import network = require('vs/base/common/network'); +import { Registry } from 'vs/platform/registry/common/platform'; +import { basename, dirname } from 'vs/base/common/paths'; +import { EditorInput, EditorOptions, TextEditorOptions, Extensions as EditorExtensions, SideBySideEditorInput, IFileEditorInput, IFileInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; +import { IUntitledEditorService, UNTITLED_SCHEMA } from 'vs/workbench/services/untitled/common/untitledEditorService'; +import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import nls = require('vs/nls'); +import { getPathLabel } from 'vs/base/common/labels'; +import { ResourceMap } from 'vs/base/common/map'; +import { once } from 'vs/base/common/event'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IFileService } from 'vs/platform/files/common/files'; export const IWorkbenchEditorService = createDecorator('editorService'); @@ -91,4 +106,344 @@ export interface IWorkbenchEditorService extends IEditorService { * Allows to resolve an untyped input to a workbench typed instanceof editor input */ createInput(input: IResourceInputType): IEditorInput; -} \ No newline at end of file +} + +export interface IEditorPart { + openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, sideBySide?: boolean): TPromise; + openEditor(input?: IEditorInput, options?: IEditorOptions | ITextEditorOptions, position?: Position): TPromise; + openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions | ITextEditorOptions }[]): TPromise; + replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions | ITextEditorOptions }[], position?: Position): TPromise; + closeEditor(position: Position, input: IEditorInput): TPromise; + closeEditors(position: Position, filter?: { except?: IEditorInput, direction?: Direction, unmodifiedOnly?: boolean }): TPromise; + closeAllEditors(except?: Position): TPromise; + getActiveEditor(): IEditor; + getVisibleEditors(): IEditor[]; + getActiveEditorInput(): IEditorInput; +} + +type ICachedEditorInput = ResourceEditorInput | IFileEditorInput; + +export class WorkbenchEditorService implements IWorkbenchEditorService { + + public _serviceBrand: any; + + private static CACHE: ResourceMap = new ResourceMap(); + + private editorPart: IEditorPart | IWorkbenchEditorService; + private fileInputFactory: IFileInputFactory; + + constructor( + editorPart: IEditorPart | IWorkbenchEditorService, + @IUntitledEditorService private untitledEditorService: IUntitledEditorService, + @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, + @IInstantiationService private instantiationService: IInstantiationService, + @IEnvironmentService private environmentService: IEnvironmentService, + @IFileService private fileService: IFileService + ) { + this.editorPart = editorPart; + this.fileInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileInputFactory(); + } + + public getActiveEditor(): IEditor { + return this.editorPart.getActiveEditor(); + } + + public getActiveEditorInput(): IEditorInput { + return this.editorPart.getActiveEditorInput(); + } + + public getVisibleEditors(): IEditor[] { + return this.editorPart.getVisibleEditors(); + } + + public isVisible(input: IEditorInput, includeSideBySide: boolean): boolean { + if (!input) { + return false; + } + + return this.getVisibleEditors().some(editor => { + if (!editor.input) { + return false; + } + + if (input.matches(editor.input)) { + return true; + } + + if (includeSideBySide && editor.input instanceof SideBySideEditorInput) { + const sideBySideInput = editor.input; + return input.matches(sideBySideInput.master) || input.matches(sideBySideInput.details); + } + + return false; + }); + } + + public openEditor(input: IEditorInput, options?: IEditorOptions, sideBySide?: boolean): TPromise; + public openEditor(input: IEditorInput, options?: IEditorOptions, position?: Position): TPromise; + public openEditor(input: IResourceInputType, position?: Position): TPromise; + public openEditor(input: IResourceInputType, sideBySide?: boolean): TPromise; + public openEditor(input: any, arg2?: any, arg3?: any): TPromise { + if (!input) { + return TPromise.as(null); + } + + // Workbench Input Support + if (input instanceof EditorInput) { + return this.doOpenEditor(input, this.toOptions(arg2), arg3); + } + + // Support opening foreign resources (such as a http link that points outside of the workbench) + const resourceInput = input; + if (resourceInput.resource instanceof URI) { + const schema = resourceInput.resource.scheme; + if (schema === network.Schemas.http || schema === network.Schemas.https) { + window.open(resourceInput.resource.toString(true)); + + return TPromise.as(null); + } + } + + // Untyped Text Editor Support (required for code that uses this service below workbench level) + const textInput = input; + const typedInput = this.createInput(textInput); + if (typedInput) { + return this.doOpenEditor(typedInput, TextEditorOptions.from(textInput), arg2); + } + + return TPromise.as(null); + } + + private toOptions(options?: IEditorOptions | EditorOptions): EditorOptions { + if (!options || options instanceof EditorOptions) { + return options as EditorOptions; + } + + const textOptions: ITextEditorOptions = options; + if (!!textOptions.selection) { + return TextEditorOptions.create(options); + } + + return EditorOptions.create(options); + } + + /** + * Allow subclasses to implement their own behavior for opening editor (see below). + */ + protected doOpenEditor(input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; + protected doOpenEditor(input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; + protected doOpenEditor(input: IEditorInput, options?: EditorOptions, arg3?: any): TPromise { + return this.editorPart.openEditor(input, options, arg3); + } + + public openEditors(editors: { input: IResourceInputType, position: Position }[]): TPromise; + public openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions }[]): TPromise; + public openEditors(editors: any[]): TPromise { + const inputs = editors.map(editor => this.createInput(editor.input)); + const typedInputs: { input: IEditorInput, position: Position, options?: EditorOptions }[] = inputs.map((input, index) => { + const options = editors[index].input instanceof EditorInput ? this.toOptions(editors[index].options) : TextEditorOptions.from(editors[index].input); + + return { + input, + options, + position: editors[index].position + }; + }); + + return this.editorPart.openEditors(typedInputs); + } + + public replaceEditors(editors: { toReplace: IResourceInputType, replaceWith: IResourceInputType }[], position?: Position): TPromise; + public replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions }[], position?: Position): TPromise; + public replaceEditors(editors: any[], position?: Position): TPromise { + const toReplaceInputs = editors.map(editor => this.createInput(editor.toReplace)); + const replaceWithInputs = editors.map(editor => this.createInput(editor.replaceWith)); + const typedReplacements: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: EditorOptions }[] = editors.map((editor, index) => { + const options = editor.toReplace instanceof EditorInput ? this.toOptions(editor.options) : TextEditorOptions.from(editor.replaceWith); + + return { + toReplace: toReplaceInputs[index], + replaceWith: replaceWithInputs[index], + options + }; + }); + + return this.editorPart.replaceEditors(typedReplacements, position); + } + + public closeEditor(position: Position, input: IEditorInput): TPromise { + return this.doCloseEditor(position, input); + } + + protected doCloseEditor(position: Position, input: IEditorInput): TPromise { + return this.editorPart.closeEditor(position, input); + } + + public closeEditors(position: Position, filter?: { except?: IEditorInput, direction?: Direction, unmodifiedOnly?: boolean }): TPromise { + return this.editorPart.closeEditors(position, filter); + } + + public closeAllEditors(except?: Position): TPromise { + return this.editorPart.closeAllEditors(except); + } + + public createInput(input: IEditorInput): EditorInput; + public createInput(input: IResourceInputType): EditorInput; + public createInput(input: any): IEditorInput { + + // Workbench Input Support + if (input instanceof EditorInput) { + return input; + } + + // Side by Side Support + const resourceSideBySideInput = input; + if (resourceSideBySideInput.masterResource && resourceSideBySideInput.detailResource) { + const masterInput = this.createInput({ resource: resourceSideBySideInput.masterResource }); + const detailInput = this.createInput({ resource: resourceSideBySideInput.detailResource }); + + return new SideBySideEditorInput(resourceSideBySideInput.label || masterInput.getName(), typeof resourceSideBySideInput.description === 'string' ? resourceSideBySideInput.description : masterInput.getDescription(), detailInput, masterInput); + } + + // Diff Editor Support + const resourceDiffInput = input; + if (resourceDiffInput.leftResource && resourceDiffInput.rightResource) { + const leftInput = this.createInput({ resource: resourceDiffInput.leftResource }); + const rightInput = this.createInput({ resource: resourceDiffInput.rightResource }); + const label = resourceDiffInput.label || this.toDiffLabel(resourceDiffInput.leftResource, resourceDiffInput.rightResource, this.workspaceContextService, this.environmentService); + + return new DiffEditorInput(label, resourceDiffInput.description, leftInput, rightInput); + } + + // Untitled file support + const untitledInput = input; + if (!untitledInput.resource || typeof untitledInput.filePath === 'string' || (untitledInput.resource instanceof URI && untitledInput.resource.scheme === UNTITLED_SCHEMA)) { + return this.untitledEditorService.createOrGet(untitledInput.filePath ? URI.file(untitledInput.filePath) : untitledInput.resource, untitledInput.language, untitledInput.contents, untitledInput.encoding); + } + + const resourceInput = input; + + // Files support + if (resourceInput.resource instanceof URI && resourceInput.resource.scheme === network.Schemas.file) { + return this.createOrGet(resourceInput.resource, this.instantiationService, resourceInput.label, resourceInput.description, resourceInput.encoding); + } + + // Any other resource + else if (resourceInput.resource instanceof URI) { + const label = resourceInput.label || basename(resourceInput.resource.fsPath); + let description: string; + if (typeof resourceInput.description === 'string') { + description = resourceInput.description; + } else if (resourceInput.resource.scheme === network.Schemas.file) { + description = dirname(resourceInput.resource.fsPath); + } + + return this.createOrGet(resourceInput.resource, this.instantiationService, label, description); + } + + return null; + } + + private createOrGet(resource: URI, instantiationService: IInstantiationService, label: string, description: string, encoding?: string): ICachedEditorInput { + if (WorkbenchEditorService.CACHE.has(resource)) { + const input = WorkbenchEditorService.CACHE.get(resource); + if (input instanceof ResourceEditorInput) { + input.setName(label); + input.setDescription(description); + } else { + input.setPreferredEncoding(encoding); + } + + return input; + } + + let input: ICachedEditorInput; + if (resource.scheme === network.Schemas.file || this.fileService.canHandleResource && this.fileService.canHandleResource(resource)) { + input = this.fileInputFactory.createFileInput(resource, encoding, instantiationService); + } else { + input = instantiationService.createInstance(ResourceEditorInput, label, description, resource); + } + + WorkbenchEditorService.CACHE.set(resource, input); + once(input.onDispose)(() => { + WorkbenchEditorService.CACHE.delete(resource); + }); + + return input; + } + + private toDiffLabel(res1: URI, res2: URI, context: IWorkspaceContextService, environment: IEnvironmentService): string { + const leftName = getPathLabel(res1.fsPath, context, environment); + const rightName = getPathLabel(res2.fsPath, context, environment); + + return nls.localize('compareLabels', "{0} ↔ {1}", leftName, rightName); + } +} + +export interface IEditorOpenHandler { + (input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; + (input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; +} + +export interface IEditorCloseHandler { + (position: Position, input: IEditorInput): TPromise; +} + +/** + * Subclass of workbench editor service that delegates all calls to the provided editor service. Subclasses can choose to override the behavior + * of openEditor() and closeEditor() by providing a handler. + * + * This gives clients a chance to override the behavior of openEditor() and closeEditor(). + */ +export class DelegatingWorkbenchEditorService extends WorkbenchEditorService { + private editorOpenHandler: IEditorOpenHandler; + private editorCloseHandler: IEditorCloseHandler; + + constructor( + @IUntitledEditorService untitledEditorService: IUntitledEditorService, + @IInstantiationService instantiationService: IInstantiationService, + @IWorkspaceContextService workspaceContextService: IWorkspaceContextService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IEnvironmentService environmentService: IEnvironmentService, + @IFileService fileService: IFileService + ) { + super( + editorService, + untitledEditorService, + workspaceContextService, + instantiationService, + environmentService, + fileService + ); + } + + public setEditorOpenHandler(handler: IEditorOpenHandler): void { + this.editorOpenHandler = handler; + } + + public setEditorCloseHandler(handler: IEditorCloseHandler): void { + this.editorCloseHandler = handler; + } + + protected doOpenEditor(input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise; + protected doOpenEditor(input: IEditorInput, options?: EditorOptions, position?: Position): TPromise; + protected doOpenEditor(input: IEditorInput, options?: EditorOptions, arg3?: any): TPromise { + const handleOpen = this.editorOpenHandler ? this.editorOpenHandler(input, options, arg3) : TPromise.as(void 0); + + return handleOpen.then(editor => { + if (editor) { + return TPromise.as(editor); + } + + return super.doOpenEditor(input, options, arg3); + }); + } + + protected doCloseEditor(position: Position, input: IEditorInput): TPromise { + const handleClose = this.editorCloseHandler ? this.editorCloseHandler(position, input) : TPromise.as(void 0); + + return handleClose.then(() => { + return super.doCloseEditor(position, input); + }); + } +} diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index c6ce1376dc1..dabe18285d6 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -14,7 +14,7 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { EditorInput, EditorOptions, TextEditorOptions } from 'vs/workbench/common/editor'; import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEditorInput'; import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices'; -import { DelegatingWorkbenchEditorService, WorkbenchEditorService, IEditorPart } from 'vs/workbench/services/editor/browser/editorService'; +import { DelegatingWorkbenchEditorService, WorkbenchEditorService, IEditorPart } from 'vs/workbench/services/editor/common/editorService'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; From e290a7582cd54ed538e78440005f94dffe7a9483 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 13 Oct 2017 17:52:06 +0200 Subject: [PATCH 092/394] settings - editor options travel through --- .../browser/parts/editor/editorPart.ts | 2 +- src/vs/workbench/common/editor.ts | 9 +++++-- .../preferences/browser/preferencesService.ts | 26 ++++++++++++------- .../parts/preferences/common/preferences.ts | 8 +++--- .../common/preferencesContribution.ts | 6 ++--- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 15ce8ce3eb0..e1a28c2dd1d 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -336,7 +336,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService } // Editor opening event (can be prevented and overridden) - const event = new EditorOpeningEvent(input, position); + const event = new EditorOpeningEvent(input, options, position); this._onEditorOpening.fire(event); const prevented = event.isPrevented(); if (prevented) { diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 0e2582432d6..2df8fc14a2d 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -262,6 +262,7 @@ export abstract class EditorInput implements IEditorInput { export interface IEditorOpeningEvent { input: IEditorInput; + options?: IEditorOptions; position: Position; /** @@ -277,11 +278,15 @@ export interface IEditorOpeningEvent { export class EditorOpeningEvent { private override: () => TPromise; - constructor(private _editorInput: IEditorInput, private _position: Position) { + constructor(private _input: IEditorInput, private _options: IEditorOptions, private _position: Position) { } public get input(): IEditorInput { - return this._editorInput; + return this._input; + } + + public get options(): IEditorOptions { + return this._options; } public get position(): Position { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index eea8fda7f35..fba847f728b 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -17,7 +17,7 @@ import { EditorInput } from 'vs/workbench/common/editor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { Position as EditorPosition, IEditor } from 'vs/platform/editor/common/editor'; +import { Position as EditorPosition, IEditor, IEditorOptions } from 'vs/platform/editor/common/editor'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -176,20 +176,20 @@ export class PreferencesService extends Disposable implements IPreferencesServic return TPromise.wrap>(null); } - openGlobalSettings(position?: EditorPosition): TPromise { - return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource, position); + openGlobalSettings(options?: IEditorOptions, position?: EditorPosition): TPromise { + return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource, options, position); } - openWorkspaceSettings(position?: EditorPosition): TPromise { + openWorkspaceSettings(options?: IEditorOptions, position?: EditorPosition): TPromise { if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('openFolderFirst', "Open a folder first to create workspace settings")); return TPromise.as(null); } - return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource, position); + return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource, options, position); } - openFolderSettings(folder: URI, position?: EditorPosition): TPromise { - return this.doOpenSettings(ConfigurationTarget.FOLDER, this.getEditableSettingsURI(ConfigurationTarget.FOLDER, folder), position); + openFolderSettings(folder: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { + return this.doOpenSettings(ConfigurationTarget.FOLDER, this.getEditableSettingsURI(ConfigurationTarget.FOLDER, folder), options, position); } switchSettings(target: ConfigurationTarget, resource: URI): TPromise { @@ -249,17 +249,23 @@ export class PreferencesService extends Disposable implements IPreferencesServic }); } - private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, position?: EditorPosition): TPromise { + private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { const openDefaultSettings = !!this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value; return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource) .then(editableSettingsEditorInput => { + if (!options) { + options = { pinned: true }; + } else { + options.pinned = true; + } + if (openDefaultSettings) { const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(configurationTarget)); const preferencesEditorInput = new PreferencesEditorInput(this.getPreferencesEditorInputName(configurationTarget, resource), editableSettingsEditorInput.getDescription(), defaultPreferencesEditorInput, editableSettingsEditorInput); this.lastOpenedSettingsInput = preferencesEditorInput; - return this.editorService.openEditor(preferencesEditorInput, { pinned: true }, position); + return this.editorService.openEditor(preferencesEditorInput, options, position); } - return this.editorService.openEditor(editableSettingsEditorInput, { pinned: true }, position); + return this.editorService.openEditor(editableSettingsEditorInput, options, position); }); } diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index ac93b8ec775..d75d4737b73 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IEditor, Position } from 'vs/platform/editor/common/editor'; +import { IEditor, Position, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IKeybindingItemEntry } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel'; import { IRange } from 'vs/editor/common/core/range'; import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; @@ -77,9 +77,9 @@ export interface IPreferencesService { resolveContent(uri: URI): TPromise; createPreferencesEditorModel(uri: URI): TPromise>; - openGlobalSettings(position?: Position): TPromise; - openWorkspaceSettings(position?: Position): TPromise; - openFolderSettings(folder: URI, position?: Position): TPromise; + openGlobalSettings(options?: IEditorOptions, position?: Position): TPromise; + openWorkspaceSettings(options?: IEditorOptions, position?: Position): TPromise; + openFolderSettings(folder: URI, options?: IEditorOptions, position?: Position): TPromise; switchSettings(target: ConfigurationTarget, resource: URI): TPromise; openGlobalKeybindingSettings(textual: boolean): TPromise; diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index ac091d532ca..48e0ef167d2 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -67,7 +67,7 @@ export class PreferencesContribution implements IWorkbenchContribution { // Global User Settings File if (resource.fsPath === this.environmentService.appSettingsPath) { - return event.prevent(() => this.preferencesService.openGlobalSettings(event.position)); + return event.prevent(() => this.preferencesService.openGlobalSettings(event.options, event.position)); } // Single Folder Workspace Settings File @@ -75,7 +75,7 @@ export class PreferencesContribution implements IWorkbenchContribution { if (state === WorkbenchState.FOLDER) { const folders = this.workspaceService.getWorkspace().folders; if (resource.fsPath === folders[0].toResource(FOLDER_SETTINGS_PATH).fsPath) { - return event.prevent(() => this.preferencesService.openWorkspaceSettings(event.position)); + return event.prevent(() => this.preferencesService.openWorkspaceSettings(event.options, event.position)); } } @@ -84,7 +84,7 @@ export class PreferencesContribution implements IWorkbenchContribution { const folders = this.workspaceService.getWorkspace().folders; for (let i = 0; i < folders.length; i++) { if (resource.fsPath === folders[i].toResource(FOLDER_SETTINGS_PATH).fsPath) { - return event.prevent(() => this.preferencesService.openFolderSettings(folders[i].uri, event.position)); + return event.prevent(() => this.preferencesService.openFolderSettings(folders[i].uri, event.options, event.position)); } } } From fedf6fdcb6e6331297e51f066d8aad8ae54bac00 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 Oct 2017 18:14:10 +0200 Subject: [PATCH 093/394] Add a flag that switches between decorations implementations --- src/vs/editor/common/editorCommon.ts | 7 + src/vs/editor/common/model/intervalTree.ts | 156 ++++++++++++ src/vs/editor/common/model/textModel.ts | 72 +++++- .../common/model/textModelWithDecorations.ts | 240 +++++++++++++++++- .../common/viewModel/viewModelDecorations.ts | 8 +- src/vs/monaco.d.ts | 6 + 6 files changed, 479 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index ab9db53d0ce..e0f3ad0a160 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -1034,6 +1034,13 @@ export interface ITextModelWithDecorations { * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). */ getAllDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + + /** + * Gets all the decorations that should be rendered in the overview ruler as an array. + * @param ownerId If set, it will ignore decorations belonging to other owners. + * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). + */ + getOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; } /** diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 62888a2f05c..df602db753f 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -131,6 +131,24 @@ export class IntervalTree { return intervalSearch(this, start, end, filterOwnerId, filterOutValidation, cachedVersionId); } + public search(filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { + if (this.root === SENTINEL) { + return []; + } + return search(this, filterOwnerId, filterOutValidation, overviewRulerOnly, cachedVersionId); + } + + public count(): number { + return nodeCount(this); + } + + /** + * Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes! + */ + public collectNodesFromOwner(ownerId: number): IntervalNode[] { + return collectNodesFromOwner(this, ownerId); + } + public insert(node: IntervalNode): void { rbTreeInsert(this, node); } @@ -214,6 +232,144 @@ export class IntervalTree { //#region Searching +function nodeCount(T: IntervalTree): number { + let node = T.root; + let count = 0; + while (node !== SENTINEL) { + if (node.visited) { + // going up from this node + node.left.visited = false; + node.right.visited = false; + node = node.parent; + continue; + } + + if (node.left !== SENTINEL && !node.left.visited) { + // go left + node = node.left; + continue; + } + + // handle current node + count++; + node.visited = true; + + if (node.right !== SENTINEL && !node.right.visited) { + // go right + node = node.right; + continue; + } + } + + if (T.root) { + T.root.visited = false; + } + + return count; +} + +function collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] { + let node = T.root; + let result: IntervalNode[] = []; + let resultLen = 0; + while (node !== SENTINEL) { + if (node.visited) { + // going up from this node + node.left.visited = false; + node.right.visited = false; + node = node.parent; + continue; + } + + if (node.left !== SENTINEL && !node.left.visited) { + // go left + node = node.left; + continue; + } + + // handle current node + if (node.ownerId === ownerId) { + result[resultLen++] = node; + } + + node.visited = true; + + if (node.right !== SENTINEL && !node.right.visited) { + // go right + node = node.right; + continue; + } + } + + if (T.root) { + T.root.visited = false; + } + + return result; +} + +function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { + let node = T.root; + let delta = 0; + let nodeStart = 0; + let nodeEnd = 0; + let result: IntervalNode[] = []; + let resultLen = 0; + while (node !== SENTINEL) { + if (node.visited) { + // going up from this node + node.left.visited = false; + node.right.visited = false; + if (node === node.parent.right) { + delta -= node.parent.delta; + } + node = node.parent; + continue; + } + + if (node.left !== SENTINEL && !node.left.visited) { + // go left + node = node.left; + continue; + } + + // handle current node + nodeStart = delta + node.start; + nodeEnd = delta + node.end; + + node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); + + let include = true; + if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) { + include = false; + } + if (filterOutValidation && node.isForValidation) { + include = false; + } + if (overviewRulerOnly && !node.options.overviewRuler.color) { + include = false; + } + if (include) { + result[resultLen++] = node; + } + + node.visited = true; + + if (node.right !== SENTINEL && !node.right.visited) { + // go right + delta += node.delta; + node = node.right; + continue; + } + } + + if (T.root) { + T.root.visited = false; + } + + return result; +} + function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree // Now, it is known that two intervals A and B overlap only when both diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 3e55882ed96..4af332e8f14 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -261,7 +261,7 @@ export class TextModel implements editorCommon.ITextModel { return this._alternativeVersionId; } - private _ensureLineStarts(): void { + protected _ensureLineStarts(): void { if (!this._lineStarts) { const eolLength = this._EOL.length; const linesLength = this._lines.length; @@ -607,6 +607,76 @@ export class TextModel implements editorCommon.ITextModel { return lineNumber; } + /** + * Validates `range` is within buffer bounds, but allows it to sit in between surrogate pairs, etc. + * Will try to not allocate if possible. + */ + protected _validateRangeRelaxedNoAllocations(range: IRange): Range { + const linesCount = this._lines.length; + + const initialStartLineNumber = range.startLineNumber; + const initialStartColumn = range.startColumn; + let startLineNumber: number; + let startColumn: number; + + if (initialStartLineNumber < 1) { + startLineNumber = 1; + startColumn = 1; + } else if (initialStartLineNumber > linesCount) { + startLineNumber = linesCount; + startColumn = this.getLineMaxColumn(startLineNumber); + } else { + startLineNumber = initialStartLineNumber | 0; + if (initialStartColumn <= 1) { + startColumn = 1; + } else { + const maxColumn = this.getLineMaxColumn(startLineNumber); + if (initialStartColumn >= maxColumn) { + startColumn = maxColumn; + } else { + startColumn = initialStartColumn | 0; + } + } + } + + const initialEndLineNumber = range.endLineNumber; + const initialEndColumn = range.endColumn; + let endLineNumber: number; + let endColumn: number; + + if (initialEndLineNumber < 1) { + endLineNumber = 1; + endColumn = 1; + } else if (initialEndLineNumber > linesCount) { + endLineNumber = linesCount; + endColumn = this.getLineMaxColumn(endLineNumber); + } else { + endLineNumber = initialEndLineNumber | 0; + if (initialEndColumn <= 1) { + endColumn = 1; + } else { + const maxColumn = this.getLineMaxColumn(endLineNumber); + if (initialEndColumn >= maxColumn) { + endColumn = maxColumn; + } else { + endColumn = initialEndColumn | 0; + } + } + } + + if ( + initialStartLineNumber === startLineNumber + && initialStartColumn === startColumn + && initialEndLineNumber === endLineNumber + && initialEndColumn === endColumn + && range instanceof Range + ) { + return range; + } + + return new Range(startLineNumber, startColumn, endLineNumber, endColumn); + } + /** * @param strict Do NOT allow a position inside a high-low surrogate pair */ diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 9ed9c9a16e6..2b9befae2f9 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -17,6 +17,9 @@ import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; +import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; + +const USE_NEW_DECORATIONS = false; export const ClassName = { EditorInfoDecoration: 'infosquiggly', @@ -134,6 +137,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _currentMarkersTracker: MarkersTracker; private _currentMarkersTrackerCnt: number; + private _tree: IntervalTree; + private _treeDecorations: { [decorationId: string]: IntervalNode; }; + private _decorations: { [decorationId: string]: InternalDecoration; }; private _internalDecorations: { [internalDecorationId: number]: InternalDecoration; }; private _multiLineDecorationsMap: { [key: string]: InternalDecoration; }; @@ -151,6 +157,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._currentMarkersTracker = null; this._currentMarkersTrackerCnt = 0; + this._tree = new IntervalTree(); + this._treeDecorations = Object.create(null); + this._decorations = Object.create(null); this._internalDecorations = Object.create(null); this._multiLineDecorationsMap = Object.create(null); @@ -187,6 +196,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } _getTrackedRangesCount(): number { + if (USE_NEW_DECORATIONS) { + return this._tree.count(); + } return Object.keys(this._decorations).length; } @@ -208,18 +220,36 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _changeDecorations(decorationsTracker: DecorationsTracker, ownerId: number, callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T): T { let changeAccessor: editorCommon.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: editorCommon.IModelDecorationOptions): string => { + if (USE_NEW_DECORATIONS) { + return this._deltaDecorationsImpl2(decorationsTracker, [], this._normalizeDeltaDecorations2(ownerId, [{ range: range, options: options }]))[0]; + } return this._addDecorationImpl(decorationsTracker, ownerId, this.validateRange(range), _normalizeOptions(options)); }, changeDecoration: (id: string, newRange: IRange): void => { + if (USE_NEW_DECORATIONS) { + this._changeDecorationImpl2(decorationsTracker, id, newRange); + return; + } this._changeDecorationImpl(decorationsTracker, id, this.validateRange(newRange)); }, changeDecorationOptions: (id: string, options: editorCommon.IModelDecorationOptions) => { + if (USE_NEW_DECORATIONS) { + this._changeDecorationOptionsImpl2(decorationsTracker, id, _normalizeOptions(options)); + return; + } this._changeDecorationOptionsImpl(decorationsTracker, id, _normalizeOptions(options)); }, removeDecoration: (id: string): void => { + if (USE_NEW_DECORATIONS) { + this._deltaDecorationsImpl2(decorationsTracker, [id], []); + return; + } this._removeDecorationImpl(decorationsTracker, id); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { + if (USE_NEW_DECORATIONS) { + return this._deltaDecorationsImpl2(decorationsTracker, oldDecorations, this._normalizeDeltaDecorations2(ownerId, newDecorations)); + } return this._deltaDecorationsImpl(decorationsTracker, ownerId, oldDecorations, this._normalizeDeltaDecorations(newDecorations)); } }; @@ -248,6 +278,16 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } public removeAllDecorationsWithOwnerId(ownerId: number): void { + if (USE_NEW_DECORATIONS) { + const nodes = this._tree.collectNodesFromOwner(ownerId); + for (let i = 0, len = nodes.length; i < len; i++) { + const node = nodes[i]; + + this._tree.delete(node); + delete this._treeDecorations[node.id]; + } + return; + } let toRemove: string[] = []; for (let decorationId in this._decorations) { @@ -264,6 +304,13 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } public getDecorationOptions(decorationId: string): editorCommon.IModelDecorationOptions { + if (USE_NEW_DECORATIONS) { + const node = this._treeDecorations[decorationId]; + if (!node) { + return null; + } + return node.options; + } let decoration = this._decorations[decorationId]; if (!decoration) { return null; @@ -271,7 +318,34 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return decoration.options; } + private _getRangeAt(start: number, end: number): Range { + const startResult = this._lineStarts.getIndexOf(start); + const startLineLength = this._lines[startResult.index].text.length; + const startColumn = Math.min(startResult.remainder + 1, startLineLength + 1); + + const endResult = this._lineStarts.getIndexOf(end); + const endLineLength = this._lines[endResult.index].text.length; + const endColumn = Math.min(endResult.remainder + 1, endLineLength + 1); + + return new Range(startResult.index + 1, startColumn, endResult.index + 1, endColumn); + } + public getDecorationRange(decorationId: string): Range { + if (USE_NEW_DECORATIONS) { + const node = this._treeDecorations[decorationId]; + if (!node) { + return null; + } + const versionId = this.getVersionId(); + if (node.cachedVersionId !== versionId) { + this._tree.resolveNode(node, versionId); + } + if (node.range === null) { + this._ensureLineStarts(); + node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); + } + return node.range; + } let decoration = this._decorations[decorationId]; if (!decoration) { return null; @@ -331,7 +405,31 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return result; } - private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): InternalDecoration[] { + private _ensureNodesHaveRanges(nodes: IntervalNode[]): IntervalNode[] { + this._ensureLineStarts(); + + for (let i = 0, len = nodes.length; i < len; i++) { + const node = nodes[i]; + if (node.range === null) { + node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); + } + } + return nodes; + } + + private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): IntervalNode[] | InternalDecoration[] { + if (USE_NEW_DECORATIONS) { + this._ensureLineStarts(); + + const startOffset = this._lineStarts.getAccumulatedValue(filterRange.startLineNumber - 2) + filterRange.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(filterRange.endLineNumber - 2) + filterRange.endColumn - 1; + + const versionId = this.getVersionId(); + const result = this._tree.intervalSearch(startOffset, endOffset, filterOwnerId, filterOutValidation, versionId); + + return this._ensureNodesHaveRanges(result); + } + const filterStartLineNumber = filterRange.startLineNumber; const filterStartColumn = filterRange.startColumn; const filterEndLineNumber = filterRange.endLineNumber; @@ -405,12 +503,47 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return this._getDecorationsInRange(new Range(startLineNumber, 1, endLineNumber, endColumn), ownerId, filterOutValidation); } - public getDecorationsInRange(range: IRange, ownerId?: number, filterOutValidation?: boolean): editorCommon.IModelDecoration[] { + public getDecorationsInRange(range: IRange, ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { let validatedRange = this.validateRange(range); return this._getDecorationsInRange(validatedRange, ownerId, filterOutValidation); } + public getOverviewRulerDecorations(ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { + if (USE_NEW_DECORATIONS) { + const versionId = this.getVersionId(); + const result = this._tree.search(ownerId, filterOutValidation, true, versionId); + return this._ensureNodesHaveRanges(result); + } + let result: InternalDecoration[] = [], resultLen = 0; + + for (let decorationId in this._decorations) { + // No `hasOwnProperty` call due to using Object.create(null) + let decoration = this._decorations[decorationId]; + + if (ownerId && decoration.ownerId && decoration.ownerId !== ownerId) { + continue; + } + + if (filterOutValidation && decoration.isForValidation) { + continue; + } + + if (!decoration.options.overviewRuler.color) { + continue; + } + + result[resultLen++] = decoration; + } + + return result; + } + public getAllDecorations(ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { + if (USE_NEW_DECORATIONS) { + const versionId = this.getVersionId(); + const result = this._tree.search(ownerId, filterOutValidation, false, versionId); + return this._ensureNodesHaveRanges(result); + } let result: InternalDecoration[] = [], resultLen = 0; for (let decorationId in this._decorations) { @@ -542,6 +675,30 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return result; } + private _normalizeDeltaDecorations2(ownerId: number, deltaDecorations: editorCommon.IModelDeltaDecoration[]): IntervalNode[] { + this._ensureLineStarts(); + + const versionId = this.getVersionId(); + let result = new Array(deltaDecorations.length); + for (let i = 0, len = deltaDecorations.length; i < len; i++) { + const dec = deltaDecorations[i]; + const range = this._validateRangeRelaxedNoAllocations(dec.range); + const options = _normalizeOptions(dec.options); + + const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; + + const node = new IntervalNode(null, startOffset, endOffset); + node.ownerId = ownerId; + node.cachedVersionId = versionId; + node.range = range; + node.setOptions(options); + + result[i] = node; + } + return result; + } + private _externalDecorationId(internalId: number): string { return `${this._instanceId};${internalId}`; } @@ -629,6 +786,25 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return decorationIds; } + private _addDecorationsImpl2(decorationsTracker: DecorationsTracker, newDecorations: IntervalNode[]): string[] { + + let decorationIds: string[] = new Array(newDecorations.length); + for (let i = 0, len = newDecorations.length; i < len; i++) { + const node = newDecorations[i]; + const internalDecorationId = (++this._lastDecorationId); + const decorationId = this._externalDecorationId(internalDecorationId); + node.id = decorationId; + + this._tree.insert(node); + this._treeDecorations[decorationId] = node; + decorationIds[i] = decorationId; + } + + decorationsTracker.markDidAddDecorations(); + + return decorationIds; + } + private _changeDecorationImpl(decorationsTracker: DecorationsTracker, decorationId: string, newRange: Range): void { let decoration = this._decorations[decorationId]; if (!decoration) { @@ -656,6 +832,24 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed decorationsTracker.markDidChangeDecorations(); } + private _changeDecorationImpl2(decorationsTracker: DecorationsTracker, decorationId: string, _range: IRange): void { + const node = this._treeDecorations[decorationId]; + if (!node) { + return; + } + const range = this._validateRangeRelaxedNoAllocations(_range); + const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; + + this._tree.delete(node); + + node.setCachedOffsets(startOffset, endOffset, this.getVersionId()); + node.range = range; + this._tree.insert(node); + + decorationsTracker.markDidChangeDecorations(); + } + private _changeDecorationOptionsImpl(decorationsTracker: DecorationsTracker, decorationId: string, options: ModelDecorationOptions): void { let decoration = this._decorations[decorationId]; if (!decoration) { @@ -672,6 +866,17 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed decorationsTracker.markDidChangeDecorations(); } + private _changeDecorationOptionsImpl2(decorationsTracker: DecorationsTracker, decorationId: string, options: ModelDecorationOptions): void { + const node = this._treeDecorations[decorationId]; + if (!node) { + return; + } + + node.setOptions(options); + + decorationsTracker.markDidChangeDecorations(); + } + private _removeDecorationImpl(decorationsTracker: DecorationsTracker, decorationId: string): void { let decoration = this._decorations[decorationId]; if (!decoration) { @@ -715,6 +920,23 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } } + private _removeDecorationsImpl2(decorationsTracker: DecorationsTracker, decorationIds: string[]): void { + for (let i = 0, len = decorationIds.length; i < len; i++) { + const decorationId = decorationIds[i]; + const node = this._treeDecorations[decorationId]; + if (!node) { + continue; + } + + this._tree.delete(node); + delete this._treeDecorations[decorationId]; + } + + if (decorationsTracker) { + decorationsTracker.markDidRemoveDecorations(); + } + } + private _resolveOldDecorations(oldDecorations: string[]): InternalDecoration[] { let result: InternalDecoration[] = []; for (let i = 0, len = oldDecorations.length; i < len; i++) { @@ -816,6 +1038,18 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return result; } + + private _deltaDecorationsImpl2(decorationsTracker: DecorationsTracker, oldDecorationsIds: string[], newDecorations: IntervalNode[]): string[] { + // TODO@interval: is it worth it to compare? + if (oldDecorationsIds.length > 0) { + this._removeDecorationsImpl2(decorationsTracker, oldDecorationsIds); + } + + if (newDecorations.length > 0) { + return this._addDecorationsImpl2(decorationsTracker, newDecorations); + } + return []; + } } function cleanClassName(className: string): string { @@ -931,6 +1165,8 @@ ModelDecorationOptions.EMPTY = ModelDecorationOptions.register({}); class ModelDeltaDecoration implements editorCommon.IModelDeltaDecoration { + _modelDeltaDecorationBrand: void; + index: number; range: Range; options: ModelDecorationOptions; diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index 59205a10171..be7a324004a 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -89,16 +89,10 @@ export class ViewModelDecorations implements IDisposable { } public getAllOverviewRulerDecorations(): ViewModelDecoration[] { - let modelDecorations = this.model.getAllDecorations(this.editorId, this.configuration.editor.readOnly); + let modelDecorations = this.model.getOverviewRulerDecorations(this.editorId, this.configuration.editor.readOnly); let result: ViewModelDecoration[] = [], resultLen = 0; for (let i = 0, len = modelDecorations.length; i < len; i++) { let modelDecoration = modelDecorations[i]; - let decorationOptions = modelDecoration.options; - - if (!decorationOptions.overviewRuler.color) { - continue; - } - let viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration); result[resultLen++] = viewModelDecoration; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 96c24eb1b18..4b4e91c9824 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1717,6 +1717,12 @@ declare module monaco.editor { * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). */ getAllDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + /** + * Gets all the decorations that should be rendered in the overview ruler as an array. + * @param ownerId If set, it will ignore decorations belonging to other owners. + * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). + */ + getOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; } /** From 76c68ae527c087702f55f605cc2cfff2ec069ec8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 Oct 2017 18:19:02 +0200 Subject: [PATCH 094/394] some cleanup in intervalTree.ts --- src/vs/editor/common/model/intervalTree.ts | 41 +++---------------- .../test/common/model/intervalTree.test.ts | 16 +++++++- 2 files changed, 19 insertions(+), 38 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index df602db753f..b1e0cb4fa44 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -19,18 +19,6 @@ export const ClassName = { EditorErrorDecoration: 'errorsquiggly' }; -export class Interval { - _intervalBrand: void; - - public start: number; - public end: number; - - constructor(start: number, end: number) { - this.start = start; - this.end = end; - } -} - export const enum NodeColor { Red, Black @@ -139,6 +127,9 @@ export class IntervalTree { } public count(): number { + if (this.root === SENTINEL) { + return 0; + } return nodeCount(this); } @@ -183,30 +174,8 @@ export class IntervalTree { assertValidTree(this); } - public getAllInOrder(): Interval[] { - let r: Interval[] = [], rLength = 0; - this.visitInOrder((n, delta) => { - r[rLength++] = new Interval(n.start + delta, n.end + delta); - }); - return r; - } - - public visitInOrder(visitor: (n: IntervalNode, delta: number) => void): void { - this._visitInOrder(this.root, 0, visitor); - } - - private _visitInOrder(n: IntervalNode, delta: number, visitor: (n: IntervalNode, delta: number) => void): void { - if (n.left !== SENTINEL) { - this._visitInOrder(n.left, delta, visitor); - } - - if (n !== SENTINEL) { - visitor(n, delta); - } - - if (n.right !== SENTINEL) { - this._visitInOrder(n.right, delta + n.delta, visitor); - } + public getAllInOrder(): IntervalNode[] { + return search(this, 0, false, false, 0); } public print(): void { diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index 1ece94f8b43..f5ab68fcb0c 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { IntervalTree, Interval, IntervalNode } from 'vs/editor/common/model/intervalTree'; +import { IntervalTree, IntervalNode } from 'vs/editor/common/model/intervalTree'; const GENERATE_TESTS = false; let TEST_COUNT = GENERATE_TESTS ? 10000 : 0; @@ -17,6 +17,18 @@ const MAX_INSERTS = 30; suite('IntervalTree', () => { + class Interval { + _intervalBrand: void; + + public start: number; + public end: number; + + constructor(start: number, end: number) { + this.start = start; + this.end = end; + } + } + class Oracle { public intervals: Interval[]; @@ -96,7 +108,7 @@ suite('IntervalTree', () => { this._tree.assertInvariants(); - let actual = this._tree.getAllInOrder(); + let actual = this._tree.getAllInOrder().map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd)); let expected = this._oracle.intervals; assert.deepEqual(actual, expected); } From fa5556c3abf12f20c78bedd7a645a90777331001 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 09:45:23 -0700 Subject: [PATCH 095/394] Add support for dim text in the terminal Fixes #36238 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a3b4ae130d4..03a12f907f7 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "2.9.1", "from": "Tyriar/xterm.js#vscode-release/1.18", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#14b0137accaf350565a005d68e91f03c96a241be" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#b84b02d4b3ba962072822d923d7040fce80a4227" }, "yauzl": { "version": "2.8.0", From 3d6b6ac91c90c894018b9fbd5bf5b05fec4fbdc9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 10:00:35 -0700 Subject: [PATCH 096/394] Focus terminal when clicking a link that doesn't activate Fixes #36187 --- .../terminal/electron-browser/terminalLinkHandler.ts | 7 ++++++- .../test/electron-browser/terminalLinkHandler.test.ts | 10 +++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts index 83b76d604ac..8650646c7ad 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts @@ -14,6 +14,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { TerminalWidgetManager } from 'vs/workbench/parts/terminal/browser/terminalWidgetManager'; import { TPromise } from 'vs/base/common/winjs.base'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; const pathPrefix = '(\\.\\.?|\\~)'; const pathSeparatorClause = '\\/'; @@ -67,7 +68,8 @@ export class TerminalLinkHandler { private _initialCwd: string, @IOpenerService private _openerService: IOpenerService, @IWorkbenchEditorService private _editorService: IWorkbenchEditorService, - @IConfigurationService private _configurationService: IConfigurationService + @IConfigurationService private _configurationService: IConfigurationService, + @ITerminalService private _terminalService: ITerminalService ) { const baseLocalLinkClause = _platform === platform.Platform.Windows ? winLocalLinkClause : unixLocalLinkClause; // Append line and column number regex @@ -120,6 +122,9 @@ export class TerminalLinkHandler { event.preventDefault(); // Require correct modifier on click if (!this._isLinkActivationModifierDown(event)) { + // If the modifier is not pressed, the terminal should be + // focused if it's not already + this._terminalService.getActiveInstance().focus(true); return false; } return handler(uri); diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts index 77d9fed7145..491637a485c 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -35,7 +35,7 @@ interface LinkFormatInfo { suite('Workbench - TerminalLinkHandler', () => { suite('localLinkRegex', () => { test('Windows', () => { - const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null, null, null, null); + const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null, null, null, null, null); function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) { assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl); assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl); @@ -105,7 +105,7 @@ suite('Workbench - TerminalLinkHandler', () => { }); test('Linux', () => { - const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null, null, null, null); + const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null, null, null, null, null); function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) { assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl); assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl); @@ -169,7 +169,7 @@ suite('Workbench - TerminalLinkHandler', () => { suite('preprocessPath', () => { test('Windows', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, 'C:\\base', null, null, null); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, 'C:\\base', null, null, null, null); let stub = sinon.stub(path, 'join', function (arg1, arg2) { return arg1 + '\\' + arg2; @@ -182,7 +182,7 @@ suite('Workbench - TerminalLinkHandler', () => { }); test('Linux', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, '/base', null, null, null); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, '/base', null, null, null, null); let stub = sinon.stub(path, 'join', function (arg1, arg2) { return arg1 + '/' + arg2; @@ -195,7 +195,7 @@ suite('Workbench - TerminalLinkHandler', () => { }); test('No Workspace', () => { - const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null, null, null, null); + const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null, null, null, null, null); assert.equal(linkHandler.preprocessPath('./src/file1'), null); assert.equal(linkHandler.preprocessPath('src/file2'), null); From 711167f7bb1db9cc7b5e5314cf8a685485657cb7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 13:23:50 -0700 Subject: [PATCH 097/394] Update xterm.js to support enableBold Part of #35666 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 03a12f907f7..dd103542200 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "2.9.1", "from": "Tyriar/xterm.js#vscode-release/1.18", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#b84b02d4b3ba962072822d923d7040fce80a4227" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#d57ac8df05ddf04b509505eadc0d408a0b3bfa38" }, "yauzl": { "version": "2.8.0", From d47a1babc298bf64b555c9336c9842f32920cb28 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 13:31:50 -0700 Subject: [PATCH 098/394] Pull in latest typings --- src/typings/xterm.d.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/typings/xterm.d.ts b/src/typings/xterm.d.ts index 197f2e7ebc8..ceed656bf3f 100644 --- a/src/typings/xterm.d.ts +++ b/src/typings/xterm.d.ts @@ -41,6 +41,11 @@ interface ITerminalOptions { */ disableStdin?: boolean; + /** + * Whether to enable the rendering of bold text. + */ + enableBold?: boolean; + /** * The font size used to render text. */ @@ -397,7 +402,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; + getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -447,7 +452,7 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; + setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; /** * Sets an option on the terminal. * @param key The option key. From a763c7a0cb92d5ac86f7f7779943977cca820f76 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 13:34:39 -0700 Subject: [PATCH 099/394] Add support for terminal.integrated.enableBold back Fixes #35666 --- src/vs/workbench/parts/terminal/common/terminal.ts | 2 +- .../terminal/electron-browser/terminal.contribution.ts | 10 +++++----- .../terminal/electron-browser/terminalInstance.ts | 6 +++++- .../parts/terminal/electron-browser/terminalPanel.ts | 2 -- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index 93ffb4af4c6..fe4841ac5ec 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -58,7 +58,7 @@ export interface ITerminalConfiguration { osx: string[]; windows: string[]; }; - // enableBold: boolean; + enableBold: boolean; rightClickCopyPaste: boolean; cursorBlinking: boolean; cursorStyle: string; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index f5d947c4492..7a048fb9732 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -140,11 +140,11 @@ configurationRegistry.registerConfiguration({ 'type': 'number', 'default': 1 }, - // 'terminal.integrated.enableBold': { - // 'type': 'boolean', - // 'description': nls.localize('terminal.integrated.enableBold', "Whether to enable bold text within the terminal, this requires support from the terminal shell."), - // 'default': true - // }, + 'terminal.integrated.enableBold': { + 'type': 'boolean', + 'description': nls.localize('terminal.integrated.enableBold', "Whether to enable bold text within the terminal, note that this requires support from the terminal shell."), + 'default': true + }, 'terminal.integrated.cursorBlinking': { 'description': nls.localize('terminal.integrated.cursorBlinking', "Controls whether the terminal cursor blinks."), 'type': 'boolean', diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index 113ed5e0e48..7467fe7724d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -266,7 +266,8 @@ export class TerminalInstance implements ITerminalInstance { theme: this._getXtermTheme(), fontFamily: font.fontFamily, fontSize: font.fontSize, - lineHeight: font.lineHeight + lineHeight: font.lineHeight, + enableBold: this._configHelper.config.enableBold }); if (this._shellLaunchConfig.initialText) { this._xterm.writeln(this._shellLaunchConfig.initialText); @@ -923,6 +924,9 @@ export class TerminalInstance implements ITerminalInstance { if (this._xterm.getOption('fontFamily') !== font.fontFamily) { this._xterm.setOption('fontFamily', font.fontFamily); } + if (this._xterm.getOption('enableBold') !== this._configHelper.config.enableBold) { + this._xterm.setOption('enableBold', this._configHelper.config.enableBold); + } this._xterm.resize(this._cols, this._rows); this._xterm.element.style.width = terminalWidth + 'px'; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 56a3523d7e2..9acf376fef2 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -302,8 +302,6 @@ export class TerminalPanel extends Panel { this._font = this._terminalService.configHelper.getFont(); // TODO: Can we support ligatures? // dom.toggleClass(this._parentDomElement, 'enable-ligatures', this._terminalService.configHelper.config.fontLigatures); - // TODO: How to handle Disable bold? - // dom.toggleClass(this._parentDomElement, 'disable-bold', !this._terminalService.configHelper.config.enableBold); this.layout(new Dimension(this._parentDomElement.offsetWidth, this._parentDomElement.offsetHeight)); } From 3a54e322918b8845dec3fd20de84656272bb2d04 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 13 Oct 2017 14:19:46 -0700 Subject: [PATCH 100/394] Update TypeScript to use new task API Fixes #35371 --- extensions/typescript/src/features/taskProvider.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/typescript/src/features/taskProvider.ts b/extensions/typescript/src/features/taskProvider.ts index 290c07a7709..d7d042e9abb 100644 --- a/extensions/typescript/src/features/taskProvider.ts +++ b/extensions/typescript/src/features/taskProvider.ts @@ -168,6 +168,7 @@ class TscTaskProvider implements vscode.TaskProvider { const buildTaskidentifier: TypeScriptTaskDefinition = { type: 'typescript', tsconfig: label }; const buildTask = new vscode.Task( buildTaskidentifier, + project.workspaceFolder || vscode.TaskScope.Workspace, localize('buildTscLabel', 'build - {0}', label), 'tsc', new vscode.ShellExecution(`${command} -p "${project.path}"`), @@ -181,6 +182,7 @@ class TscTaskProvider implements vscode.TaskProvider { const watchTaskidentifier: TypeScriptTaskDefinition = { type: 'typescript', tsconfig: label, option: 'watch' }; const watchTask = new vscode.Task( watchTaskidentifier, + project.workspaceFolder || vscode.TaskScope.Workspace, localize('buildAndWatchTscLabel', 'watch - {0}', label), 'tsc', new vscode.ShellExecution(`${command} --watch -p "${project.path}"`), From 9613018ef0a7c16be99a4fdf331addafd05eb410 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 13 Oct 2017 14:46:12 -0700 Subject: [PATCH 101/394] Update ts grammar --- .../syntaxes/JavaScript.tmLanguage.json | 9 ++-- .../syntaxes/JavaScriptReact.tmLanguage.json | 9 ++-- .../test/colorize-results/test_jsx.json | 52 +++++++++---------- .../syntaxes/TypeScript.tmLanguage.json | 8 +-- .../syntaxes/TypeScriptReact.tmLanguage.json | 9 ++-- 5 files changed, 37 insertions(+), 50 deletions(-) diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index 85546d41404..7b1ec3d76c5 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/824f47ea6e98590ac2e75db5bebdf6eff71421ad", "name": "JavaScript (with React support)", "scopeName": "source.js", "fileTypes": [ @@ -1707,8 +1707,7 @@ "include": "#comment" }, { - "comment": "(default|*|name) as alias", - "match": "(?x) (?: \\b(default)\\b | (\\*) | ([_$[:alpha:]][_$[:alnum:]]*)) \\s+\n (as) \\s+ (?: (\\b default \\b | \\*) | ([_$[:alpha:]][_$[:alnum:]]*))", + "match": "(?)", + "contentName": "meta.tag.attributes.js", "patterns": [ { "include": "#comment" diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json index 0de22f4d7a9..f0ad9fc5c29 100644 --- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/824f47ea6e98590ac2e75db5bebdf6eff71421ad", "name": "JavaScript (with React support)", "scopeName": "source.js.jsx", "fileTypes": [ @@ -1707,8 +1707,7 @@ "include": "#comment" }, { - "comment": "(default|*|name) as alias", - "match": "(?x) (?: \\b(default)\\b | (\\*) | ([_$[:alpha:]][_$[:alnum:]]*)) \\s+\n (as) \\s+ (?: (\\b default \\b | \\*) | ([_$[:alpha:]][_$[:alnum:]]*))", + "match": "(?)", + "contentName": "meta.tag.attributes.js.jsx", "patterns": [ { "include": "#comment" diff --git a/extensions/javascript/test/colorize-results/test_jsx.json b/extensions/javascript/test/colorize-results/test_jsx.json index 9a5a14a90b7..7824e567af2 100644 --- a/extensions/javascript/test/colorize-results/test_jsx.json +++ b/extensions/javascript/test/colorize-results/test_jsx.json @@ -1772,7 +1772,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1783,7 +1783,7 @@ }, { "c": "href", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx entity.other.attribute-name.js.jsx", "r": { "dark_plus": "entity.other.attribute-name: #9CDCFE", "light_plus": "entity.other.attribute-name: #FF0000", @@ -1794,7 +1794,7 @@ }, { "c": "=", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx keyword.operator.assignment.js.jsx", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1805,7 +1805,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1816,7 +1816,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1827,7 +1827,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1838,7 +1838,7 @@ }, { "c": "onClick", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx entity.other.attribute-name.js.jsx", "r": { "dark_plus": "entity.other.attribute-name: #9CDCFE", "light_plus": "entity.other.attribute-name: #FF0000", @@ -1849,7 +1849,7 @@ }, { "c": "=", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx keyword.operator.assignment.js.jsx", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1860,7 +1860,7 @@ }, { "c": "{", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.begin.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.begin.js.jsx", "r": { "dark_plus": "punctuation.section.embedded: #569CD6", "light_plus": "punctuation.section.embedded: #0000FF", @@ -1871,7 +1871,7 @@ }, { "c": "this", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx variable.language.this.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx meta.embedded.expression.js.jsx variable.language.this.js.jsx", "r": { "dark_plus": "variable.language: #569CD6", "light_plus": "variable.language: #0000FF", @@ -1882,7 +1882,7 @@ }, { "c": ".", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.accessor.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx meta.embedded.expression.js.jsx punctuation.accessor.js.jsx", "r": { "dark_plus": "meta.embedded: #D4D4D4", "light_plus": "meta.embedded: #000000", @@ -1893,7 +1893,7 @@ }, { "c": "toggle", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx variable.other.property.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx meta.embedded.expression.js.jsx variable.other.property.js.jsx", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -1904,7 +1904,7 @@ }, { "c": "}", - "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.end.js.jsx", + "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx meta.tag.without-attributes.js.jsx meta.jsx.children.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx meta.embedded.expression.js.jsx punctuation.section.embedded.end.js.jsx", "r": { "dark_plus": "punctuation.section.embedded: #569CD6", "light_plus": "punctuation.section.embedded: #0000FF", @@ -2168,7 +2168,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.tag.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2179,7 +2179,7 @@ }, { "c": "default", - "t": "source.js.jsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx entity.other.attribute-name.js.jsx", "r": { "dark_plus": "entity.other.attribute-name: #9CDCFE", "light_plus": "entity.other.attribute-name: #FF0000", @@ -2190,7 +2190,7 @@ }, { "c": "=", - "t": "source.js.jsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx keyword.operator.assignment.js.jsx", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2201,7 +2201,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2212,7 +2212,7 @@ }, { "c": "World", - "t": "source.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2223,7 +2223,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2234,7 +2234,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.tag.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2245,7 +2245,7 @@ }, { "c": "alt", - "t": "source.js.jsx meta.tag.js.jsx entity.other.attribute-name.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx entity.other.attribute-name.js.jsx", "r": { "dark_plus": "entity.other.attribute-name: #9CDCFE", "light_plus": "entity.other.attribute-name: #FF0000", @@ -2256,7 +2256,7 @@ }, { "c": "=", - "t": "source.js.jsx meta.tag.js.jsx keyword.operator.assignment.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx keyword.operator.assignment.js.jsx", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2267,7 +2267,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx punctuation.definition.string.begin.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2278,7 +2278,7 @@ }, { "c": "Mars", - "t": "source.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2289,7 +2289,7 @@ }, { "c": "\"", - "t": "source.js.jsx meta.tag.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx string.quoted.double.js.jsx punctuation.definition.string.end.js.jsx", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2300,7 +2300,7 @@ }, { "c": " ", - "t": "source.js.jsx meta.tag.js.jsx", + "t": "source.js.jsx meta.tag.js.jsx meta.tag.attributes.js.jsx", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", diff --git a/extensions/typescript/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript/syntaxes/TypeScript.tmLanguage.json index fc4a8971471..454dc854bdf 100644 --- a/extensions/typescript/syntaxes/TypeScript.tmLanguage.json +++ b/extensions/typescript/syntaxes/TypeScript.tmLanguage.json @@ -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/TypeScript-TmLanguage/commit/4109ddc9e27186afcf7263a448c86a59e9aa7d9e", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/f3a2069b99f45c34ac5cc7dc5f1dcb4e81486ab9", "name": "TypeScript", "scopeName": "source.ts", "fileTypes": [ @@ -1701,8 +1701,7 @@ "include": "#comment" }, { - "comment": "(default|*|name) as alias", - "match": "(?x) (?: \\b(default)\\b | (\\*) | ([_$[:alpha:]][_$[:alnum:]]*)) \\s+\n (as) \\s+ (?: (\\b default \\b | \\*) | ([_$[:alpha:]][_$[:alnum:]]*))", + "match": "(?)", + "contentName": "meta.tag.attributes.tsx", "patterns": [ { "include": "#comment" From 989c40066d124cde846cf5ded8364251246e100e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 13 Oct 2017 14:51:04 -0700 Subject: [PATCH 102/394] Fix commenting of jsx attribute using jsx style comments Fixes #36175 --- extensions/javascript/package.json | 2 ++ extensions/typescript/package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index 4d7fa6dff20..866167e1ba6 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -68,6 +68,7 @@ "embeddedLanguages": { "meta.tag.js": "jsx-tags", "meta.tag.without-attributes.js": "jsx-tags", + "meta.tag.attributes.js.jsx": "javascriptreact", "meta.embedded.expression.js": "javascriptreact" } }, @@ -78,6 +79,7 @@ "embeddedLanguages": { "meta.tag.js": "jsx-tags", "meta.tag.without-attributes.js": "jsx-tags", + "meta.tag.attributes.js": "javascript", "meta.embedded.expression.js": "javascript" } }, diff --git a/extensions/typescript/package.json b/extensions/typescript/package.json index 6934e4221bd..ad4545f9355 100644 --- a/extensions/typescript/package.json +++ b/extensions/typescript/package.json @@ -78,6 +78,7 @@ "embeddedLanguages": { "meta.tag.tsx": "jsx-tags", "meta.tag.without-attributes.tsx": "jsx-tags", + "meta.tag.attributes.tsx": "typescriptreact", "meta.embedded.expression.tsx": "typescriptreact" } } From 73635a9cd341fd1b65ccd1003562387f1a76ab58 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 13 Oct 2017 15:35:54 -0700 Subject: [PATCH 103/394] Add option to disable quick suggestions for js/ts paths Fixes #35877 --- extensions/typescript/package.json | 8 ++++- extensions/typescript/package.nls.json | 3 +- .../src/features/completionItemProvider.ts | 30 ++++++++++++------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/extensions/typescript/package.json b/extensions/typescript/package.json index ad4545f9355..3062949aad7 100644 --- a/extensions/typescript/package.json +++ b/extensions/typescript/package.json @@ -393,6 +393,12 @@ ], "description": "%typescript.tsc.autoDetect%", "scope": "resource" + }, + "typescript.quickSuggestionsForPaths": { + "type": "boolean", + "default": true, + "description": "%typescript.quickSuggestionsForPaths%", + "scope": "resource" } } }, @@ -571,4 +577,4 @@ } ] } -} +} \ No newline at end of file diff --git a/extensions/typescript/package.nls.json b/extensions/typescript/package.nls.json index f23e78bf4e1..39725205f50 100644 --- a/extensions/typescript/package.nls.json +++ b/extensions/typescript/package.nls.json @@ -41,5 +41,6 @@ "javascript.nameSuggestions": "Enable/disable including unique names from the file in JavaScript suggestion lists.", "typescript.tsc.autoDetect": "Controls auto detection of tsc tasks. 'off' disables this feature. 'build' only creates single run compile tasks. 'watch' only creates compile and watch tasks. 'on' creates both build and watch tasks. Default is 'on'.", "typescript.problemMatchers.tsc.label": "TypeScript problems", - "typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)" + "typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)", + "typescript.quickSuggestionsForPaths": "Enable/disable quick suggestions when typing out an import path." } diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index 77fe1015a32..f4e46e19cee 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -122,34 +122,36 @@ class MyCompletionItem extends CompletionItem { interface Configuration { useCodeSnippetsOnMethodSuggest: boolean; nameSuggestions: boolean; + quickSuggestionsForPaths: boolean; } namespace Configuration { export const useCodeSnippetsOnMethodSuggest = 'useCodeSnippetsOnMethodSuggest'; export const nameSuggestions = 'nameSuggestions'; + export const quickSuggestionsForPaths = 'quickSuggestionsForPaths'; } export default class TypeScriptCompletionItemProvider implements CompletionItemProvider { - private config: Configuration; + private config: Configuration = { + useCodeSnippetsOnMethodSuggest: false, + nameSuggestions: true, + quickSuggestionsForPaths: true + }; constructor( private client: ITypescriptServiceClient, private typingsStatus: TypingsStatus - ) { - this.config = { - useCodeSnippetsOnMethodSuggest: false, - nameSuggestions: true - }; - } + ) { } public updateConfiguration(): void { // Use shared setting for js and ts const typeScriptConfig = workspace.getConfiguration('typescript'); - this.config.useCodeSnippetsOnMethodSuggest = typeScriptConfig.get(Configuration.useCodeSnippetsOnMethodSuggest, false); - const jsConfig = workspace.getConfiguration('javascript'); - this.config.nameSuggestions = jsConfig.get(Configuration.nameSuggestions, true); + this.config.useCodeSnippetsOnMethodSuggest = typeScriptConfig.get(Configuration.useCodeSnippetsOnMethodSuggest, false); + this.config.quickSuggestionsForPaths = typeScriptConfig.get(Configuration.quickSuggestionsForPaths, true); + + this.config.nameSuggestions = workspace.getConfiguration('javascript').get(Configuration.nameSuggestions, true); } public provideCompletionItems( @@ -175,6 +177,10 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP } if (context.triggerCharacter === '"' || context.triggerCharacter === '\'') { + if (!this.config.quickSuggestionsForPaths) { + return Promise.resolve([]); + } + // make sure we are in something that looks like the start of an import const line = document.lineAt(position.line).text.slice(0, position.character); if (!line.match(/\b(from|import)\s*["']$/) && !line.match(/\b(import|require)\(['"]$/)) { @@ -183,6 +189,10 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP } if (context.triggerCharacter === '/') { + if (!this.config.quickSuggestionsForPaths) { + return Promise.resolve([]); + } + // make sure we are in something that looks like an import path const line = document.lineAt(position.line).text.slice(0, position.character); if (!line.match(/\bfrom\s*["'][^'"]*$/) && !line.match(/\b(import|require)\(['"][^'"]*$/)) { From 3049d48dbbcc259bdca2fb9b0cb115e455fb7266 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 16:37:49 -0700 Subject: [PATCH 104/394] Only update terminal display settings when visible Fixes #35763 --- .../electron-browser/terminalInstance.ts | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index 7467fe7724d..378e96b3648 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -913,24 +913,31 @@ export class TerminalInstance implements ITerminalInstance { if (!terminalWidth) { return; } + if (this._xterm) { const font = this._configHelper.getFont(); - if (this._xterm.getOption('lineHeight') !== font.lineHeight) { - this._xterm.setOption('lineHeight', font.lineHeight); - } - if (this._xterm.getOption('fontSize') !== font.fontSize) { - this._xterm.setOption('fontSize', font.fontSize); - } - if (this._xterm.getOption('fontFamily') !== font.fontFamily) { - this._xterm.setOption('fontFamily', font.fontFamily); - } - if (this._xterm.getOption('enableBold') !== this._configHelper.config.enableBold) { - this._xterm.setOption('enableBold', this._configHelper.config.enableBold); + + // Only apply these settings when the terminal is visible so that + // the characters are measured correctly. + if (this._isVisible) { + if (this._xterm.getOption('lineHeight') !== font.lineHeight) { + this._xterm.setOption('lineHeight', font.lineHeight); + } + if (this._xterm.getOption('fontSize') !== font.fontSize) { + this._xterm.setOption('fontSize', font.fontSize); + } + if (this._xterm.getOption('fontFamily') !== font.fontFamily) { + this._xterm.setOption('fontFamily', font.fontFamily); + } + if (this._xterm.getOption('enableBold') !== this._configHelper.config.enableBold) { + this._xterm.setOption('enableBold', this._configHelper.config.enableBold); + } } this._xterm.resize(this._cols, this._rows); this._xterm.element.style.width = terminalWidth + 'px'; } + this._processReady.then(() => { if (this._process && this._process.connected) { // The child process could aready be terminated From 2963b8ce6327b104bb8604f047bfdd20cd0988f0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 Oct 2017 16:57:50 -0700 Subject: [PATCH 105/394] Changes new terminal actions to show workspace selector All new terminal UI actions except for ctrl+shift+tilde (which remains unchanged) now show a workspace selector in a multi-root context. This includes: - The plus button on the panel - The new terminal option in the term quick open - The context menu shown by right clicking the terminal area Fixes #34163 --- .../terminal/browser/terminalQuickOpen.ts | 19 +++++++++--- .../electron-browser/terminal.contribution.ts | 4 ++- .../electron-browser/terminalActions.ts | 31 +++++++++++++++++-- .../electron-browser/terminalPanel.ts | 6 ++-- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts b/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts index 0f5e860dc61..dc1412e510e 100644 --- a/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts +++ b/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts @@ -14,6 +14,8 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ContributableActionProvider } from 'vs/workbench/browser/actions'; import { stripWildcards } from 'vs/base/common/strings'; import { matchesFuzzy } from 'vs/base/common/filters'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { PICK_WORKSPACE_FOLDER_COMMAND } from 'vs/workbench/browser/actions/workspaceActions'; export class TerminalEntry extends QuickOpenEntry { @@ -49,7 +51,8 @@ export class CreateTerminal extends QuickOpenEntry { constructor( private label: string, - private terminalService: ITerminalService + private terminalService: ITerminalService, + private commandService: ICommandService ) { super(); } @@ -65,9 +68,14 @@ export class CreateTerminal extends QuickOpenEntry { public run(mode: Mode, context: IEntryRunContext): boolean { if (mode === Mode.OPEN) { setTimeout(() => { - const newTerminal = this.terminalService.createInstance(); - this.terminalService.setActiveInstance(newTerminal); - this.terminalService.showPanel(true); + return this.commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND).then(workspace => { + const instance = this.terminalService.createInstance({ cwd: workspace.uri.fsPath }, true); + if (!instance) { + return TPromise.as(void 0); + } + this.terminalService.setActiveInstance(instance); + return this.terminalService.showPanel(true); + }); }, 0); return true; } @@ -82,6 +90,7 @@ export class TerminalPickerHandler extends QuickOpenHandler { constructor( @ITerminalService private terminalService: ITerminalService, + @ICommandService private commandService: ICommandService, @IPanelService private panelService: IPanelService ) { super(); @@ -92,7 +101,7 @@ export class TerminalPickerHandler extends QuickOpenHandler { const normalizedSearchValueLowercase = stripWildcards(searchValue).toLowerCase(); const terminalEntries: QuickOpenEntry[] = this.getTerminals(); - terminalEntries.push(new CreateTerminal(nls.localize("'workbench.action.terminal.newplus", "$(plus) Create New Integrated Terminal"), this.terminalService)); + terminalEntries.push(new CreateTerminal(nls.localize("'workbench.action.terminal.newplus", "$(plus) Create New Integrated Terminal"), this.terminalService, this.commandService)); const entries = terminalEntries.filter(e => { if (!searchValue) { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index 7a048fb9732..184802fb0da 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -18,7 +18,7 @@ import { TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFA import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, CreateNewSelectWorkspaceTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; @@ -187,6 +187,7 @@ configurationRegistry.registerConfiguration({ QUICKOPEN_ACTION_ID, ShowAllCommandsAction.ID, CreateNewTerminalAction.ID, + CreateNewSelectWorkspaceTerminalAction.ID, CopyTerminalSelectionAction.ID, KillTerminalAction.ID, FocusActiveTerminalAction.ID, @@ -279,6 +280,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewTermina primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_BACKTICK } }), 'Terminal: Create New Integrated Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewSelectWorkspaceTerminalAction, CreateNewSelectWorkspaceTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (Select Workspace)', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousTerminalAction, FocusPreviousTerminalAction.ID, FocusPreviousTerminalAction.LABEL), 'Terminal: Focus Previous Terminal', category); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index b38714c7e04..7bb15300f3a 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -21,6 +21,8 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { ActionBarContributor } from 'vs/workbench/browser/actions'; import { TerminalEntry } from 'vs/workbench/parts/terminal/browser/terminalQuickOpen'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { PICK_WORKSPACE_FOLDER_COMMAND } from 'vs/workbench/browser/actions/workspaceActions'; export const TERMINAL_PICKER_PREFIX = 'term '; @@ -196,14 +198,12 @@ export class CreateNewTerminalAction extends Action { public static ID = 'workbench.action.terminal.new'; public static LABEL = nls.localize('workbench.action.terminal.new', "Create New Integrated Terminal"); - public static PANEL_LABEL = nls.localize('workbench.action.terminal.new.short', "New Terminal"); constructor( id: string, label: string, @ITerminalService private terminalService: ITerminalService ) { super(id, label); - this.class = 'terminal-action new'; } public run(event?: any): TPromise { @@ -216,6 +216,33 @@ export class CreateNewTerminalAction extends Action { } } +export class CreateNewSelectWorkspaceTerminalAction extends Action { + + public static ID = 'workbench.action.terminal.newSelectWorkspace'; + public static LABEL = nls.localize('workbench.action.terminal.newSelectWorkspace', "Create New Integrated Terminal (Select Workspace)"); + public static PANEL_LABEL = nls.localize('workbench.action.terminal.new.short', "New Terminal"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService, + @ICommandService private commandService: ICommandService + ) { + super(id, label); + this.class = 'terminal-action new'; + } + + public run(event?: any): TPromise { + return this.commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND).then(workspace => { + const instance = this.terminalService.createInstance({ cwd: workspace.uri.fsPath }, true); + if (!instance) { + return TPromise.as(void 0); + } + this.terminalService.setActiveInstance(instance); + return this.terminalService.showPanel(true); + }); + } +} + export class FocusActiveTerminalAction extends Action { public static ID = 'workbench.action.terminal.focus'; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 9acf376fef2..2ec3fb4ed98 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -19,7 +19,7 @@ import { ITerminalService, ITerminalFont, TERMINAL_PANEL_ID } from 'vs/workbench import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { TerminalFindWidget } from './terminalFindWidget'; import { editorHoverBackground, editorHoverBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; -import { KillTerminalAction, CreateNewTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, CreateNewSelectWorkspaceTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Panel } from 'vs/workbench/browser/panel'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -115,7 +115,7 @@ export class TerminalPanel extends Panel { if (!this._actions) { this._actions = [ this._instantiationService.createInstance(SwitchTerminalInstanceAction, SwitchTerminalInstanceAction.ID, SwitchTerminalInstanceAction.LABEL), - this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.PANEL_LABEL), + this._instantiationService.createInstance(CreateNewSelectWorkspaceTerminalAction, CreateNewSelectWorkspaceTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.PANEL_LABEL), this._instantiationService.createInstance(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.PANEL_LABEL) ]; this._actions.forEach(a => { @@ -129,7 +129,7 @@ export class TerminalPanel extends Panel { if (!this._contextMenuActions) { this._copyContextMenuAction = this._instantiationService.createInstance(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, nls.localize('copy', "Copy")); this._contextMenuActions = [ - this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, nls.localize('createNewTerminal', "New Terminal")), + this._instantiationService.createInstance(CreateNewSelectWorkspaceTerminalAction, CreateNewSelectWorkspaceTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.PANEL_LABEL), new Separator(), this._copyContextMenuAction, this._instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, nls.localize('paste', "Paste")), From 97e3a85eec2c894f5de56212cac710dac0da83be Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Fri, 13 Oct 2017 23:13:06 -0700 Subject: [PATCH 106/394] Notify test bot --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index a04880dd308..0854813e23f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ cache: notifications: email: false + webhooks: + - http://vscode-test-probot.westus.cloudapp.azure.com:3450/travis/notifications addons: apt: From 65ab631d5144da4066d9335dc88ce0643ee6b151 Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Sat, 14 Oct 2017 00:16:14 -0700 Subject: [PATCH 107/394] add missing awaits --- src/vs/workbench/api/node/extHostSCM.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index a9c1e63af2e..9fafcbf368d 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -204,7 +204,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG return; } - this._commands.executeCommand(command.command, ...command.arguments); + await this._commands.executeCommand(command.command, ...command.arguments); } _takeResourceStateSnapshot(): SCMRawResourceSplice[] { @@ -532,6 +532,6 @@ export class ExtHostSCM { return; } - group.$executeResourceCommand(handle); + await group.$executeResourceCommand(handle); } } From 36b598c0472da771ee61b996240f8af64b24f601 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Sat, 14 Oct 2017 17:37:45 -0700 Subject: [PATCH 108/394] Fix typos for descriptions of emmet prefrerences #35676 --- extensions/emmet/package.nls.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/emmet/package.nls.json b/extensions/emmet/package.nls.json index 837b936b5b1..52a78763207 100644 --- a/extensions/emmet/package.nls.json +++ b/extensions/emmet/package.nls.json @@ -41,8 +41,8 @@ "emmetPreferencesStylusBetween": "Symbol to be placed at the between CSS property and value when expanding CSS abbreviations in Stylus files", "emmetShowSuggestionsAsSnippets": "If true, then emmet suggestions will show up as snippets allowing you to order them as per editor.snippetSuggestions setting.", "emmetPreferencesBemElementSeparator": "Element separator used for classes when using the bem filter", - "emmetPreferencesBemModifierSeparator": "Modifer separator used for classes when using the bem filter", - "emmetPreferencesFilterCommentBefore": "A definition of comment that should be placed before after element when comment filter is applied.", - "emmetPreferencesFilterCommentAfter": "A definition of comment that should be placed before matched element when comment filter is applied.", + "emmetPreferencesBemModifierSeparator": "Modifier separator used for classes when using the bem filter", + "emmetPreferencesFilterCommentBefore": "A definition of comment that should be placed before matched element when comment filter is applied.", + "emmetPreferencesFilterCommentAfter": "A definition of comment that should be placed after matched element when comment filter is applied.", "emmetPreferencesFilterCommentTrigger": "A comma-separated list of attribute names that should exist in abbreviation for the comment filter to be applied" } \ No newline at end of file From de68b077b53d6eeafeaf39699d6384c4b8750a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Tar?= Date: Sun, 15 Oct 2017 19:56:52 +0200 Subject: [PATCH 109/394] Improve consistency of Emmet messages (#36251) - Start Emmet with capital E - Write BEM with all caps like in the official documentation --- extensions/emmet/package.nls.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/extensions/emmet/package.nls.json b/extensions/emmet/package.nls.json index 52a78763207..07ffacf4b44 100644 --- a/extensions/emmet/package.nls.json +++ b/extensions/emmet/package.nls.json @@ -23,13 +23,13 @@ "command.incrementNumberByTen": "Increment by 10", "command.decrementNumberByTen": "Decrement by 10", "emmetSyntaxProfiles": "Define profile for specified syntax or use your own profile with specific rules.", - "emmetExclude": "An array of languages where emmet abbreviations should not be expanded.", - "emmetExtensionsPath": "Path to a folder containing emmet profiles and snippets.'", - "emmetShowExpandedAbbreviation": "Shows expanded emmet abbreviations as suggestions.\nThe option \"inMarkupAndStylesheetFilesOnly\" applies to html, haml, jade, slim, xml, xsl, css, scss, sass, less and stylus.\nThe option \"always\" applies to all parts of the file regardless of markup/css.", - "emmetShowAbbreviationSuggestions": "Shows possible emmet abbreviations as suggestions. Not applicable in stylesheets or when emmet.showExpandedAbbreviation is set to \"never\".", - "emmetIncludeLanguages": "Enable emmet abbreviations in languages that are not supported by default. Add a mapping here between the language and emmet supported language.\n Eg: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Variables to be used in emmet snippets", - "emmetTriggerExpansionOnTab": "When enabled, emmet abbreviations are expanded when pressing TAB.", + "emmetExclude": "An array of languages where Emmet abbreviations should not be expanded.", + "emmetExtensionsPath": "Path to a folder containing Emmet profiles and snippets.'", + "emmetShowExpandedAbbreviation": "Shows expanded Emmet abbreviations as suggestions.\nThe option \"inMarkupAndStylesheetFilesOnly\" applies to html, haml, jade, slim, xml, xsl, css, scss, sass, less and stylus.\nThe option \"always\" applies to all parts of the file regardless of markup/css.", + "emmetShowAbbreviationSuggestions": "Shows possible Emmet abbreviations as suggestions. Not applicable in stylesheets or when emmet.showExpandedAbbreviation is set to \"never\".", + "emmetIncludeLanguages": "Enable Emmet abbreviations in languages that are not supported by default. Add a mapping here between the language and emmet supported language.\n Eg: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetVariables": "Variables to be used in Emmet snippets", + "emmetTriggerExpansionOnTab": "When enabled, Emmet abbreviations are expanded when pressing TAB.", "emmetPreferences": "Preferences used to modify behavior of some actions and resolvers of Emmet.", "emmetPreferencesIntUnit": "Default unit for integer values", "emmetPreferencesFloatUnit": "Default unit for float values", @@ -39,10 +39,10 @@ "emmetPreferencesCssBetween": "Symbol to be placed at the between CSS property and value when expanding CSS abbreviations", "emmetPreferencesSassBetween": "Symbol to be placed at the between CSS property and value when expanding CSS abbreviations in Sass files", "emmetPreferencesStylusBetween": "Symbol to be placed at the between CSS property and value when expanding CSS abbreviations in Stylus files", - "emmetShowSuggestionsAsSnippets": "If true, then emmet suggestions will show up as snippets allowing you to order them as per editor.snippetSuggestions setting.", - "emmetPreferencesBemElementSeparator": "Element separator used for classes when using the bem filter", - "emmetPreferencesBemModifierSeparator": "Modifier separator used for classes when using the bem filter", + "emmetShowSuggestionsAsSnippets": "If true, then Emmet suggestions will show up as snippets allowing you to order them as per editor.snippetSuggestions setting.", + "emmetPreferencesBemElementSeparator": "Element separator used for classes when using the BEM filter", + "emmetPreferencesBemModifierSeparator": "Modifier separator used for classes when using the BEM filter", "emmetPreferencesFilterCommentBefore": "A definition of comment that should be placed before matched element when comment filter is applied.", "emmetPreferencesFilterCommentAfter": "A definition of comment that should be placed after matched element when comment filter is applied.", "emmetPreferencesFilterCommentTrigger": "A comma-separated list of attribute names that should exist in abbreviation for the comment filter to be applied" -} \ No newline at end of file +} From c2da4060c8c5c8dd24bc5a36a0b3ccc0d2289eea Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 09:20:32 +0200 Subject: [PATCH 110/394] Document current decoration behaviour --- .../common/model/modelDecorations.test.ts | 697 +++++++++++++++++- 1 file changed, 693 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 84defed4ada..1699981d0da 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -27,6 +27,7 @@ function modelHasDecorations(model: Model, decorations: ILightWeightDecoration2[ className: actualDecorations[i].options.className }); } + modelDecorations.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range)); assert.deepEqual(modelDecorations, decorations, 'Model decorations'); } @@ -168,13 +169,13 @@ suite('Editor Model - Model Decorations', () => { var decId1 = addDecoration(thisModel, 1, 2, 3, 2, 'myType1'); var decId2 = addDecoration(thisModel, 1, 2, 3, 1, 'myType2'); modelHasDecorations(thisModel, [ - { - range: new Range(1, 2, 3, 2), - className: 'myType1' - }, { range: new Range(1, 2, 3, 1), className: 'myType2' + }, + { + range: new Range(1, 2, 3, 2), + className: 'myType1' } ]); thisModel.changeDecorations((changeAccessor) => { @@ -352,6 +353,694 @@ suite('Editor Model - Model Decorations', () => { }); }); +suite('Decorations and editing', () => { + + function _runTest(decRange: Range, stickiness: TrackedRangeStickiness, editRange: Range, editText: string, editForceMoveMarkers: boolean, expectedDecRange: Range, msg: string): void { + let model = Model.createFromString([ + 'My First Line', + 'My Second Line', + 'Third Line' + ].join('\n')); + + const id = model.deltaDecorations([], [{ range: decRange, options: { stickiness: stickiness } }])[0]; + model.applyEdits([{ range: editRange, text: editText, forceMoveMarkers: editForceMoveMarkers, identifier: null }]); + const actual = model.getDecorationRange(id); + assert.deepEqual(actual, expectedDecRange, msg); + + model.dispose(); + } + + function runTest(decRange: Range, editRange: Range, editText: string, expectedDecRange: Range[][]): void { + _runTest(decRange, 0, editRange, editText, false, expectedDecRange[0][0], 'no-0-AlwaysGrowsWhenTypingAtEdges'); + _runTest(decRange, 1, editRange, editText, false, expectedDecRange[0][1], 'no-1-NeverGrowsWhenTypingAtEdges'); + _runTest(decRange, 2, editRange, editText, false, expectedDecRange[0][2], 'no-2-GrowsOnlyWhenTypingBefore'); + _runTest(decRange, 3, editRange, editText, false, expectedDecRange[0][3], 'no-3-GrowsOnlyWhenTypingAfter'); + + _runTest(decRange, 0, editRange, editText, true, expectedDecRange[1][0], 'force-0-AlwaysGrowsWhenTypingAtEdges'); + _runTest(decRange, 1, editRange, editText, true, expectedDecRange[1][1], 'force-1-NeverGrowsWhenTypingAtEdges'); + _runTest(decRange, 2, editRange, editText, true, expectedDecRange[1][2], 'force-2-GrowsOnlyWhenTypingBefore'); + _runTest(decRange, 3, editRange, editText, true, expectedDecRange[1][3], 'force-3-GrowsOnlyWhenTypingAfter'); + } + + suite('insert', () => { + suite('collapsed dec', () => { + test('before', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 3), 'xx', + [ + [new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6)], + [new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6)], + ] + ); + }); + test('equal', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 4), 'xx', + [ + [new Range(1, 4, 1, 6), new Range(1, 6, 1, 6), new Range(1, 4, 1, 4), new Range(1, 6, 1, 6)], + [new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6)], + ] + ); + }); + test('after', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 5), 'xx', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('before', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 3), 'xx', + [ + [new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11)], + [new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11)], + ] + ); + }); + test('start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 4), 'xx', + [ + [new Range(1, 4, 1, 11), new Range(1, 6, 1, 11), new Range(1, 4, 1, 11), new Range(1, 6, 1, 11)], + [new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11)], + ] + ); + }); + test('inside', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 5), 'xx', + [ + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + ] + ); + }); + test('end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 9), 'xx', + [ + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 11)], + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + ] + ); + }); + test('after', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 10), 'xx', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + }); + }); + + suite('delete', () => { + suite('collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 1, 1, 3), '', + [ + [new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2)], + [new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 2, 1, 4), '', + [ + [new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2)], + [new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2), new Range(1, 2, 1, 2)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 5), '', + [ + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + ] + ); + }); + test('edit.start >= range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 6), '', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 7), '', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 1, 1, 3), '', + [ + [new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7)], + [new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 2, 1, 4), '', + [ + [new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7)], + [new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7), new Range(1, 2, 1, 7)], + ] + ); + }); + test('edit.start < range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 5), '', + [ + [new Range(1, 3, 1, 7), new Range(1, 3, 1, 7), new Range(1, 3, 1, 7), new Range(1, 3, 1, 7)], + [new Range(1, 3, 1, 7), new Range(1, 3, 1, 7), new Range(1, 3, 1, 7), new Range(1, 3, 1, 7)], + ] + ); + }); + + test('edit.start < range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 9), '', + [ + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + ] + ); + }); + + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 10), '', + [ + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + ] + ); + }); + + test('edit.start == range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 6), '', + [ + [new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7)], + [new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7)], + ] + ); + }); + + test('edit.start == range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 9), '', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + + test('edit.start == range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 10), '', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + + test('edit.start > range.start && edit.start < range.end && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 7), '', + [ + [new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7)], + [new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7)], + ] + ); + }); + + test('edit.start > range.start && edit.start < range.end && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 9), '', + [ + [new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5)], + [new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5)], + ] + ); + }); + + test('edit.start > range.start && edit.start < range.end && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 10), '', + [ + [new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5)], + [new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5)], + ] + ); + }); + + test('edit.start == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 11), '', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 11), '', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + }); + }); + + suite('replace short', () => { + suite('collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 1, 1, 3), 'c', + [ + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 2, 1, 4), 'c', + [ + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + [new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3), new Range(1, 3, 1, 3)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 5), 'c', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + test('edit.start >= range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 6), 'c', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 5, 1, 5), new Range(1, 5, 1, 5), new Range(1, 5, 1, 5), new Range(1, 5, 1, 5)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 7), 'c', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 1, 1, 3), 'c', + [ + [new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8)], + [new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 2, 1, 4), 'c', + [ + [new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8)], + [new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8), new Range(1, 3, 1, 8)], + ] + ); + }); + test('edit.start < range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 5), 'c', + [ + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + ] + ); + }); + test('edit.start < range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 9), 'c', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 10), 'c', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + test('edit.start == range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 6), 'c', + [ + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + [new Range(1, 5, 1, 8), new Range(1, 5, 1, 8), new Range(1, 5, 1, 8), new Range(1, 5, 1, 8)], + ] + ); + }); + test('edit.start == range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 9), 'c', + [ + [new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5)], + [new Range(1, 5, 1, 5), new Range(1, 5, 1, 5), new Range(1, 5, 1, 5), new Range(1, 5, 1, 5)], + ] + ); + }); + test('edit.start == range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 10), 'c', + [ + [new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5), new Range(1, 4, 1, 5)], + [new Range(1, 5, 1, 5), new Range(1, 5, 1, 5), new Range(1, 5, 1, 5), new Range(1, 5, 1, 5)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 7), 'c', + [ + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 9), 'c', + [ + [new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6)], + [new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 10), 'c', + [ + [new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6)], + [new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6), new Range(1, 4, 1, 6)], + ] + ); + }); + test('edit.start == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 11), 'c', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 10), new Range(1, 4, 1, 10), new Range(1, 4, 1, 10), new Range(1, 4, 1, 10)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 11), 'c', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + }); + }); + + suite('replace long', () => { + suite('collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 1, 1, 3), 'cccc', + [ + [new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6)], + [new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 2, 1, 4), 'cccc', + [ + [new Range(1, 4, 1, 6), new Range(1, 6, 1, 6), new Range(1, 4, 1, 4), new Range(1, 6, 1, 6)], + [new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6), new Range(1, 6, 1, 6)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 5), 'cccc', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 7, 1, 7), new Range(1, 7, 1, 7), new Range(1, 7, 1, 7), new Range(1, 7, 1, 7)], + ] + ); + }); + test('edit.start >= range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 6), 'cccc', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 8, 1, 8), new Range(1, 8, 1, 8), new Range(1, 8, 1, 8), new Range(1, 8, 1, 8)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 7), 'cccc', + [ + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + [new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4), new Range(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 1, 1, 3), 'cccc', + [ + [new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11)], + [new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 2, 1, 4), 'cccc', + [ + [new Range(1, 4, 1, 11), new Range(1, 6, 1, 11), new Range(1, 4, 1, 11), new Range(1, 6, 1, 11)], + [new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11), new Range(1, 6, 1, 11)], + ] + ); + }); + test('edit.start < range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 5), 'cccc', + [ + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + [new Range(1, 7, 1, 11), new Range(1, 7, 1, 11), new Range(1, 7, 1, 11), new Range(1, 7, 1, 11)], + ] + ); + }); + test('edit.start < range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 9), 'cccc', + [ + [new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7)], + [new Range(1, 7, 1, 7), new Range(1, 7, 1, 7), new Range(1, 7, 1, 7), new Range(1, 7, 1, 7)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 10), 'cccc', + [ + [new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7), new Range(1, 4, 1, 7)], + [new Range(1, 7, 1, 7), new Range(1, 7, 1, 7), new Range(1, 7, 1, 7), new Range(1, 7, 1, 7)], + ] + ); + }); + test('edit.start == range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 6), 'cccc', + [ + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + [new Range(1, 8, 1, 11), new Range(1, 8, 1, 11), new Range(1, 8, 1, 11), new Range(1, 8, 1, 11)], + ] + ); + }); + test('edit.start == range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 9), 'cccc', + [ + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + [new Range(1, 8, 1, 8), new Range(1, 8, 1, 8), new Range(1, 8, 1, 8), new Range(1, 8, 1, 8)], + ] + ); + }); + test('edit.start == range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 10), 'cccc', + [ + [new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8), new Range(1, 4, 1, 8)], + [new Range(1, 8, 1, 8), new Range(1, 8, 1, 8), new Range(1, 8, 1, 8), new Range(1, 8, 1, 8)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 7), 'cccc', + [ + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + [new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11), new Range(1, 4, 1, 11)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 9), 'cccc', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 10), 'cccc', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + test('edit.start == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 11), 'cccc', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 13), new Range(1, 4, 1, 13), new Range(1, 4, 1, 13), new Range(1, 4, 1, 13)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 11), 'cccc', + [ + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + [new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9), new Range(1, 4, 1, 9)], + ] + ); + }); + }); + }); +}); + interface ILightWeightDecoration { id: string; range: Range; From 4b539d4d6474548b2ff28dd7e2aa3eb42ceb24d9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 09:25:23 +0200 Subject: [PATCH 111/394] :lipstick: --- src/vs/workbench/browser/labels.ts | 8 ++-- .../workbench/electron-browser/workbench.ts | 4 +- .../markers/browser/markersFileDecorations.ts | 8 ++-- .../electron-browser/scmFileDecorations.ts | 8 ++-- .../decorations/browser/decorations.ts | 14 +++---- .../decorations/browser/decorationsService.ts | 40 +++++++++---------- .../test/browser/decorationsService.test.ts | 20 +++++----- 7 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 8a312fa3457..08a68da883c 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -20,7 +20,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import { IResourceDecorationsService, IResourceDecorationChangeEvent } from 'vs/workbench/services/decorations/browser/decorations'; +import { IDecorationsService, IResourceDecorationChangeEvent } from 'vs/workbench/services/decorations/browser/decorations'; import { Schemas } from 'vs/base/common/network'; import { FileKind } from 'vs/platform/files/common/files'; import { IModel } from 'vs/editor/common/editorCommon'; @@ -53,7 +53,7 @@ export class ResourceLabel extends IconLabel { @IModeService private modeService: IModeService, @IModelService private modelService: IModelService, @IEnvironmentService protected environmentService: IEnvironmentService, - @IResourceDecorationsService protected decorationsService: IResourceDecorationsService, + @IDecorationsService protected decorationsService: IDecorationsService, @IThemeService private themeService: IThemeService ) { super(container, options); @@ -183,7 +183,7 @@ export class ResourceLabel extends IconLabel { } if (this.options && this.options.fileDecorations) { - let deco = this.decorationsService.getTopDecoration( + let deco = this.decorationsService.getDecoration( resource, this.options.fileKind !== FileKind.FILE ); @@ -240,7 +240,7 @@ export class FileLabel extends ResourceLabel { @IModeService modeService: IModeService, @IModelService modelService: IModelService, @IEnvironmentService environmentService: IEnvironmentService, - @IResourceDecorationsService decorationsService: IResourceDecorationsService, + @IDecorationsService decorationsService: IDecorationsService, @IThemeService themeService: IThemeService, @IUntitledEditorService private untitledEditorService: IUntitledEditorService, ) { diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index c88d5d05d54..25ddf4ea5ef 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -97,7 +97,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService'; import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService'; -import { IResourceDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; +import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; import URI from 'vs/base/common/uri'; export const MessagesVisibleContext = new RawContextKey('globalMessageVisible', false); @@ -585,7 +585,7 @@ export class Workbench implements IPartService { serviceCollection.set(ITextFileService, new SyncDescriptor(TextFileService)); // File Decorations - serviceCollection.set(IResourceDecorationsService, new SyncDescriptor(FileDecorationsService)); + serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService)); // SCM Service serviceCollection.set(ISCMService, new SyncDescriptor(SCMService)); diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts index 46f91a0b701..670e1db47da 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts @@ -7,7 +7,7 @@ import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IMarkerService, IMarker } from 'vs/platform/markers/common/markers'; -import { IResourceDecorationsService, IDecorationsProvider, IResourceDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; +import { IDecorationsService, IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import Event from 'vs/base/common/event'; @@ -29,7 +29,7 @@ class MarkersDecorationsProvider implements IDecorationsProvider { this.onDidChange = _markerService.onMarkerChanged; } - provideDecorations(resource: URI): IResourceDecorationData { + provideDecorations(resource: URI): IDecorationData { let markers = this._markerService.read({ resource }); let first: IMarker; for (const marker of markers) { @@ -59,7 +59,7 @@ class MarkersFileDecorations implements IWorkbenchContribution { constructor( @IMarkerService private _markerService: IMarkerService, - @IResourceDecorationsService private _decorationsService: IResourceDecorationsService, + @IDecorationsService private _decorationsService: IDecorationsService, @IConfigurationService private _configurationService: IConfigurationService ) { // @@ -86,7 +86,7 @@ class MarkersFileDecorations implements IWorkbenchContribution { this._enabled = value.decorations.enabled; if (this._enabled) { const provider = new MarkersDecorationsProvider(this._markerService); - this._provider = this._decorationsService.registerDecortionsProvider(provider); + this._provider = this._decorationsService.registerDecorationsProvider(provider); } else if (this._provider) { this._enabled = value.decorations.enabled; this._provider.dispose(); diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index 97c1c66a212..ebfd9f55cd9 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -6,7 +6,7 @@ 'use strict'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IResourceDecorationsService, IDecorationsProvider, IResourceDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; +import { IDecorationsService, IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource } from 'vs/workbench/services/scm/common/scm'; import URI from 'vs/base/common/uri'; @@ -60,7 +60,7 @@ class SCMDecorationsProvider implements IDecorationsProvider { this._onDidChange.fire(uris); } - provideDecorations(uri: URI): IResourceDecorationData { + provideDecorations(uri: URI): IDecorationData { const resource = this._data.get(uri.toString()); if (!resource || !resource.decorations.color || !resource.decorations.tooltip) { return undefined; @@ -88,7 +88,7 @@ export class FileDecorations implements IWorkbenchContribution { private _currentConfig: ISCMConfiguration; constructor( - @IResourceDecorationsService private _decorationsService: IResourceDecorationsService, + @IDecorationsService private _decorationsService: IDecorationsService, @IConfigurationService private _configurationService: IConfigurationService, @ISCMService private _scmService: ISCMService, ) { @@ -127,7 +127,7 @@ export class FileDecorations implements IWorkbenchContribution { private _onDidAddRepository(repo: ISCMRepository): void { const provider = new SCMDecorationsProvider(repo.provider, this._configurationService.getConfiguration('scm')); - const registration = this._decorationsService.registerDecortionsProvider(provider); + const registration = this._decorationsService.registerDecorationsProvider(provider); this._providers.set(repo, combinedDisposable([registration, provider])); } diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 110b0e39b2a..1c42c362433 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -10,9 +10,9 @@ import Event from 'vs/base/common/event'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { IDisposable } from 'vs/base/common/lifecycle'; -export const IResourceDecorationsService = createDecorator('IFileDecorationsService'); +export const IDecorationsService = createDecorator('IFileDecorationsService'); -export interface IResourceDecorationData { +export interface IDecorationData { readonly weight?: number; readonly color?: ColorIdentifier; readonly opacity?: number; @@ -20,7 +20,7 @@ export interface IResourceDecorationData { readonly tooltip?: string; } -export interface IResourceDecoration { +export interface IDecoration { readonly _decoBrand: undefined; readonly weight?: number; readonly tooltip?: string; @@ -31,20 +31,20 @@ export interface IResourceDecoration { export interface IDecorationsProvider { readonly label: string; readonly onDidChange: Event; - provideDecorations(uri: URI): IResourceDecorationData | Thenable; + provideDecorations(uri: URI): IDecorationData | Thenable; } export interface IResourceDecorationChangeEvent { affectsResource(uri: URI): boolean; } -export interface IResourceDecorationsService { +export interface IDecorationsService { readonly _serviceBrand: any; readonly onDidChangeDecorations: Event; - registerDecortionsProvider(provider: IDecorationsProvider): IDisposable; + registerDecorationsProvider(provider: IDecorationsProvider): IDisposable; - getTopDecoration(uri: URI, includeChildren: boolean): IResourceDecoration; + getDecoration(uri: URI, includeChildren: boolean): IDecoration; } diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 0203f93a682..522181bb4d9 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -6,7 +6,7 @@ import URI from 'vs/base/common/uri'; import Event, { Emitter, debounceEvent, any } from 'vs/base/common/event'; -import { IResourceDecorationsService, IResourceDecoration, IResourceDecorationChangeEvent, IDecorationsProvider, IResourceDecorationData } from './decorations'; +import { IDecorationsService, IDecoration, IResourceDecorationChangeEvent, IDecorationsProvider, IDecorationData } from './decorations'; import { TernarySearchTree } from 'vs/base/common/map'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { isThenable } from 'vs/base/common/async'; @@ -19,7 +19,7 @@ import { IIterator } from 'vs/base/common/iterator'; class DecorationRule { - static keyOf(data: IResourceDecorationData | IResourceDecorationData[]): string { + static keyOf(data: IDecorationData | IDecorationData[]): string { if (Array.isArray(data)) { return data.map(DecorationRule.keyOf).join(','); } else { @@ -30,11 +30,11 @@ class DecorationRule { private static readonly _classNames = new IdGenerator('monaco-decorations-style-'); - readonly data: IResourceDecorationData | IResourceDecorationData[]; + readonly data: IDecorationData | IDecorationData[]; readonly labelClassName: string; readonly badgeClassName: string; - constructor(data: IResourceDecorationData | IResourceDecorationData[]) { + constructor(data: IDecorationData | IDecorationData[]) { this.data = data; this.labelClassName = DecorationRule._classNames.nextId(); this.badgeClassName = DecorationRule._classNames.nextId(); @@ -48,7 +48,7 @@ class DecorationRule { } } - private _appendForOne(data: IResourceDecorationData, element: HTMLStyleElement, theme: ITheme): void { + private _appendForOne(data: IDecorationData, element: HTMLStyleElement, theme: ITheme): void { const { color, opacity, letter } = data; // label createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); @@ -60,7 +60,7 @@ class DecorationRule { } } - private _appendForMany(data: IResourceDecorationData[], element: HTMLStyleElement, theme: ITheme): void { + private _appendForMany(data: IDecorationData[], element: HTMLStyleElement, theme: ITheme): void { // label const { color, opacity } = data[0]; createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); @@ -87,9 +87,9 @@ class DecorationRule { } } -class ResourceDecoration implements IResourceDecoration { +class ResourceDecoration implements IDecoration { - static from(data: IResourceDecorationData | IResourceDecorationData[]): ResourceDecoration { + static from(data: IDecorationData | IDecorationData[]): ResourceDecoration { let result = new ResourceDecoration(data); if (Array.isArray(data)) { result.weight = data[0].weight; @@ -102,14 +102,14 @@ class ResourceDecoration implements IResourceDecoration { } _decoBrand: undefined; - _data: IResourceDecorationData | IResourceDecorationData[]; + _data: IDecorationData | IDecorationData[]; weight?: number; tooltip?: string; labelClassName?: string; badgeClassName?: string; - private constructor(data: IResourceDecorationData | IResourceDecorationData[]) { + private constructor(data: IDecorationData | IDecorationData[]) { this._data = data; } } @@ -133,7 +133,7 @@ class DecorationStyles { this._styleElement.parentElement.removeChild(this._styleElement); } - asDecoration(data: IResourceDecorationData | IResourceDecorationData[]): ResourceDecoration { + asDecoration(data: IDecorationData | IDecorationData[]): ResourceDecoration { let key = DecorationRule.keyOf(data); let rule = this._decorationRules.get(key); let result = ResourceDecoration.from(data); @@ -160,7 +160,7 @@ class DecorationStyles { cleanUp(iter: IIterator): void { // remove every rule for which no more // decoration (data) is kept. this isn't cheap - let usedDecorations = new Set(); + let usedDecorations = new Set(); for (let e = iter.next(); !e.done; e = iter.next()) { e.value.data.forEach(value => { if (value instanceof ResourceDecoration) { @@ -216,7 +216,7 @@ class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { class DecorationProviderWrapper { - readonly data = TernarySearchTree.forPaths | IResourceDecorationData>(); + readonly data = TernarySearchTree.forPaths | IDecorationData>(); private readonly _dispoable: IDisposable; constructor( @@ -240,7 +240,7 @@ class DecorationProviderWrapper { return Boolean(this.data.get(uri.toString())) || Boolean(this.data.findSuperstr(uri.toString())); } - getOrRetrieve(uri: URI, includeChildren: boolean, callback: (data: IResourceDecorationData, isChild: boolean) => void): void { + getOrRetrieve(uri: URI, includeChildren: boolean, callback: (data: IDecorationData, isChild: boolean) => void): void { const key = uri.toString(); let item = this.data.get(key); @@ -271,7 +271,7 @@ class DecorationProviderWrapper { } } - private _fetchData(uri: URI): IResourceDecorationData { + private _fetchData(uri: URI): IDecorationData { const dataOrThenable = this._provider.provideDecorations(uri); if (!isThenable(dataOrThenable)) { @@ -289,7 +289,7 @@ class DecorationProviderWrapper { } } - private _keepItem(uri: URI, data: IResourceDecorationData): IResourceDecorationData { + private _keepItem(uri: URI, data: IDecorationData): IDecorationData { let deco = data ? data : null; this.data.set(uri.toString(), deco); this._emitter.fire(uri); @@ -297,7 +297,7 @@ class DecorationProviderWrapper { } } -export class FileDecorationsService implements IResourceDecorationsService { +export class FileDecorationsService implements IDecorationsService { _serviceBrand: any; @@ -340,7 +340,7 @@ export class FileDecorationsService implements IResourceDecorationsService { dispose(this._disposables); } - registerDecortionsProvider(provider: IDecorationsProvider): IDisposable { + registerDecorationsProvider(provider: IDecorationsProvider): IDisposable { const wrapper = new DecorationProviderWrapper( provider, @@ -358,8 +358,8 @@ export class FileDecorationsService implements IResourceDecorationsService { }; } - getTopDecoration(uri: URI, includeChildren: boolean): IResourceDecoration { - let data: IResourceDecorationData[] = []; + getDecoration(uri: URI, includeChildren: boolean): IDecoration { + let data: IDecorationData[] = []; let onlyChildren = true; for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) { next.value.getOrRetrieve(uri, includeChildren, (deco, isChild) => { diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index d1611916273..8135a7eceac 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService'; -import { IDecorationsProvider, IResourceDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; +import { IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import URI from 'vs/base/common/uri'; import Event, { toPromise } from 'vs/base/common/event'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; @@ -28,12 +28,12 @@ suite('DecorationsService', function () { let uri = URI.parse('foo:bar'); let callCounter = 0; - service.registerDecortionsProvider(new class implements IDecorationsProvider { + service.registerDecorationsProvider(new class implements IDecorationsProvider { readonly label: string = 'Test'; readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return new Promise(resolve => { + return new Promise(resolve => { setTimeout(() => resolve({ color: 'someBlue', tooltip: 'T' @@ -43,7 +43,7 @@ suite('DecorationsService', function () { }); // trigger -> async - assert.equal(service.getTopDecoration(uri, false), undefined); + assert.equal(service.getDecoration(uri, false), undefined); assert.equal(callCounter, 1); // event when result is computed @@ -51,7 +51,7 @@ suite('DecorationsService', function () { assert.equal(e.affectsResource(uri), true); // sync result - assert.deepEqual(service.getTopDecoration(uri, false).tooltip, 'T'); + assert.deepEqual(service.getDecoration(uri, false).tooltip, 'T'); assert.equal(callCounter, 1); }); }); @@ -61,7 +61,7 @@ suite('DecorationsService', function () { let uri = URI.parse('foo:bar'); let callCounter = 0; - service.registerDecortionsProvider(new class implements IDecorationsProvider { + service.registerDecorationsProvider(new class implements IDecorationsProvider { readonly label: string = 'Test'; readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { @@ -71,7 +71,7 @@ suite('DecorationsService', function () { }); // trigger -> sync - assert.deepEqual(service.getTopDecoration(uri, false).tooltip, 'Z'); + assert.deepEqual(service.getDecoration(uri, false).tooltip, 'Z'); assert.equal(callCounter, 1); }); @@ -79,7 +79,7 @@ suite('DecorationsService', function () { let uri = URI.parse('foo:bar'); let callCounter = 0; - let reg = service.registerDecortionsProvider(new class implements IDecorationsProvider { + let reg = service.registerDecorationsProvider(new class implements IDecorationsProvider { readonly label: string = 'Test'; readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { @@ -89,14 +89,14 @@ suite('DecorationsService', function () { }); // trigger -> sync - assert.deepEqual(service.getTopDecoration(uri, false).tooltip, 'J'); + assert.deepEqual(service.getDecoration(uri, false).tooltip, 'J'); assert.equal(callCounter, 1); // un-register -> ensure good event let didSeeEvent = false; service.onDidChangeDecorations(e => { assert.equal(e.affectsResource(uri), true); - assert.deepEqual(service.getTopDecoration(uri, false), undefined); + assert.deepEqual(service.getDecoration(uri, false), undefined); assert.equal(callCounter, 1); didSeeEvent = true; }); From e8cea009a55dc19b27268573bf3e935747a1c650 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 Oct 2017 10:40:10 +0200 Subject: [PATCH 112/394] fix #33526 --- src/vs/platform/quickOpen/common/quickOpen.ts | 1 + .../parts/quickopen/quickOpenController.ts | 20 +++--- .../parts/files/browser/fileActions.ts | 71 ++++++------------- 3 files changed, 32 insertions(+), 60 deletions(-) diff --git a/src/vs/platform/quickOpen/common/quickOpen.ts b/src/vs/platform/quickOpen/common/quickOpen.ts index c0611d3dde4..0b3bf170855 100644 --- a/src/vs/platform/quickOpen/common/quickOpen.ts +++ b/src/vs/platform/quickOpen/common/quickOpen.ts @@ -123,6 +123,7 @@ export interface IInputOptions { export interface IShowOptions { quickNavigateConfiguration?: IQuickNavigateConfiguration; inputSelection?: { start: number; end: number; }; + autoFocus?: IAutoFocus; } export const IQuickOpenService = createDecorator('quickOpenService'); diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 00bd2d8d83a..2f178d70c51 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -545,6 +545,7 @@ export class QuickOpenController extends Component implements IQuickOpenService public show(prefix?: string, options?: IShowOptions): TPromise { let quickNavigateConfiguration = options ? options.quickNavigateConfiguration : void 0; let inputSelection = options ? options.inputSelection : void 0; + let autoFocus = options ? options.autoFocus : void 0; this.previousValue = prefix; @@ -565,8 +566,7 @@ export class QuickOpenController extends Component implements IQuickOpenService this.telemetryService.publicLog('quickOpenWidgetShown', { mode: handlerDescriptor.getId(), quickNavigate: quickNavigateConfiguration }); // Trigger onOpen - this.resolveHandler(handlerDescriptor) - .done(null, errors.onUnexpectedError); + this.resolveHandler(handlerDescriptor).done(null, errors.onUnexpectedError); // Create upon first open if (!this.quickOpenWidget) { @@ -601,19 +601,21 @@ export class QuickOpenController extends Component implements IQuickOpenService // Show quick open with prefix or editor history if (!this.quickOpenWidget.isVisible() || quickNavigateConfiguration) { if (prefix) { - this.quickOpenWidget.show(prefix, { quickNavigateConfiguration, inputSelection }); + this.quickOpenWidget.show(prefix, { quickNavigateConfiguration, inputSelection, autoFocus }); } else { const editorHistory = this.getEditorHistoryWithGroupLabel(); if (editorHistory.getEntries().length < 2) { quickNavigateConfiguration = null; // If no entries can be shown, default to normal quick open mode } - let autoFocus: IAutoFocus; - if (!quickNavigateConfiguration) { - autoFocus = { autoFocusFirstEntry: true }; - } else { - const visibleEditorCount = this.editorService.getVisibleEditors().length; - autoFocus = { autoFocusFirstEntry: visibleEditorCount === 0, autoFocusSecondEntry: visibleEditorCount !== 0 }; + // Compute auto focus + if (!autoFocus) { + if (!quickNavigateConfiguration) { + autoFocus = { autoFocusFirstEntry: true }; + } else { + const visibleEditorCount = this.editorService.getVisibleEditors().length; + autoFocus = { autoFocusFirstEntry: visibleEditorCount === 0, autoFocusSecondEntry: visibleEditorCount !== 0 }; + } } // Update context diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index 8f9afccbafe..6975b962704 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -27,7 +27,7 @@ import { VIEWLET_ID, FileOnDiskContentProvider } from 'vs/workbench/parts/files/ import labels = require('vs/base/common/labels'); import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; -import { toResource, IEditorIdentifier, EditorInput } from 'vs/workbench/common/editor'; +import { toResource, IEditorIdentifier } from 'vs/workbench/common/editor'; import { FileStat, Model, NewStatPlaceholder } from 'vs/workbench/parts/files/common/explorerModel'; import { ExplorerView } from 'vs/workbench/parts/files/browser/views/explorerView'; import { ExplorerViewlet } from 'vs/workbench/parts/files/browser/explorerViewlet'; @@ -35,10 +35,9 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import { IQuickOpenService, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; -import { IHistoryService } from 'vs/workbench/services/history/common/history'; +import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { Position, IResourceInput, IEditorInput, IUntitledResourceInput } from 'vs/platform/editor/common/editor'; +import { Position, IResourceInput, IUntitledResourceInput } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature2, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService, IMessageWithAction, IConfirmation, Severity, CancelAction, IConfirmationResult } from 'vs/platform/message/common/message'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -52,6 +51,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { once } from 'vs/base/common/event'; export interface IEditableData { action: IAction; @@ -1197,12 +1197,9 @@ export class GlobalCompareResourcesAction extends Action { id: string, label: string, @IQuickOpenService private quickOpenService: IQuickOpenService, - @IInstantiationService private instantiationService: IInstantiationService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IHistoryService private historyService: IHistoryService, - @IWorkspaceContextService private contextService: IWorkspaceContextService, @IMessageService private messageService: IMessageService, - @IEnvironmentService private environmentService: IEnvironmentService + @IEditorGroupService private editorGroupService: IEditorGroupService ) { super(id, label); } @@ -1212,50 +1209,22 @@ export class GlobalCompareResourcesAction extends Action { const activeResource = activeInput ? activeInput.getResource() : void 0; if (activeResource) { - // Keep as resource to compare - globalResourceToCompare = activeResource; - - // Pick another entry from history - interface IHistoryPickEntry extends IFilePickOpenEntry { - input: IEditorInput | IResourceInput; - } - - const history = this.historyService.getHistory(); - const picks: IHistoryPickEntry[] = history.map(input => { - let resource: URI; - let label: string; - let description: string; - - if (input instanceof EditorInput) { - resource = input.getResource(); - } else { - resource = (input as IResourceInput).resource; + // Compare with next editor that opens + const unbind = once(this.editorGroupService.onEditorOpening)(e => { + const resource = e.input.getResource(); + if (resource) { + e.prevent(() => { + return this.editorService.openEditor({ + leftResource: activeResource, + rightResource: resource + }); + }); } + }); - // Cannot compare file with self - exclude active file - if (!!resource && resource.toString() === globalResourceToCompare.toString()) { - return void 0; - } - - if (!resource) { - return void 0; // only support to compare with files and untitled - } - - label = paths.basename(resource.fsPath); - description = labels.getPathLabel(resources.dirname(resource), this.contextService, this.environmentService); - - return { input, resource, label, description }; - }).filter(p => !!p); - - return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickHistory', "Select a previously opened file to compare with"), autoFocus: { autoFocusFirstEntry: true }, matchOnDescription: true }).then(pick => { - if (pick) { - const compareAction = this.instantiationService.createInstance(CompareResourcesAction, pick.resource, null); - if (compareAction._isEnabled()) { - compareAction.run().done(() => compareAction.dispose()); - } else { - this.messageService.show(Severity.Info, nls.localize('unableToFileToCompare', "The selected file can not be compared with '{0}'.", paths.basename(globalResourceToCompare.fsPath))); - } - } + // Bring up quick open + this.quickOpenService.show('', { autoFocus: { autoFocusSecondEntry: true } }).then(() => { + unbind.dispose(); // make sure to unbind if quick open is closing }); } else { this.messageService.show(Severity.Info, nls.localize('openFileToCompare', "Open a file first to compare it with another file.")); @@ -1305,7 +1274,7 @@ export class CompareResourcesAction extends Action { return nls.localize('compareFiles', "Compare Files"); } - _isEnabled(): boolean { + public _isEnabled(): boolean { // Need at least a resource to compare if (!globalResourceToCompare) { From 46075929b2f273f6339ce9659cb58fd29a7acf1d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 Oct 2017 10:48:33 +0200 Subject: [PATCH 113/394] fix #35765 --- npm-shrinkwrap.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index dd103542200..a801e584465 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -566,6 +566,16 @@ "from": "winreg@1.2.0", "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.0.tgz" }, + "windows-foreground-love": { + "version": "0.1.0", + "from": "windows-foreground-love@0.1.0", + "resolved": "https://registry.npmjs.org/windows-foreground-love/-/windows-foreground-love-0.1.0.tgz" + }, + "windows-mutex": { + "version": "0.2.0", + "from": "windows-mutex@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz" + }, "windows-process-tree": { "version": "0.1.6", "from": "windows-process-tree@0.1.6", @@ -582,4 +592,4 @@ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz" } } -} +} \ No newline at end of file From 60a493cdc2ebaba842f229563842625054f0e6c2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 10:54:36 +0200 Subject: [PATCH 114/394] Tests for configuration change event --- .../configuration/common/configuration.ts | 5 +- .../common/configurationModels.ts | 93 ++++++++------ .../test/common/configurationModels.test.ts | 116 +++++++++++++++++- 3 files changed, 171 insertions(+), 43 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 8a1daa65929..16e5736bd3f 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -31,10 +31,7 @@ export enum ConfigurationTarget { export interface IConfigurationChangeEvent { affectedKeys: string[]; - affectsConfiugration(configuration: string): boolean; - affectsConfiugration(configuration: string, overrideIdentifier: string): boolean; - affectsConfiugration(configuration: string, resource: URI): boolean; - affectsConfiugration(configuration: string, overrideIdentifier: string, resource: URI): boolean; + affectsConfiugration(configuration: string, resource?: URI): boolean; // Following data is used for telemetry source: ConfigurationTarget; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 7acaca42472..be314db0f04 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -455,15 +455,47 @@ export class Configuration { } } -export class AllKeysConfigurationChangeEvent implements IConfigurationChangeEvent { +export class AbstractConfigurationChangeEvent { - constructor(readonly affectedKeys: string[], readonly source: ConfigurationTarget, readonly sourceConfig: any) { } + protected doesConfigurationContains(configuration: ConfigurationModel, config: string): boolean { + let changedKeysTree = configuration.contents; + let requestedTree = toValuesTree({ [config]: true }, () => { }); - affectsConfiugration: () => true; + let key; + while (typeof requestedTree === 'object' && (key = Object.keys(requestedTree)[0])) { // Only one key should present, since we added only one property + changedKeysTree = changedKeysTree[key]; + if (!changedKeysTree) { + return false; // Requested tree is not found + } + requestedTree = requestedTree[key]; + } + return true; + } + + protected updateKeys(configuration: ConfigurationModel, keys: string[], resource?: URI): void { + for (const key of keys) { + configuration.setValue(key, true); + } + } +} + +export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChangeEvent implements IConfigurationChangeEvent { + + private changedConfiguration: ConfigurationModel = null; + + constructor(readonly affectedKeys: string[], readonly source: ConfigurationTarget, readonly sourceConfig: any) { super(); } + + affectsConfiugration(config: string, resource?: URI): boolean { + if (!this.changedConfiguration) { + this.changedConfiguration = new ConfigurationModel(); + this.updateKeys(this.changedConfiguration, this.affectedKeys); + } + return this.doesConfigurationContains(this.changedConfiguration, config); + } } -export class ConfigurationChangeEvent implements IConfigurationChangeEvent { +export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent implements IConfigurationChangeEvent { private changedConfiguration: ConfigurationModel = new ConfigurationModel(); private changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); @@ -483,7 +515,8 @@ export class ConfigurationChangeEvent implements IConfigurationChangeEvent { this.changedConfigurationByResource.set(resource, changedConfigurationByResource); } } - return this.changeWithKeys(arg1, arg2); + this.changeWithKeys(arg1, arg2); + return this; } telemetryData(source: ConfigurationTarget, sourceConfig: any): ConfigurationChangeEvent { @@ -506,46 +539,30 @@ export class ConfigurationChangeEvent implements IConfigurationChangeEvent { return this._sourceConfig; } - affectsConfiugration(config: string): boolean - affectsConfiugration(config: string, overrideIdentifier: string): boolean - affectsConfiugration(config: string, resource: URI): boolean - affectsConfiugration(config: string, overrideIdentifier: string, resource: URI): boolean - affectsConfiugration(config: string, arg1?: any, arg2?: any): boolean { - let resource = arg1 instanceof URI ? arg1 : arg2 instanceof URI ? arg2 : void 0; - let overrideIdentifier = resource && arg1 !== resource ? arg1 : void 0; - let model = resource ? this.changedConfigurationByResource.get(resource) : this.changedConfiguration; - if (model) { + affectsConfiugration(config: string, resource?: URI): boolean { + let configurationModelsToSearch: ConfigurationModel[] = [this.changedConfiguration]; - if (overrideIdentifier) { - return model.overrides.some(override => override.identifiers.indexOf(overrideIdentifier) !== -1); + if (resource) { + let model = this.changedConfigurationByResource.get(resource); + if (model) { + configurationModelsToSearch.push(model); } - - let changedKeysTree = model.contents; - let requestedTree = toValuesTree({ [config]: true }, () => { }); - - let key; - while (typeof requestedTree === 'object' && (key = Object.keys(requestedTree)[0])) { // Only one key should present, since we added only one property - changedKeysTree = changedKeysTree[key]; - if (!changedKeysTree) { - return false; // Requested tree is not found - } - requestedTree = requestedTree[key]; - } - return true; + } else { + configurationModelsToSearch.push(...this.changedConfigurationByResource.values()); } + + for (const configuration of configurationModelsToSearch) { + if (this.doesConfigurationContains(configuration, config)) { + return true; + } + } + return false; } - private changeWithKeys(keys: string[], resource?: URI): ConfigurationChangeEvent { + private changeWithKeys(keys: string[], resource?: URI): void { let changedConfiguration = resource ? this.getOrSetChangedConfigurationForResource(resource) : this.changedConfiguration; - for (const key of keys) { - if (OVERRIDE_PROPERTY_PATTERN.test(key)) { - changedConfiguration.setValueInOverrides(overrideIdentifierFromKey(key), 'key'/* any key */, true); - } else { - changedConfiguration.setValue(key, true); - } - } - return this; + this.updateKeys(changedConfiguration, keys); } private getOrSetChangedConfigurationForResource(resource: URI): ConfigurationModel { diff --git a/src/vs/platform/configuration/test/common/configurationModels.test.ts b/src/vs/platform/configuration/test/common/configurationModels.test.ts index b4cc2a1d476..294b9d0e69e 100644 --- a/src/vs/platform/configuration/test/common/configurationModels.test.ts +++ b/src/vs/platform/configuration/test/common/configurationModels.test.ts @@ -5,9 +5,11 @@ 'use strict'; import * as assert from 'assert'; -import { ConfigurationModel, CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; +import { ConfigurationModel, CustomConfigurationModel, DefaultConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; +import URI from 'vs/base/common/uri'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; suite('ConfigurationModel', () => { @@ -396,4 +398,116 @@ suite('CustomConfigurationModel', () => { assert.equal(undefined, new DefaultConfigurationModel().getSectionContents('[a]')); }); +}); + +suite('ConfigurationChangeEvent', () => { + + test('changeEvent affecting keys for all resources', () => { + let testObject = new ConfigurationChangeEvent(); + + testObject.change(['window.zoomLevel', 'workbench.editor.enablePreview', 'files', '[markdown]']); + + assert.deepEqual(testObject.affectedKeys, ['window.zoomLevel', 'workbench.editor.enablePreview', 'files', '[markdown]']); + assert.ok(testObject.affectsConfiugration('window.zoomLevel')); + assert.ok(testObject.affectsConfiugration('window')); + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiugration('workbench.editor')); + assert.ok(testObject.affectsConfiugration('workbench')); + assert.ok(testObject.affectsConfiugration('files')); + assert.ok(!testObject.affectsConfiugration('files.exclude')); + assert.ok(testObject.affectsConfiugration('[markdown]')); + }); + + test('changeEvent affecting keys for resources', () => { + let testObject = new ConfigurationChangeEvent(); + + testObject.change(['window.title']); + testObject.change(['window.zoomLevel'], URI.file('file1')); + testObject.change(['workbench.editor.enablePreview'], URI.file('file2')); + testObject.change(['window.restoreFullscreen'], URI.file('file1')); + testObject.change(['window.restoreWindows'], URI.file('file2')); + + assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); + + assert.ok(testObject.affectsConfiugration('window.zoomLevel')); + assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('file1'))); + assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen')); + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file1'))); + assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('window.restoreWindows')); + assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file('file1'))); + + assert.ok(testObject.affectsConfiugration('window.title')); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('window')); + assert.ok(testObject.affectsConfiugration('window', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file1'))); + + assert.ok(testObject.affectsConfiugration('workbench.editor')); + assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file('file1'))); + + assert.ok(testObject.affectsConfiugration('workbench')); + assert.ok(testObject.affectsConfiugration('workbench', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('workbench', URI.file('file1'))); + + assert.ok(!testObject.affectsConfiugration('files')); + assert.ok(!testObject.affectsConfiugration('files', URI.file('file1'))); + assert.ok(!testObject.affectsConfiugration('files', URI.file('file2'))); + }); + +}); + +suite('AllKeysConfigurationChangeEvent', () => { + + test('changeEvent affects keys for any resource', () => { + let testObject = new AllKeysConfigurationChangeEvent(['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows'], ConfigurationTarget.USER, null); + + assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); + + assert.ok(testObject.affectsConfiugration('window.zoomLevel')); + assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen')); + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('window.restoreWindows')); + assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('file2'))); + assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('file1'))); + + assert.ok(testObject.affectsConfiugration('window.title')); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('window')); + assert.ok(testObject.affectsConfiugration('window', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window', URI.file('file2'))); + + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file2'))); + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file1'))); + + assert.ok(testObject.affectsConfiugration('workbench.editor')); + assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('file2'))); + assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('file1'))); + + assert.ok(testObject.affectsConfiugration('workbench')); + assert.ok(testObject.affectsConfiugration('workbench', URI.file('file2'))); + assert.ok(testObject.affectsConfiugration('workbench', URI.file('file1'))); + + assert.ok(!testObject.affectsConfiugration('files')); + assert.ok(!testObject.affectsConfiugration('files', URI.file('file1'))); + }); }); \ No newline at end of file From 9927869cc86ba2307687a124b673dac86d17f7cc Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 10:56:27 +0200 Subject: [PATCH 115/394] Fix workspace configuration change event --- .../common/configurationModels.ts | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index b4518c06965..91366479302 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -268,33 +268,21 @@ export class Configuration extends BaseConfiguration { } } -export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent { +export class WorkspaceConfigurationChangeEvent extends ConfigurationChangeEvent implements IConfigurationChangeEvent { - constructor(private configurationChangeEvent: ConfigurationChangeEvent, private workspace: Workspace) { + constructor(private workspace: Workspace) { + super(); } - get affectedKeys(): string[] { - return this.configurationChangeEvent.affectedKeys; - } - - get source(): ConfigurationTarget { - return this.configurationChangeEvent.source; - } - - get sourceConfig(): any { - return this.configurationChangeEvent.sourceConfig; - } - - affectsConfiugration(config: string, arg1?: any, arg2?: any): boolean { - if (this.configurationChangeEvent.affectsConfiugration(config, arg1, arg2)) { + affectsConfiugration(config: string, resource?: URI): boolean { + if (super.affectsConfiugration(config, resource)) { return true; } - let resource = arg1 instanceof URI ? arg1 : arg2 instanceof URI ? arg2 : void 0; if (resource) { let workspaceFolder = this.workspace.getFolder(resource); if (workspaceFolder) { - return this.configurationChangeEvent.affectsConfiugration(config, resource && arg1 !== resource ? arg1 : void 0, resource); + return super.affectsConfiugration(config, resource); } } From 8b18ddadf1200dd7ef26a35dfe0e3918c4e05df8 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 Oct 2017 11:00:03 +0200 Subject: [PATCH 116/394] move CompositeBar into workbench/parts/compositebar --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 2 +- .../workbench/browser/{ => parts/compositebar}/compositeBar.ts | 2 +- .../browser/{ => parts/compositebar}/compositeBarActions.ts | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/vs/workbench/browser/{ => parts/compositebar}/compositeBar.ts (99%) rename src/vs/workbench/browser/{ => parts/compositebar}/compositeBarActions.ts (100%) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 2130ea88179..857847afc19 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -29,7 +29,7 @@ import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { CompositeBar } from 'vs/workbench/browser/compositeBar'; +import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; export class ActivitybarPart extends Part implements IActivityBarService { diff --git a/src/vs/workbench/browser/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts similarity index 99% rename from src/vs/workbench/browser/compositeBar.ts rename to src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 5320747811c..ec5f8f3e640 100644 --- a/src/vs/workbench/browser/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -21,7 +21,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import Event, { Emitter } from 'vs/base/common/event'; -import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem } from 'vs/workbench/browser/compositeBarActions'; +import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; export interface ICompositeBarOptions { label: 'icon' | 'name'; diff --git a/src/vs/workbench/browser/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts similarity index 100% rename from src/vs/workbench/browser/compositeBarActions.ts rename to src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts From 12fa7c85e29a70285a044d5cae973172d4947b53 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 Oct 2017 11:07:57 +0200 Subject: [PATCH 117/394] move ActivityActinos into compositeBarActions.ts --- .../parts/activitybar/activitybarActions.ts | 214 +---------------- .../parts/compositebar/compositeBar.ts | 3 +- .../parts/compositebar/compositeBarActions.ts | 217 +++++++++++++++++- 3 files changed, 216 insertions(+), 218 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 69b532ccb46..b20d15c85cb 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -9,11 +9,8 @@ import 'vs/css!./media/activityaction'; import nls = require('vs/nls'); import DOM = require('vs/base/browser/dom'); import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, $ } from 'vs/base/browser/builder'; import { Action } from 'vs/base/common/actions'; -import { BaseActionItem, IBaseActionItemOptions } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IActivityBarService, ProgressBadge, TextBadge, NumberBadge, IconBadge, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { IActivityBarService } from 'vs/workbench/services/activity/common/activityBarService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IActivity, IGlobalActivity } from 'vs/workbench/common/activity'; @@ -21,51 +18,11 @@ import { dispose } from 'vs/base/common/lifecycle'; import { IViewletService, } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { IThemeService, ITheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; -import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; -import { contrastBorder, activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; +import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; - -export class ActivityAction extends Action { - private badge: IBadge; - private _onDidChangeBadge = new Emitter(); - - constructor(private _activity: IActivity) { - super(_activity.id, _activity.name, _activity.cssClass); - - this.badge = null; - } - - public get activity(): IActivity { - return this._activity; - } - - public get onDidChangeBadge(): Event { - return this._onDidChangeBadge.event; - } - - public activate(): void { - if (!this.checked) { - this._setChecked(true); - } - } - - public deactivate(): void { - if (this.checked) { - this._setChecked(false); - } - } - - public getBadge(): IBadge { - return this.badge; - } - - public setBadge(badge: IBadge): void { - this.badge = badge; - this._onDidChangeBadge.fire(this); - } -} +import { ActivityAction, ActivityActionItem } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; export class ViewletActivityAction extends ActivityAction { @@ -105,171 +62,6 @@ export class ViewletActivityAction extends ActivityAction { } } -export class ActivityActionItem extends BaseActionItem { - protected $container: Builder; - protected $label: Builder; - protected $badge: Builder; - - private $badgeContent: Builder; - private mouseUpTimeout: number; - - constructor( - action: ActivityAction, - options: IBaseActionItemOptions, - @IThemeService protected themeService: IThemeService - ) { - super(null, action, options); - - this.themeService.onThemeChange(this.onThemeChange, this, this._callOnDispose); - action.onDidChangeBadge(this.handleBadgeChangeEvenet, this, this._callOnDispose); - } - - protected get activity(): IActivity { - return (this._action as ActivityAction).activity; - } - - protected updateStyles(): void { - const theme = this.themeService.getTheme(); - - // Label - if (this.$label) { - const background = theme.getColor(ACTIVITY_BAR_FOREGROUND); - - this.$label.style('background-color', background ? background.toString() : null); - } - - // Badge - if (this.$badgeContent) { - const badgeForeground = theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND); - const badgeBackground = theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND); - const contrastBorderColor = theme.getColor(contrastBorder); - - this.$badgeContent.style('color', badgeForeground ? badgeForeground.toString() : null); - this.$badgeContent.style('background-color', badgeBackground ? badgeBackground.toString() : null); - - this.$badgeContent.style('border-style', contrastBorderColor ? 'solid' : null); - this.$badgeContent.style('border-width', contrastBorderColor ? '1px' : null); - this.$badgeContent.style('border-color', contrastBorderColor ? contrastBorderColor.toString() : null); - } - } - - public render(container: HTMLElement): void { - super.render(container); - - // Make the container tab-able for keyboard navigation - this.$container = $(container).attr({ - tabIndex: '0', - role: 'button', - title: this.activity.name - }); - - // Try hard to prevent keyboard only focus feedback when using mouse - this.$container.on(DOM.EventType.MOUSE_DOWN, () => { - this.$container.addClass('clicked'); - }); - - this.$container.on(DOM.EventType.MOUSE_UP, () => { - if (this.mouseUpTimeout) { - clearTimeout(this.mouseUpTimeout); - } - - this.mouseUpTimeout = setTimeout(() => { - this.$container.removeClass('clicked'); - }, 800); // delayed to prevent focus feedback from showing on mouse up - }); - - // Label - this.$label = $('a.action-label').appendTo(this.builder); - if (this.activity.cssClass) { - this.$label.addClass(this.activity.cssClass); - } - - this.$badge = this.builder.clone().div({ 'class': 'badge' }, (badge: Builder) => { - this.$badgeContent = badge.div({ 'class': 'badge-content' }); - }); - - this.$badge.hide(); - - this.updateStyles(); - } - - private onThemeChange(theme: ITheme): void { - this.updateStyles(); - } - - public setBadge(badge: IBadge): void { - this.updateBadge(badge); - } - - protected updateBadge(badge: IBadge): void { - this.$badgeContent.empty(); - this.$badge.hide(); - - if (badge) { - - // Number - if (badge instanceof NumberBadge) { - if (badge.number) { - this.$badgeContent.text(badge.number > 99 ? '99+' : badge.number.toString()); - this.$badge.show(); - } - } - - // Text - else if (badge instanceof TextBadge) { - this.$badgeContent.text(badge.text); - this.$badge.show(); - } - - // Text - else if (badge instanceof IconBadge) { - this.$badge.show(); - } - - // Progress - else if (badge instanceof ProgressBadge) { - this.$badge.show(); - } - } - - // Title - let title: string; - if (badge && badge.getDescription()) { - if (this.activity.name) { - title = nls.localize('badgeTitle', "{0} - {1}", this.activity.name, badge.getDescription()); - } else { - title = badge.getDescription(); - } - } else { - title = this.activity.name; - } - - [this.$label, this.$badge, this.$container].forEach(b => { - if (b) { - b.attr('aria-label', title); - b.title(title); - } - }); - } - - private handleBadgeChangeEvenet(): void { - const action = this.getAction(); - if (action instanceof ActivityAction) { - this.updateBadge(action.getBadge()); - } - } - - public dispose(): void { - super.dispose(); - - if (this.mouseUpTimeout) { - clearTimeout(this.mouseUpTimeout); - } - - this.$badge.destroy(); - } -} - export class OpenViewletAction extends Action { constructor( diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index ec5f8f3e640..18b83e8938e 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -18,10 +18,9 @@ import { IBadge } from 'vs/workbench/services/activity/common/activityBarService import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import Event, { Emitter } from 'vs/base/common/event'; -import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; export interface ICompositeBarOptions { label: 'icon' | 'name'; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 6b0986b6b0f..184dd5ae36e 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -9,24 +9,231 @@ import nls = require('vs/nls'); import { Action } from 'vs/base/common/actions'; import { TPromise } from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; +import { Builder, $ } from 'vs/base/browser/builder'; +import { BaseActionItem, IBaseActionItemOptions, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { dispose } from 'vs/base/common/lifecycle'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IActivityBarService, TextBadge, NumberBadge, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; +import { IActivityBarService, TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activityBarService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ActivityAction, ActivityActionItem } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; -import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; -import { ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; +import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import Event, { Emitter } from 'vs/base/common/event'; export interface ICompositeActivity { badge: IBadge; clazz: string; } +export class ActivityAction extends Action { + private badge: IBadge; + private _onDidChangeBadge = new Emitter(); + + constructor(private _activity: IActivity) { + super(_activity.id, _activity.name, _activity.cssClass); + + this.badge = null; + } + + public get activity(): IActivity { + return this._activity; + } + + public get onDidChangeBadge(): Event { + return this._onDidChangeBadge.event; + } + + public activate(): void { + if (!this.checked) { + this._setChecked(true); + } + } + + public deactivate(): void { + if (this.checked) { + this._setChecked(false); + } + } + + public getBadge(): IBadge { + return this.badge; + } + + public setBadge(badge: IBadge): void { + this.badge = badge; + this._onDidChangeBadge.fire(this); + } +} + +export class ActivityActionItem extends BaseActionItem { + protected $container: Builder; + protected $label: Builder; + protected $badge: Builder; + + private $badgeContent: Builder; + private mouseUpTimeout: number; + + constructor( + action: ActivityAction, + options: IBaseActionItemOptions, + @IThemeService protected themeService: IThemeService + ) { + super(null, action, options); + + this.themeService.onThemeChange(this.onThemeChange, this, this._callOnDispose); + action.onDidChangeBadge(this.handleBadgeChangeEvenet, this, this._callOnDispose); + } + + protected get activity(): IActivity { + return (this._action as ActivityAction).activity; + } + + protected updateStyles(): void { + const theme = this.themeService.getTheme(); + + // Label + if (this.$label) { + const background = theme.getColor(ACTIVITY_BAR_FOREGROUND); + + this.$label.style('background-color', background ? background.toString() : null); + } + + // Badge + if (this.$badgeContent) { + const badgeForeground = theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND); + const badgeBackground = theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND); + const contrastBorderColor = theme.getColor(contrastBorder); + + this.$badgeContent.style('color', badgeForeground ? badgeForeground.toString() : null); + this.$badgeContent.style('background-color', badgeBackground ? badgeBackground.toString() : null); + + this.$badgeContent.style('border-style', contrastBorderColor ? 'solid' : null); + this.$badgeContent.style('border-width', contrastBorderColor ? '1px' : null); + this.$badgeContent.style('border-color', contrastBorderColor ? contrastBorderColor.toString() : null); + } + } + + public render(container: HTMLElement): void { + super.render(container); + + // Make the container tab-able for keyboard navigation + this.$container = $(container).attr({ + tabIndex: '0', + role: 'button', + title: this.activity.name + }); + + // Try hard to prevent keyboard only focus feedback when using mouse + this.$container.on(dom.EventType.MOUSE_DOWN, () => { + this.$container.addClass('clicked'); + }); + + this.$container.on(dom.EventType.MOUSE_UP, () => { + if (this.mouseUpTimeout) { + clearTimeout(this.mouseUpTimeout); + } + + this.mouseUpTimeout = setTimeout(() => { + this.$container.removeClass('clicked'); + }, 800); // delayed to prevent focus feedback from showing on mouse up + }); + + // Label + this.$label = $('a.action-label').appendTo(this.builder); + if (this.activity.cssClass) { + this.$label.addClass(this.activity.cssClass); + } + + this.$badge = this.builder.clone().div({ 'class': 'badge' }, (badge: Builder) => { + this.$badgeContent = badge.div({ 'class': 'badge-content' }); + }); + + this.$badge.hide(); + + this.updateStyles(); + } + + private onThemeChange(theme: ITheme): void { + this.updateStyles(); + } + + public setBadge(badge: IBadge): void { + this.updateBadge(badge); + } + + protected updateBadge(badge: IBadge): void { + this.$badgeContent.empty(); + this.$badge.hide(); + + if (badge) { + + // Number + if (badge instanceof NumberBadge) { + if (badge.number) { + this.$badgeContent.text(badge.number > 99 ? '99+' : badge.number.toString()); + this.$badge.show(); + } + } + + // Text + else if (badge instanceof TextBadge) { + this.$badgeContent.text(badge.text); + this.$badge.show(); + } + + // Text + else if (badge instanceof IconBadge) { + this.$badge.show(); + } + + // Progress + else if (badge instanceof ProgressBadge) { + this.$badge.show(); + } + } + + // Title + let title: string; + if (badge && badge.getDescription()) { + if (this.activity.name) { + title = nls.localize('badgeTitle', "{0} - {1}", this.activity.name, badge.getDescription()); + } else { + title = badge.getDescription(); + } + } else { + title = this.activity.name; + } + + [this.$label, this.$badge, this.$container].forEach(b => { + if (b) { + b.attr('aria-label', title); + b.title(title); + } + }); + } + + private handleBadgeChangeEvenet(): void { + const action = this.getAction(); + if (action instanceof ActivityAction) { + this.updateBadge(action.getBadge()); + } + } + + public dispose(): void { + super.dispose(); + + if (this.mouseUpTimeout) { + clearTimeout(this.mouseUpTimeout); + } + + this.$badge.destroy(); + } +} + export class CompositeOverflowActivityAction extends ActivityAction { constructor( From 1a87d359d7e0e10dd93f662287f30efba5a6161f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 11:12:26 +0200 Subject: [PATCH 118/394] tests for workspace configuration change event --- .../common/configurationModels.ts | 2 +- .../test/common/configurationModels.test.ts | 97 ++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 91366479302..48506da5b83 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -282,7 +282,7 @@ export class WorkspaceConfigurationChangeEvent extends ConfigurationChangeEvent if (resource) { let workspaceFolder = this.workspace.getFolder(resource); if (workspaceFolder) { - return super.affectsConfiugration(config, resource); + return super.affectsConfiugration(config, workspaceFolder.uri); } } diff --git a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts index 14e684e145e..90091e4f0c1 100644 --- a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts +++ b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts @@ -5,8 +5,11 @@ 'use strict'; import * as assert from 'assert'; -import { FolderConfigurationModel, ScopedConfigurationModel, FolderSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; +import { join } from 'vs/base/common/paths'; +import { FolderConfigurationModel, ScopedConfigurationModel, FolderSettingsModel, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import URI from 'vs/base/common/uri'; suite('ConfigurationService - Model', () => { @@ -94,4 +97,96 @@ suite('ConfigurationService - Model', () => { assert.deepEqual(new FolderConfigurationModel(settingsConfig, [launchConfig, tasksConfig], ConfigurationScope.WINDOW).contents, expected); assert.deepEqual(new FolderConfigurationModel(settingsConfig, [tasksConfig, launchConfig], ConfigurationScope.WINDOW).contents, expected); }); +}); + +suite('WorkspaceConfigurationChangeEvent', () => { + + test('changeEvent affecting workspace folders', () => { + let testObject = new WorkspaceConfigurationChangeEvent(new Workspace('id', 'name', + [new WorkspaceFolder({ index: 0, name: '1', uri: URI.file('folder1') }), + new WorkspaceFolder({ index: 1, name: '2', uri: URI.file('folder2') }), + new WorkspaceFolder({ index: 2, name: '3', uri: URI.file('folder3') })])); + + testObject.change(['window.title']); + testObject.change(['window.zoomLevel'], URI.file('folder1')); + testObject.change(['workbench.editor.enablePreview'], URI.file('folder2')); + testObject.change(['window.restoreFullscreen'], URI.file('folder1')); + testObject.change(['window.restoreWindows'], URI.file('folder2')); + + assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); + + assert.ok(testObject.affectsConfiugration('window.zoomLevel')); + assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('folder1'))); + assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file('file1'))); + assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file(join('folder3', 'file3')))); + + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen')); + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file(join('folder1', 'file1')))); + assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file1'))); + assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file(join('folder3', 'file3')))); + + assert.ok(testObject.affectsConfiugration('window.restoreWindows')); + assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('folder2'))); + assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file('file2'))); + assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file(join('folder3', 'file3')))); + + assert.ok(testObject.affectsConfiugration('window.title')); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('folder1'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file(join('folder1', 'file1')))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('folder2'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file(join('folder2', 'file2')))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('folder3'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file2'))); + assert.ok(testObject.affectsConfiugration('window.title', URI.file('file3'))); + + assert.ok(testObject.affectsConfiugration('window')); + assert.ok(testObject.affectsConfiugration('window', URI.file('folder1'))); + assert.ok(testObject.affectsConfiugration('window', URI.file(join('folder1', 'file1')))); + assert.ok(testObject.affectsConfiugration('window', URI.file('folder2'))); + assert.ok(testObject.affectsConfiugration('window', URI.file(join('folder2', 'file2')))); + assert.ok(testObject.affectsConfiugration('window', URI.file('folder3'))); + assert.ok(testObject.affectsConfiugration('window', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiugration('window', URI.file('file1'))); + assert.ok(testObject.affectsConfiugration('window', URI.file('file2'))); + assert.ok(testObject.affectsConfiugration('window', URI.file('file3'))); + + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('folder2'))); + assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('folder3'))); + + assert.ok(testObject.affectsConfiugration('workbench.editor')); + assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('folder2'))); + assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file('folder3'))); + + assert.ok(testObject.affectsConfiugration('workbench')); + assert.ok(testObject.affectsConfiugration('workbench', URI.file('folder2'))); + assert.ok(testObject.affectsConfiugration('workbench', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('workbench', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiugration('workbench', URI.file('folder3'))); + + assert.ok(!testObject.affectsConfiugration('files')); + assert.ok(!testObject.affectsConfiugration('files', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiugration('files', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiugration('files', URI.file('folder2'))); + assert.ok(!testObject.affectsConfiugration('files', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiugration('files', URI.file('folder3'))); + assert.ok(!testObject.affectsConfiugration('files', URI.file(join('folder3', 'file3')))); + }); + }); \ No newline at end of file From 788c5c536b32f667419f9a1e458fb29e7e67e27f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 11:15:23 +0200 Subject: [PATCH 119/394] Correct mistyping --- .../configuration/common/configuration.ts | 2 +- .../common/configurationModels.ts | 4 +- .../test/common/configurationModels.test.ts | 122 ++++++++--------- .../parts/debug/browser/debugActionItems.ts | 2 +- .../watermark/electron-browser/watermark.ts | 2 +- .../common/configurationModels.ts | 6 +- .../test/common/configurationModels.test.ts | 128 +++++++++--------- 7 files changed, 133 insertions(+), 133 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 16e5736bd3f..5cbe7665027 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -31,7 +31,7 @@ export enum ConfigurationTarget { export interface IConfigurationChangeEvent { affectedKeys: string[]; - affectsConfiugration(configuration: string, resource?: URI): boolean; + affectsConfiguration(configuration: string, resource?: URI): boolean; // Following data is used for telemetry source: ConfigurationTarget; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index be314db0f04..a7e62338321 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -485,7 +485,7 @@ export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChange constructor(readonly affectedKeys: string[], readonly source: ConfigurationTarget, readonly sourceConfig: any) { super(); } - affectsConfiugration(config: string, resource?: URI): boolean { + affectsConfiguration(config: string, resource?: URI): boolean { if (!this.changedConfiguration) { this.changedConfiguration = new ConfigurationModel(); this.updateKeys(this.changedConfiguration, this.affectedKeys); @@ -539,7 +539,7 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i return this._sourceConfig; } - affectsConfiugration(config: string, resource?: URI): boolean { + affectsConfiguration(config: string, resource?: URI): boolean { let configurationModelsToSearch: ConfigurationModel[] = [this.changedConfiguration]; if (resource) { diff --git a/src/vs/platform/configuration/test/common/configurationModels.test.ts b/src/vs/platform/configuration/test/common/configurationModels.test.ts index 294b9d0e69e..598b7d6d616 100644 --- a/src/vs/platform/configuration/test/common/configurationModels.test.ts +++ b/src/vs/platform/configuration/test/common/configurationModels.test.ts @@ -408,14 +408,14 @@ suite('ConfigurationChangeEvent', () => { testObject.change(['window.zoomLevel', 'workbench.editor.enablePreview', 'files', '[markdown]']); assert.deepEqual(testObject.affectedKeys, ['window.zoomLevel', 'workbench.editor.enablePreview', 'files', '[markdown]']); - assert.ok(testObject.affectsConfiugration('window.zoomLevel')); - assert.ok(testObject.affectsConfiugration('window')); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); - assert.ok(testObject.affectsConfiugration('workbench.editor')); - assert.ok(testObject.affectsConfiugration('workbench')); - assert.ok(testObject.affectsConfiugration('files')); - assert.ok(!testObject.affectsConfiugration('files.exclude')); - assert.ok(testObject.affectsConfiugration('[markdown]')); + assert.ok(testObject.affectsConfiguration('window.zoomLevel')); + assert.ok(testObject.affectsConfiguration('window')); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiguration('workbench.editor')); + assert.ok(testObject.affectsConfiguration('workbench')); + assert.ok(testObject.affectsConfiguration('files')); + assert.ok(!testObject.affectsConfiguration('files.exclude')); + assert.ok(testObject.affectsConfiguration('[markdown]')); }); test('changeEvent affecting keys for resources', () => { @@ -429,41 +429,41 @@ suite('ConfigurationChangeEvent', () => { assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); - assert.ok(testObject.affectsConfiugration('window.zoomLevel')); - assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.zoomLevel')); + assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('file1'))); + assert.ok(!testObject.affectsConfiguration('window.zoomLevel', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen')); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen')); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file1'))); + assert.ok(!testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window.restoreWindows')); - assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.restoreWindows')); + assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('window.restoreWindows', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.title')); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.title')); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window')); - assert.ok(testObject.affectsConfiugration('window', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window')); + assert.ok(testObject.affectsConfiguration('window', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('workbench.editor')); - assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('workbench.editor')); + assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('workbench.editor', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('workbench')); - assert.ok(testObject.affectsConfiugration('workbench', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('workbench', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('workbench')); + assert.ok(testObject.affectsConfiguration('workbench', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('workbench', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('files')); - assert.ok(!testObject.affectsConfiugration('files', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('files', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('files')); + assert.ok(!testObject.affectsConfiguration('files', URI.file('file1'))); + assert.ok(!testObject.affectsConfiguration('files', URI.file('file2'))); }); }); @@ -475,39 +475,39 @@ suite('AllKeysConfigurationChangeEvent', () => { assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); - assert.ok(testObject.affectsConfiugration('window.zoomLevel')); - assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.zoomLevel')); + assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen')); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen')); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window.restoreWindows')); - assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.restoreWindows')); + assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.title')); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.title')); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window')); - assert.ok(testObject.affectsConfiugration('window', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window')); + assert.ok(testObject.affectsConfiguration('window', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('workbench.editor')); - assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('workbench.editor')); + assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('workbench')); - assert.ok(testObject.affectsConfiugration('workbench', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('workbench', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('workbench')); + assert.ok(testObject.affectsConfiguration('workbench', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('workbench', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('files')); - assert.ok(!testObject.affectsConfiugration('files', URI.file('file1'))); + assert.ok(!testObject.affectsConfiguration('files')); + assert.ok(!testObject.affectsConfiguration('files', URI.file('file1'))); }); }); \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 4cba52bfbcc..9467e227330 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -55,7 +55,7 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem { private registerListeners(): void { this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - if (e.affectsConfiugration('launch')) { + if (e.affectsConfiguration('launch')) { this.updateOptions(); } })); diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 11538b93dad..ec6aa876b65 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -127,7 +127,7 @@ export class WatermarkContribution implements IWorkbenchContribution { } }); this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { - if (e.affectsConfiugration(WORKBENCH_TIPS_ENABLED_KEY)) { + if (e.affectsConfiguration(WORKBENCH_TIPS_ENABLED_KEY)) { const enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); if (enabled !== this.enabled) { this.enabled = enabled; diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 48506da5b83..1fd4c79e89d 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -274,15 +274,15 @@ export class WorkspaceConfigurationChangeEvent extends ConfigurationChangeEvent super(); } - affectsConfiugration(config: string, resource?: URI): boolean { - if (super.affectsConfiugration(config, resource)) { + affectsConfiguration(config: string, resource?: URI): boolean { + if (super.affectsConfiguration(config, resource)) { return true; } if (resource) { let workspaceFolder = this.workspace.getFolder(resource); if (workspaceFolder) { - return super.affectsConfiugration(config, workspaceFolder.uri); + return super.affectsConfiguration(config, workspaceFolder.uri); } } diff --git a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts index 90091e4f0c1..58e25f17575 100644 --- a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts +++ b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts @@ -115,78 +115,78 @@ suite('WorkspaceConfigurationChangeEvent', () => { assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); - assert.ok(testObject.affectsConfiugration('window.zoomLevel')); - assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file('folder1'))); - assert.ok(testObject.affectsConfiugration('window.zoomLevel', URI.file(join('folder1', 'file1')))); - assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('window.zoomLevel', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiguration('window.zoomLevel')); + assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('folder1'))); + assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiguration('window.zoomLevel', URI.file('file1'))); + assert.ok(!testObject.affectsConfiguration('window.zoomLevel', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('window.zoomLevel', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('window.zoomLevel', URI.file(join('folder3', 'file3')))); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen')); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file(join('folder1', 'file1')))); - assert.ok(testObject.affectsConfiugration('window.restoreFullscreen', URI.file('folder1'))); - assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file1'))); - assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('window.restoreFullscreen', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen')); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file(join('folder1', 'file1')))); + assert.ok(testObject.affectsConfiguration('window.restoreFullscreen', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file1'))); + assert.ok(!testObject.affectsConfiguration('window.restoreFullscreen', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('window.restoreFullscreen', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('window.restoreFullscreen', URI.file(join('folder3', 'file3')))); - assert.ok(testObject.affectsConfiugration('window.restoreWindows')); - assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file('folder2'))); - assert.ok(testObject.affectsConfiugration('window.restoreWindows', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file('file2'))); - assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file(join('folder1', 'file1')))); - assert.ok(!testObject.affectsConfiugration('window.restoreWindows', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiguration('window.restoreWindows')); + assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file('folder2'))); + assert.ok(testObject.affectsConfiguration('window.restoreWindows', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('window.restoreWindows', URI.file('file2'))); + assert.ok(!testObject.affectsConfiguration('window.restoreWindows', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiguration('window.restoreWindows', URI.file(join('folder3', 'file3')))); - assert.ok(testObject.affectsConfiugration('window.title')); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('folder1'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file(join('folder1', 'file1')))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('folder2'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file(join('folder2', 'file2')))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('folder3'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file(join('folder3', 'file3')))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window.title', URI.file('file3'))); + assert.ok(testObject.affectsConfiguration('window.title')); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('folder1'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file(join('folder1', 'file1')))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('folder2'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file(join('folder2', 'file2')))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('folder3'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window.title', URI.file('file3'))); - assert.ok(testObject.affectsConfiugration('window')); - assert.ok(testObject.affectsConfiugration('window', URI.file('folder1'))); - assert.ok(testObject.affectsConfiugration('window', URI.file(join('folder1', 'file1')))); - assert.ok(testObject.affectsConfiugration('window', URI.file('folder2'))); - assert.ok(testObject.affectsConfiugration('window', URI.file(join('folder2', 'file2')))); - assert.ok(testObject.affectsConfiugration('window', URI.file('folder3'))); - assert.ok(testObject.affectsConfiugration('window', URI.file(join('folder3', 'file3')))); - assert.ok(testObject.affectsConfiugration('window', URI.file('file1'))); - assert.ok(testObject.affectsConfiugration('window', URI.file('file2'))); - assert.ok(testObject.affectsConfiugration('window', URI.file('file3'))); + assert.ok(testObject.affectsConfiguration('window')); + assert.ok(testObject.affectsConfiguration('window', URI.file('folder1'))); + assert.ok(testObject.affectsConfiguration('window', URI.file(join('folder1', 'file1')))); + assert.ok(testObject.affectsConfiguration('window', URI.file('folder2'))); + assert.ok(testObject.affectsConfiguration('window', URI.file(join('folder2', 'file2')))); + assert.ok(testObject.affectsConfiguration('window', URI.file('folder3'))); + assert.ok(testObject.affectsConfiguration('window', URI.file(join('folder3', 'file3')))); + assert.ok(testObject.affectsConfiguration('window', URI.file('file1'))); + assert.ok(testObject.affectsConfiguration('window', URI.file('file2'))); + assert.ok(testObject.affectsConfiguration('window', URI.file('file3'))); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview')); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('folder2'))); - assert.ok(testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('folder1'))); - assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file(join('folder1', 'file1')))); - assert.ok(!testObject.affectsConfiugration('workbench.editor.enablePreview', URI.file('folder3'))); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview')); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('folder2'))); + assert.ok(testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiguration('workbench.editor.enablePreview', URI.file('folder3'))); - assert.ok(testObject.affectsConfiugration('workbench.editor')); - assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file('folder2'))); - assert.ok(testObject.affectsConfiugration('workbench.editor', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file('folder1'))); - assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file(join('folder1', 'file1')))); - assert.ok(!testObject.affectsConfiugration('workbench.editor', URI.file('folder3'))); + assert.ok(testObject.affectsConfiguration('workbench.editor')); + assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file('folder2'))); + assert.ok(testObject.affectsConfiguration('workbench.editor', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('workbench.editor', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiguration('workbench.editor', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiguration('workbench.editor', URI.file('folder3'))); - assert.ok(testObject.affectsConfiugration('workbench')); - assert.ok(testObject.affectsConfiugration('workbench', URI.file('folder2'))); - assert.ok(testObject.affectsConfiugration('workbench', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('workbench', URI.file('folder1'))); - assert.ok(!testObject.affectsConfiugration('workbench', URI.file('folder3'))); + assert.ok(testObject.affectsConfiguration('workbench')); + assert.ok(testObject.affectsConfiguration('workbench', URI.file('folder2'))); + assert.ok(testObject.affectsConfiguration('workbench', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('workbench', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiguration('workbench', URI.file('folder3'))); - assert.ok(!testObject.affectsConfiugration('files')); - assert.ok(!testObject.affectsConfiugration('files', URI.file('folder1'))); - assert.ok(!testObject.affectsConfiugration('files', URI.file(join('folder1', 'file1')))); - assert.ok(!testObject.affectsConfiugration('files', URI.file('folder2'))); - assert.ok(!testObject.affectsConfiugration('files', URI.file(join('folder2', 'file2')))); - assert.ok(!testObject.affectsConfiugration('files', URI.file('folder3'))); - assert.ok(!testObject.affectsConfiugration('files', URI.file(join('folder3', 'file3')))); + assert.ok(!testObject.affectsConfiguration('files')); + assert.ok(!testObject.affectsConfiguration('files', URI.file('folder1'))); + assert.ok(!testObject.affectsConfiguration('files', URI.file(join('folder1', 'file1')))); + assert.ok(!testObject.affectsConfiguration('files', URI.file('folder2'))); + assert.ok(!testObject.affectsConfiguration('files', URI.file(join('folder2', 'file2')))); + assert.ok(!testObject.affectsConfiguration('files', URI.file('folder3'))); + assert.ok(!testObject.affectsConfiguration('files', URI.file(join('folder3', 'file3')))); }); }); \ No newline at end of file From 0d9e0253582be4c704ce3e684a1307ee3c3e8cce Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 11:20:11 +0200 Subject: [PATCH 120/394] Use wrapper pattern for Workspace Configuration Change Event --- .../common/configurationModels.ts | 23 ++++++++++++++----- .../test/common/configurationModels.test.ts | 19 +++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 1fd4c79e89d..8b9e5aa53fe 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -268,21 +268,32 @@ export class Configuration extends BaseConfiguration { } } -export class WorkspaceConfigurationChangeEvent extends ConfigurationChangeEvent implements IConfigurationChangeEvent { +export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent { - constructor(private workspace: Workspace) { - super(); + constructor(private configurationChangeEvent: ConfigurationChangeEvent, private workspace: Workspace) { + } + + get affectedKeys(): string[] { + return this.configurationChangeEvent.affectedKeys; + } + + get source(): ConfigurationTarget { + return this.configurationChangeEvent.source; + } + + get sourceConfig(): any { + return this.configurationChangeEvent.sourceConfig; } affectsConfiguration(config: string, resource?: URI): boolean { - if (super.affectsConfiguration(config, resource)) { + if (this.configurationChangeEvent.affectsConfiguration(config, resource)) { return true; } if (resource) { let workspaceFolder = this.workspace.getFolder(resource); if (workspaceFolder) { - return super.affectsConfiguration(config, workspaceFolder.uri); + return this.configurationChangeEvent.affectsConfiguration(config, workspaceFolder.uri); } } diff --git a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts index 58e25f17575..781260d8502 100644 --- a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts +++ b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts @@ -10,6 +10,8 @@ import { FolderConfigurationModel, ScopedConfigurationModel, FolderSettingsModel import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import URI from 'vs/base/common/uri'; +import { ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; suite('ConfigurationService - Model', () => { @@ -102,18 +104,21 @@ suite('ConfigurationService - Model', () => { suite('WorkspaceConfigurationChangeEvent', () => { test('changeEvent affecting workspace folders', () => { - let testObject = new WorkspaceConfigurationChangeEvent(new Workspace('id', 'name', + let configurationChangeEvent = new ConfigurationChangeEvent(); + configurationChangeEvent.change(['window.title']); + configurationChangeEvent.change(['window.zoomLevel'], URI.file('folder1')); + configurationChangeEvent.change(['workbench.editor.enablePreview'], URI.file('folder2')); + configurationChangeEvent.change(['window.restoreFullscreen'], URI.file('folder1')); + configurationChangeEvent.change(['window.restoreWindows'], URI.file('folder2')); + configurationChangeEvent.telemetryData(ConfigurationTarget.WORKSPACE, {}); + + let testObject = new WorkspaceConfigurationChangeEvent(configurationChangeEvent, new Workspace('id', 'name', [new WorkspaceFolder({ index: 0, name: '1', uri: URI.file('folder1') }), new WorkspaceFolder({ index: 1, name: '2', uri: URI.file('folder2') }), new WorkspaceFolder({ index: 2, name: '3', uri: URI.file('folder3') })])); - testObject.change(['window.title']); - testObject.change(['window.zoomLevel'], URI.file('folder1')); - testObject.change(['workbench.editor.enablePreview'], URI.file('folder2')); - testObject.change(['window.restoreFullscreen'], URI.file('folder1')); - testObject.change(['window.restoreWindows'], URI.file('folder2')); - assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); + assert.equal(testObject.source, ConfigurationTarget.WORKSPACE); assert.ok(testObject.affectsConfiguration('window.zoomLevel')); assert.ok(testObject.affectsConfiguration('window.zoomLevel', URI.file('folder1'))); From db4031b6d5ced25fb689461cdf9ae4fd0fa5c3ad Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 11:33:03 +0200 Subject: [PATCH 121/394] deco - fallback to tree color only when an element is focused *and* selected --- .../services/decorations/browser/decorationsService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 522181bb4d9..feb0ff47fe3 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -52,7 +52,7 @@ class DecorationRule { const { color, opacity, letter } = data; // label createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); - createCSSRule(`.selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); + createCSSRule(`.focused .selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); // badge if (letter) { createCSSRule(`.${this.badgeClassName}`, `background-color: ${theme.getColor(color)}; color: ${theme.getColor(listActiveSelectionForeground)};`, element); @@ -64,7 +64,7 @@ class DecorationRule { // label const { color, opacity } = data[0]; createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); - createCSSRule(`.selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); + createCSSRule(`.focused .selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); // badge let letters: string[] = []; From 996d90415e831d8682b6b6ee149b4aee3085097e Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 11:52:50 +0200 Subject: [PATCH 122/394] Revert changes in preferences --- .../parts/preferences/browser/preferencesRenderers.ts | 5 ++--- .../parts/preferences/browser/preferencesService.ts | 4 +--- .../workbench/parts/preferences/common/preferencesModels.ts | 4 +--- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 98996425277..6a06a153b61 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -561,9 +561,8 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr range, options: { stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - className: 'findMatch', - - }, + className: 'findMatch' + } }; } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 3a786ee208c..c3f74852cee 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -119,7 +119,6 @@ export class PreferencesService extends Disposable implements IPreferencesServic .then(preferencesEditorModel => preferencesEditorModel ? preferencesEditorModel.content : null); } - // vsode://DefaultSettings/1 createPreferencesEditorModel(uri: URI): TPromise> { let promise = this.defaultPreferencesEditorModels.get(uri); if (promise) { @@ -251,7 +250,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { - const openDefaultSettings = !!this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value; + const openDefaultSettings = !!this.configurationService.getValue(DEFAULT_SETTINGS_EDITOR_SETTING); return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource) .then(editableSettingsEditorInput => { if (!options) { @@ -261,7 +260,6 @@ export class PreferencesService extends Disposable implements IPreferencesServic } if (openDefaultSettings) { - // get a new URI for default settings here const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(configurationTarget)); const preferencesEditorInput = new PreferencesEditorInput(this.getPreferencesEditorInputName(configurationTarget, resource), editableSettingsEditorInput.getDescription(), defaultPreferencesEditorInput, editableSettingsEditorInput); this.lastOpenedSettingsInput = preferencesEditorInput; diff --git a/src/vs/workbench/parts/preferences/common/preferencesModels.ts b/src/vs/workbench/parts/preferences/common/preferencesModels.ts index 26e4c93d348..f17231a589b 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesModels.ts @@ -244,9 +244,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti constructor(reference: IReference, private _configurationTarget: ConfigurationTarget, @ITextFileService protected textFileService: ITextFileService) { super(); this.settingsModel = reference.object.textEditorModel; - this._register(this.onDispose(() => { - reference.dispose(); - })); + this._register(this.onDispose(() => reference.dispose())); this._register(this.settingsModel.onDidChangeContent(() => { this._settingsGroups = null; })); From 342f81d2483d79bd86e6722d7976713364bea367 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 Oct 2017 11:54:37 +0200 Subject: [PATCH 123/394] quick open - add and use prepareQuery --- .../parts/quickopen/common/quickOpenScorer.ts | 75 ++++--- .../test/common/quickOpenScorer.test.ts | 183 ++++++++++-------- .../browser/parts/editor/editorPicker.ts | 14 +- .../parts/quickopen/quickOpenController.ts | 12 +- .../search/browser/openAnythingHandler.ts | 23 +-- .../services/search/node/rawSearchService.ts | 5 +- 6 files changed, 172 insertions(+), 140 deletions(-) diff --git a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts index fe804a29d1f..a479c16aa0a 100644 --- a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts +++ b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts @@ -16,7 +16,7 @@ export type ScorerCache = { [key: string]: IItemScore }; const NO_SCORE: Score = [0, []]; -export function _doScore(target: string, query: string, fuzzy: boolean): Score { +export function _doScore(target: string, query: string, queryLower: string, fuzzy: boolean): Score { if (!target || !query) { return NO_SCORE; // return early if target or query are undefined } @@ -29,7 +29,6 @@ export function _doScore(target: string, query: string, fuzzy: boolean): Score { const queryLen = query.length; const targetLower = target.toLowerCase(); - const queryLower = query.toLowerCase(); let res = NO_SCORE; @@ -236,8 +235,34 @@ const LABEL_PREFIX_SCORE = 1 << 17; const LABEL_CAMELCASE_SCORE = 1 << 16; const LABEL_SCORE_THRESHOLD = 1 << 15; -export function scoreItem(item: T, query: string, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache): IItemScore { - if (!item || !query) { +export interface IPreparedQuery { + value: string; + lowercase: string; + containsPathSeparator: boolean; +} + +/** + * Helper function to prepare a search value for scoring in quick open by removing unwanted characters. + */ +export function prepareQuery(value: string): IPreparedQuery { + let lowercase: string; + let containsPathSeparator: boolean; + + if (value) { + value = stripWildcards(value).replace(/\s/g, ''); // get rid of all wildcards and whitespace + if (isWindows) { + value = value.replace(/\//g, '\\'); // Help Windows users to search for paths when using slash + } + + lowercase = value.toLowerCase(); + containsPathSeparator = value.indexOf(nativeSep) >= 0; + } + + return { value, lowercase, containsPathSeparator }; +} + +export function scoreItem(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache): IItemScore { + if (!item || !query.value) { return NO_ITEM_SCORE; // we need an item and query to score on at least } @@ -250,9 +275,9 @@ export function scoreItem(item: T, query: string, fuzzy: boolean, accessor: I let cacheHash: string; if (description) { - cacheHash = `${label}${description}${query}${fuzzy}`; + cacheHash = `${label}${description}${query.value}${fuzzy}`; } else { - cacheHash = `${label}${query}${fuzzy}`; + cacheHash = `${label}${query.value}${fuzzy}`; } const cached = cache[cacheHash]; @@ -266,31 +291,31 @@ export function scoreItem(item: T, query: string, fuzzy: boolean, accessor: I return itemScore; } -function doScoreItem(label: string, description: string, path: string, query: string, fuzzy: boolean): IItemScore { +function doScoreItem(label: string, description: string, path: string, query: IPreparedQuery, fuzzy: boolean): IItemScore { // 1.) treat identity matches on full path highest - if (path && isEqual(query, path, true)) { + if (path && isEqual(query.value, path, true)) { return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : void 0 }; } // We only consider label matches if the query is not including file path separators - const preferLabelMatches = !path || query.indexOf(nativeSep) === -1; + const preferLabelMatches = !path || !query.containsPathSeparator; if (preferLabelMatches) { // 2.) treat prefix matches on the label second highest - const prefixLabelMatch = matchesPrefix(query, label); + const prefixLabelMatch = matchesPrefix(query.value, label); if (prefixLabelMatch) { return { score: LABEL_PREFIX_SCORE, labelMatch: prefixLabelMatch }; } // 3.) treat camelcase matches on the label third highest - const camelcaseLabelMatch = matchesCamelCase(query, label); + const camelcaseLabelMatch = matchesCamelCase(query.value, label); if (camelcaseLabelMatch) { return { score: LABEL_CAMELCASE_SCORE, labelMatch: camelcaseLabelMatch }; } // 4.) prefer scores on the label if any - const [labelScore, labelPositions] = _doScore(label, query, fuzzy); + const [labelScore, labelPositions] = _doScore(label, query.value, query.lowercase, fuzzy); if (labelScore) { return { score: labelScore + LABEL_SCORE_THRESHOLD, labelMatch: createMatches(labelPositions) }; } @@ -306,7 +331,7 @@ function doScoreItem(label: string, description: string, path: string, query: const descriptionPrefixLength = descriptionPrefix.length; const descriptionAndLabel = `${descriptionPrefix}${label}`; - const [labelDescriptionScore, labelDescriptionPositions] = _doScore(descriptionAndLabel, query, fuzzy); + const [labelDescriptionScore, labelDescriptionPositions] = _doScore(descriptionAndLabel, query.value, query.lowercase, fuzzy); if (labelDescriptionScore) { const labelDescriptionMatches = createMatches(labelDescriptionPositions); const labelMatch: IMatch[] = []; @@ -339,7 +364,7 @@ function doScoreItem(label: string, description: string, path: string, query: return NO_ITEM_SCORE; } -export function compareItemsByScore(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache, fallbackComparer = fallbackCompare): number { +export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache, fallbackComparer = fallbackCompare): number { const itemScoreA = scoreItem(itemA, query, fuzzy, accessor, cache); const itemScoreB = scoreItem(itemB, query, fuzzy, accessor, cache); @@ -482,7 +507,7 @@ function compareByMatchLength(matchesA?: IMatch[], matchesB?: IMatch[]): number return matchLengthA === matchLengthB ? 0 : matchLengthB < matchLengthA ? 1 : -1; } -export function fallbackCompare(itemA: T, itemB: T, query: string, accessor: IItemAccessor): number { +export function fallbackCompare(itemA: T, itemB: T, query: IPreparedQuery, accessor: IItemAccessor): number { // check for label + description length and prefer shorter const labelA = accessor.getItemLabel(itemA); @@ -510,33 +535,19 @@ export function fallbackCompare(itemA: T, itemB: T, query: string, accessor: // compare by label if (labelA !== labelB) { - return compareAnything(labelA, labelB, query); + return compareAnything(labelA, labelB, query.value); } // compare by description if (descriptionA && descriptionB && descriptionA !== descriptionB) { - return compareAnything(descriptionA, descriptionB, query); + return compareAnything(descriptionA, descriptionB, query.value); } // compare by path if (pathA && pathB && pathA !== pathB) { - return compareAnything(pathA, pathB, query); + return compareAnything(pathA, pathB, query.value); } // equal return 0; -} - -/** - * Helper function to prepare a search value for scoring in quick open by removing unwanted characters. - */ -export function massageSearchForScoring(searchValue: string): string { - if (searchValue) { - searchValue = stripWildcards(searchValue).replace(/\s/g, ''); // get rid of all wildcards and whitespace - if (isWindows) { - searchValue = searchValue.replace(/\//g, '\\'); // Help Windows users to search for paths when using slash - } - } - - return searchValue; } \ No newline at end of file diff --git a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts index 8aedf7ce3ea..877f8a0caa0 100644 --- a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts +++ b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import * as scorer from 'vs/base/parts/quickopen/common/quickOpenScorer'; import URI from 'vs/base/common/uri'; -import { basename, dirname } from 'vs/base/common/paths'; +import { basename, dirname, nativeSep } from 'vs/base/common/paths'; import { isWindows } from 'vs/base/common/platform'; class ResourceAccessorClass implements scorer.IItemAccessor { @@ -43,28 +43,44 @@ class NullAccessorClass implements scorer.IItemAccessor { } } +function _doScore(target: string, query: string, fuzzy: boolean): scorer.Score { + return scorer._doScore(target, query, query.toLowerCase(), fuzzy); +} + +function scoreItem(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache): scorer.IItemScore { + return scorer.scoreItem(item, scorer.prepareQuery(query), fuzzy, accessor, cache); +} + +function compareItemsByScore(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache, fallbackComparer = scorer.fallbackCompare): number { + return scorer.compareItemsByScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, cache, fallbackComparer); +} + const NullAccessor = new NullAccessorClass(); -const cache: scorer.ScorerCache = Object.create(null); +let cache: scorer.ScorerCache = Object.create(null); suite('Quick Open Scorer', () => { + setup(() => { + cache = Object.create(null); + }); + test('score (fuzzy)', function () { const target = 'HeLlo-World'; const scores: scorer.Score[] = []; - scores.push(scorer._doScore(target, 'HelLo-World', true)); // direct case match - scores.push(scorer._doScore(target, 'hello-world', true)); // direct mix-case match - scores.push(scorer._doScore(target, 'HW', true)); // direct case prefix (multiple) - scores.push(scorer._doScore(target, 'hw', true)); // direct mix-case prefix (multiple) - scores.push(scorer._doScore(target, 'H', true)); // direct case prefix - scores.push(scorer._doScore(target, 'h', true)); // direct mix-case prefix - scores.push(scorer._doScore(target, 'ld', true)); // in-string mix-case match (consecutive, avoids scattered hit) - scores.push(scorer._doScore(target, 'W', true)); // direct case word prefix - scores.push(scorer._doScore(target, 'w', true)); // direct mix-case word prefix - scores.push(scorer._doScore(target, 'Ld', true)); // in-string case match (multiple) - scores.push(scorer._doScore(target, 'L', true)); // in-string case match - scores.push(scorer._doScore(target, 'l', true)); // in-string mix-case match - scores.push(scorer._doScore(target, '4', true)); // no match + scores.push(_doScore(target, 'HelLo-World', true)); // direct case match + scores.push(_doScore(target, 'hello-world', true)); // direct mix-case match + scores.push(_doScore(target, 'HW', true)); // direct case prefix (multiple) + scores.push(_doScore(target, 'hw', true)); // direct mix-case prefix (multiple) + scores.push(_doScore(target, 'H', true)); // direct case prefix + scores.push(_doScore(target, 'h', true)); // direct mix-case prefix + scores.push(_doScore(target, 'ld', true)); // in-string mix-case match (consecutive, avoids scattered hit) + scores.push(_doScore(target, 'W', true)); // direct case word prefix + scores.push(_doScore(target, 'w', true)); // direct mix-case word prefix + scores.push(_doScore(target, 'Ld', true)); // in-string case match (multiple) + scores.push(_doScore(target, 'L', true)); // in-string case match + scores.push(_doScore(target, 'l', true)); // in-string mix-case match + scores.push(_doScore(target, '4', true)); // no match // Assert scoring order let sortedScores = scores.concat().sort((a, b) => b[0] - a[0]); @@ -83,28 +99,28 @@ suite('Quick Open Scorer', () => { test('score (non fuzzy)', function () { const target = 'HeLlo-World'; - assert.ok(scorer._doScore(target, 'HelLo-World', false)[0] > 0); - assert.equal(scorer._doScore(target, 'HelLo-World', false)[1].length, 'HelLo-World'.length); + assert.ok(_doScore(target, 'HelLo-World', false)[0] > 0); + assert.equal(_doScore(target, 'HelLo-World', false)[1].length, 'HelLo-World'.length); - assert.ok(scorer._doScore(target, 'hello-world', false)[0] > 0); - assert.equal(scorer._doScore(target, 'HW', false)[0], 0); - assert.ok(scorer._doScore(target, 'h', false)[0] > 0); - assert.ok(scorer._doScore(target, 'ello', false)[0] > 0); - assert.ok(scorer._doScore(target, 'ld', false)[0] > 0); - assert.equal(scorer._doScore(target, 'eo', false)[0], 0); + assert.ok(_doScore(target, 'hello-world', false)[0] > 0); + assert.equal(_doScore(target, 'HW', false)[0], 0); + assert.ok(_doScore(target, 'h', false)[0] > 0); + assert.ok(_doScore(target, 'ello', false)[0] > 0); + assert.ok(_doScore(target, 'ld', false)[0] > 0); + assert.equal(_doScore(target, 'eo', false)[0], 0); }); test('scoreItem - matches are proper', function () { - let res = scorer.scoreItem(null, 'something', true, ResourceAccessor, cache); + let res = scoreItem(null, 'something', true, ResourceAccessor, cache); assert.ok(!res.score); const resource = URI.file('/xyz/some/path/someFile123.txt'); - res = scorer.scoreItem(resource, 'something', true, NullAccessor, cache); + res = scoreItem(resource, 'something', true, NullAccessor, cache); assert.ok(!res.score); // Path Identity - const identityRes = scorer.scoreItem(resource, ResourceAccessor.getItemPath(resource), true, ResourceAccessor, cache); + const identityRes = scoreItem(resource, ResourceAccessor.getItemPath(resource), true, ResourceAccessor, cache); assert.ok(identityRes.score); assert.equal(identityRes.descriptionMatch.length, 1); assert.equal(identityRes.labelMatch.length, 1); @@ -114,7 +130,7 @@ suite('Quick Open Scorer', () => { assert.equal(identityRes.labelMatch[0].end, ResourceAccessor.getItemLabel(resource).length); // Basename Prefix - const basenamePrefixRes = scorer.scoreItem(resource, 'som', true, ResourceAccessor, cache); + const basenamePrefixRes = scoreItem(resource, 'som', true, ResourceAccessor, cache); assert.ok(basenamePrefixRes.score); assert.ok(!basenamePrefixRes.descriptionMatch); assert.equal(basenamePrefixRes.labelMatch.length, 1); @@ -122,7 +138,7 @@ suite('Quick Open Scorer', () => { assert.equal(basenamePrefixRes.labelMatch[0].end, 'som'.length); // Basename Camelcase - const basenameCamelcaseRes = scorer.scoreItem(resource, 'sF', true, ResourceAccessor, cache); + const basenameCamelcaseRes = scoreItem(resource, 'sF', true, ResourceAccessor, cache); assert.ok(basenameCamelcaseRes.score); assert.ok(!basenameCamelcaseRes.descriptionMatch); assert.equal(basenameCamelcaseRes.labelMatch.length, 2); @@ -132,7 +148,7 @@ suite('Quick Open Scorer', () => { assert.equal(basenameCamelcaseRes.labelMatch[1].end, 5); // Basename Match - const basenameRes = scorer.scoreItem(resource, 'of', true, ResourceAccessor, cache); + const basenameRes = scoreItem(resource, 'of', true, ResourceAccessor, cache); assert.ok(basenameRes.score); assert.ok(!basenameRes.descriptionMatch); assert.equal(basenameRes.labelMatch.length, 2); @@ -142,7 +158,7 @@ suite('Quick Open Scorer', () => { assert.equal(basenameRes.labelMatch[1].end, 5); // Path Match - const pathRes = scorer.scoreItem(resource, 'xyz123', true, ResourceAccessor, cache); + const pathRes = scoreItem(resource, 'xyz123', true, ResourceAccessor, cache); assert.ok(pathRes.score); assert.ok(pathRes.descriptionMatch); assert.ok(pathRes.labelMatch); @@ -154,7 +170,7 @@ suite('Quick Open Scorer', () => { assert.equal(pathRes.descriptionMatch[0].end, 4); // No Match - const noRes = scorer.scoreItem(resource, '987', true, ResourceAccessor, cache); + const noRes = scoreItem(resource, '987', true, ResourceAccessor, cache); assert.ok(!noRes.score); assert.ok(!noRes.labelMatch); assert.ok(!noRes.descriptionMatch); @@ -168,10 +184,10 @@ suite('Quick Open Scorer', () => { test('scoreItem - invalid input', function () { - let res = scorer.scoreItem(null, null, true, ResourceAccessor, cache); + let res = scoreItem(null, null, true, ResourceAccessor, cache); assert.equal(res.score, 0); - res = scorer.scoreItem(null, 'null', true, ResourceAccessor, cache); + res = scoreItem(null, 'null', true, ResourceAccessor, cache); assert.equal(res.score, 0); }); @@ -181,7 +197,7 @@ suite('Quick Open Scorer', () => { // xsp is more relevant to the end of the file path even though it matches // fuzzy also in the beginning. we verify the more relevant match at the // end gets returned. - const pathRes = scorer.scoreItem(resource, 'xspfile123', true, ResourceAccessor, cache); + const pathRes = scoreItem(resource, 'xspfile123', true, ResourceAccessor, cache); assert.ok(pathRes.score); assert.ok(pathRes.descriptionMatch); assert.ok(pathRes.labelMatch); @@ -198,7 +214,7 @@ suite('Quick Open Scorer', () => { // expect "ad" to be matched towards the end of the file because the // match is more compact - const res = scorer.scoreItem(resource, 'ad', true, ResourceAccessor, cache); + const res = scoreItem(resource, 'ad', true, ResourceAccessor, cache); assert.ok(res.score); assert.ok(res.descriptionMatch); assert.ok(!res.labelMatch.length); @@ -217,12 +233,12 @@ suite('Quick Open Scorer', () => { // Full resource A path let query = ResourceAccessor.getItemPath(resourceA); - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -230,12 +246,12 @@ suite('Quick Open Scorer', () => { // Full resource B path query = ResourceAccessor.getItemPath(resourceB); - res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); @@ -249,12 +265,12 @@ suite('Quick Open Scorer', () => { // Full resource A basename let query = ResourceAccessor.getItemLabel(resourceA); - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -262,12 +278,12 @@ suite('Quick Open Scorer', () => { // Full resource B basename query = ResourceAccessor.getItemLabel(resourceB); - res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); @@ -281,12 +297,12 @@ suite('Quick Open Scorer', () => { // resource A camelcase let query = 'fA'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -294,12 +310,12 @@ suite('Quick Open Scorer', () => { // resource B camelcase query = 'fB'; - res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); @@ -313,12 +329,12 @@ suite('Quick Open Scorer', () => { // Resource A part of basename let query = 'fileA'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -326,12 +342,12 @@ suite('Quick Open Scorer', () => { // Resource B part of basename query = 'fileB'; - res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); @@ -345,12 +361,12 @@ suite('Quick Open Scorer', () => { // Resource A part of path let query = 'pathfileA'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -358,12 +374,12 @@ suite('Quick Open Scorer', () => { // Resource B part of path query = 'pathfileB'; - res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); @@ -377,12 +393,12 @@ suite('Quick Open Scorer', () => { // Resource A part of path let query = 'somepath'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -396,12 +412,12 @@ suite('Quick Open Scorer', () => { // Resource A part of path let query = 'file'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceC); assert.equal(res[2], resourceB); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceC); assert.equal(res[2], resourceB); @@ -415,12 +431,12 @@ suite('Quick Open Scorer', () => { // Resource A part of path let query = 'somepath'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); - res = [resourceC, resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); assert.equal(res[2], resourceC); @@ -433,7 +449,7 @@ suite('Quick Open Scorer', () => { let query = 'co/te'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); assert.equal(res[2], resourceC); @@ -445,11 +461,11 @@ suite('Quick Open Scorer', () => { let query = 'vscode'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => -1)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => -1)); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); - res = [resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => -1)); + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => -1)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); @@ -460,11 +476,11 @@ suite('Quick Open Scorer', () => { let query = 'AH'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); - res = [resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); @@ -475,11 +491,11 @@ suite('Quick Open Scorer', () => { let query = 'xp'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); - res = [resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); @@ -490,11 +506,11 @@ suite('Quick Open Scorer', () => { let query = 'xp'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); - res = [resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); @@ -505,11 +521,11 @@ suite('Quick Open Scorer', () => { let query = 'exfile'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); - res = [resourceB, resourceA].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); @@ -522,12 +538,12 @@ suite('Quick Open Scorer', () => { let query = isWindows ? 'modu1\\index.js' : 'modu1/index.js'; - let res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceC); query = isWindows ? 'un1\\index.js' : 'un1/index.js'; - res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); }); @@ -538,7 +554,7 @@ suite('Quick Open Scorer', () => { let query = 'StatVideoindex'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceC); }); @@ -549,7 +565,7 @@ suite('Quick Open Scorer', () => { let query = 'bookpageIndex'; - let res = [resourceA, resourceB, resourceC].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceC); }); @@ -559,7 +575,7 @@ suite('Quick Open Scorer', () => { let query = isWindows ? 'ui\\icons' : 'ui/icons'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); }); @@ -569,7 +585,7 @@ suite('Quick Open Scorer', () => { let query = isWindows ? 'ui\\input\\index' : 'ui/input/index'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); }); @@ -579,12 +595,15 @@ suite('Quick Open Scorer', () => { let query = 'listview'; - let res = [resourceA, resourceB].sort((r1, r2) => scorer.compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); }); - test('massageSearchForScoring', function () { - assert.equal(scorer.massageSearchForScoring(' f*a '), 'fa'); - assert.equal(scorer.massageSearchForScoring('model tester.ts'), 'modeltester.ts'); + test('prepareSearchForScoring', function () { + assert.equal(scorer.prepareQuery(' f*a ').value, 'fa'); + assert.equal(scorer.prepareQuery('model Tester.ts').value, 'modelTester.ts'); + assert.equal(scorer.prepareQuery('Model Tester.ts').lowercase, 'modeltester.ts'); + assert.equal(scorer.prepareQuery('ModelTester.ts').containsPathSeparator, false); + assert.equal(scorer.prepareQuery('Model' + nativeSep + 'Tester.ts').containsPathSeparator, true); }); }); \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/editorPicker.ts b/src/vs/workbench/browser/parts/editor/editorPicker.ts index f7c63fa7e08..fe160365da8 100644 --- a/src/vs/workbench/browser/parts/editor/editorPicker.ts +++ b/src/vs/workbench/browser/parts/editor/editorPicker.ts @@ -22,7 +22,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { EditorInput, toResource, IEditorGroup, IEditorStacksModel } from 'vs/workbench/common/editor'; -import { compareItemsByScore, scoreItem, ScorerCache, massageSearchForScoring } from 'vs/base/parts/quickopen/common/quickOpenScorer'; +import { compareItemsByScore, scoreItem, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; export class EditorPickerEntry extends QuickOpenEntryGroup { private stacks: IEditorStacksModel; @@ -106,15 +106,15 @@ export abstract class BaseEditorPicker extends QuickOpenHandler { return TPromise.as(null); } - // Massage search for scoring - searchValue = massageSearchForScoring(searchValue); + // Prepare search for scoring + const query = prepareQuery(searchValue); const entries = editorEntries.filter(e => { - if (!searchValue) { + if (!query.value) { return true; } - const itemScore = scoreItem(e, searchValue, true, QuickOpenItemAccessor, this.scorerCache); + const itemScore = scoreItem(e, query, true, QuickOpenItemAccessor, this.scorerCache); if (!itemScore.score) { return false; } @@ -126,13 +126,13 @@ export abstract class BaseEditorPicker extends QuickOpenHandler { // Sorting const stacks = this.editorGroupService.getStacksModel(); - if (searchValue) { + if (query.value) { entries.sort((e1, e2) => { if (e1.group !== e2.group) { return stacks.positionOfGroup(e1.group) - stacks.positionOfGroup(e2.group); } - return compareItemsByScore(e1, e2, searchValue, true, QuickOpenItemAccessor, this.scorerCache); + return compareItemsByScore(e1, e2, query, true, QuickOpenItemAccessor, this.scorerCache); }); } diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 2f178d70c51..08681245fcd 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -55,7 +55,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree'; import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { FileKind, IFileService } from 'vs/platform/files/common/files'; -import { scoreItem, ScorerCache, compareItemsByScore, massageSearchForScoring } from 'vs/base/parts/quickopen/common/quickOpenScorer'; +import { scoreItem, ScorerCache, compareItemsByScore, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; const HELP_PREFIX = '?'; @@ -1181,17 +1181,17 @@ class EditorHistoryHandler { public getResults(searchValue?: string): QuickOpenEntry[] { // Massage search for scoring - searchValue = massageSearchForScoring(searchValue); + const query = prepareQuery(searchValue); // Just return all if we are not searching const history = this.historyService.getHistory(); - if (!searchValue) { + if (!query.value) { return history.map(input => this.instantiationService.createInstance(EditorHistoryEntry, input)); } // Otherwise filter by search value and sort by score. Include matches on description // in case the user is explicitly including path separators. - const accessor = searchValue.indexOf(paths.nativeSep) >= 0 ? MatchOnDescription : DoNotMatchOnDescription; + const accessor = query.containsPathSeparator ? MatchOnDescription : DoNotMatchOnDescription; return history // For now, only support to match on inputs that provide resource information @@ -1211,7 +1211,7 @@ class EditorHistoryHandler { // Make sure the search value is matching .filter(e => { - const itemScore = scoreItem(e, searchValue, false, accessor, this.scorerCache); + const itemScore = scoreItem(e, query, false, accessor, this.scorerCache); if (!itemScore.score) { return false; } @@ -1223,7 +1223,7 @@ class EditorHistoryHandler { // Sort by score and provide a fallback sorter that keeps the // recency of items in case the score for items is the same - .sort((e1, e2) => compareItemsByScore(e1, e2, searchValue, false, accessor, this.scorerCache, (e1, e2, searchValue, accessor) => -1)); + .sort((e1, e2) => compareItemsByScore(e1, e2, query, false, accessor, this.scorerCache, (e1, e2, query, accessor) => -1)); } } diff --git a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts index 69c76344f67..16acf16b142 100644 --- a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts +++ b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts @@ -23,7 +23,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchSearchConfiguration } from 'vs/workbench/parts/search/common/search'; import { IRange } from 'vs/editor/common/core/range'; -import { compareItemsByScore, scoreItem, ScorerCache, massageSearchForScoring } from 'vs/base/parts/quickopen/common/quickOpenScorer'; +import { compareItemsByScore, scoreItem, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; export import OpenSymbolHandler = openSymbolHandler.OpenSymbolHandler; // OpenSymbolHandler is used from an extension and must be in the main bundle file so it can load @@ -173,15 +173,16 @@ export class OpenAnythingHandler extends QuickOpenHandler { this.cancelPendingSearch(); this.isClosed = false; // Treat this call as the handler being in use - // Massage search for scoring - searchValue = massageSearchForScoring(searchValue); + // Prepare search for scoring + const query = prepareQuery(searchValue); - const searchWithRange = this.extractRange(searchValue); // Find a suitable range from the pattern looking for ":" and "#" + const searchWithRange = this.extractRange(query.value); // Find a suitable range from the pattern looking for ":" and "#" if (searchWithRange) { - searchValue = searchWithRange.search; // ignore range portion in query + query.value = searchWithRange.search; // ignore range portion in query + query.lowercase = query.value.toLowerCase(); } - if (!searchValue) { + if (!query.value) { return TPromise.as(new QuickOpenModel()); // Respond directly to empty search } @@ -190,12 +191,12 @@ export class OpenAnythingHandler extends QuickOpenHandler { const resultPromises: TPromise[] = []; // File Results - const filePromise = this.openFileHandler.getResults(searchValue, OpenAnythingHandler.MAX_DISPLAYED_RESULTS); + const filePromise = this.openFileHandler.getResults(query.value, OpenAnythingHandler.MAX_DISPLAYED_RESULTS); resultPromises.push(filePromise); // Symbol Results (unless disabled or a range or absolute path is specified) if (this.includeSymbols && !searchWithRange) { - resultPromises.push(this.openSymbolHandler.getResults(searchValue)); + resultPromises.push(this.openSymbolHandler.getResults(query.value)); } // Join and sort unified @@ -212,7 +213,7 @@ export class OpenAnythingHandler extends QuickOpenHandler { // Sort const unsortedResultTime = Date.now(); - const compare = (elementA: QuickOpenEntry, elementB: QuickOpenEntry) => compareItemsByScore(elementA, elementB, searchValue, true, QuickOpenItemAccessor, this.scorerCache); + const compare = (elementA: QuickOpenEntry, elementB: QuickOpenEntry) => compareItemsByScore(elementA, elementB, query, true, QuickOpenItemAccessor, this.scorerCache); const viewResults = arrays.top(mergedResults, compare, OpenAnythingHandler.MAX_DISPLAYED_RESULTS); const sortedResultTime = Date.now(); @@ -221,7 +222,7 @@ export class OpenAnythingHandler extends QuickOpenHandler { if (entry instanceof FileEntry) { entry.setRange(searchWithRange ? searchWithRange.range : null); - const itemScore = scoreItem(entry, searchValue, true, QuickOpenItemAccessor, this.scorerCache); + const itemScore = scoreItem(entry, query, true, QuickOpenItemAccessor, this.scorerCache); entry.setHighlights(itemScore.labelMatch, itemScore.descriptionMatch); } }); @@ -229,7 +230,7 @@ export class OpenAnythingHandler extends QuickOpenHandler { const duration = new Date().getTime() - startTime; filePromise.then(fileModel => { const data = this.createTimerEventData(startTime, { - searchLength: searchValue.length, + searchLength: query.value.length, unsortedResultTime, sortedResultTime, resultCount: mergedResults.length, diff --git a/src/vs/workbench/services/search/node/rawSearchService.ts b/src/vs/workbench/services/search/node/rawSearchService.ts index 12c6c6e0381..55fb059c48f 100644 --- a/src/vs/workbench/services/search/node/rawSearchService.ts +++ b/src/vs/workbench/services/search/node/rawSearchService.ts @@ -23,7 +23,7 @@ import { TextSearchWorkerProvider } from 'vs/workbench/services/search/node/text import { IRawSearchService, IRawSearch, IRawFileMatch, ISerializedFileMatch, ISerializedSearchProgressItem, ISerializedSearchComplete, ISearchEngine, IFileSearchProgressItem, ITelemetryEvent } from './search'; import { ICachedSearchStats, IProgress } from 'vs/platform/search/common/search'; import { fuzzyContains } from 'vs/base/common/strings'; -import { compareItemsByScore, IItemAccessor, ScorerCache } from 'vs/base/parts/quickopen/common/quickOpenScorer'; +import { compareItemsByScore, IItemAccessor, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; export class SearchService implements IRawSearchService { @@ -254,7 +254,8 @@ export class SearchService implements IRawSearchService { // this is very important because we are also limiting the number of results by config.maxResults // and as such we want the top items to be included in this result set if the number of items // exceeds config.maxResults. - const compare = (matchA: IRawFileMatch, matchB: IRawFileMatch) => compareItemsByScore(matchA, matchB, strings.stripWildcards(config.filePattern), true, FileMatchItemAccessor, scorerCache); + const query = prepareQuery(config.filePattern); + const compare = (matchA: IRawFileMatch, matchB: IRawFileMatch) => compareItemsByScore(matchA, matchB, query, true, FileMatchItemAccessor, scorerCache); return arrays.topAsync(results, compare, config.maxResults, 10000); } From 183035fb52a924557ef13502dc0777d062025c49 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 11:55:48 +0200 Subject: [PATCH 124/394] Fix compilation issues --- src/vs/workbench/parts/files/browser/fileActions.ts | 2 +- src/vs/workbench/parts/files/browser/views/explorerViewer.ts | 2 +- .../parts/preferences/common/preferencesContribution.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index 6975b962704..5204850eaee 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -714,7 +714,7 @@ export class BaseDeleteFileAction extends BaseFileAction { let confirmPromise: TPromise; // Check if we need to ask for confirmation at all - if (this.skipConfirm || (this.useTrash && this.configurationService.lookup(BaseDeleteFileAction.CONFIRM_DELETE_SETTING_KEY).value === false)) { + if (this.skipConfirm || (this.useTrash && this.configurationService.getValue(BaseDeleteFileAction.CONFIRM_DELETE_SETTING_KEY) === false)) { confirmPromise = TPromise.as({ confirmed: true } as IConfirmationResult); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 01b9954702b..4878cedef0b 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -949,7 +949,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { let confirmPromise: TPromise; // Handle confirm setting - const confirmDragAndDrop = !isCopy && this.configurationService.lookup(FileDragAndDrop.CONFIRM_DND_SETTING_KEY).value; + const confirmDragAndDrop = !isCopy && this.configurationService.getValue(FileDragAndDrop.CONFIRM_DND_SETTING_KEY); if (confirmDragAndDrop) { confirmPromise = this.messageService.confirm({ message: nls.localize('confirmMove', "Are you sure you want to move '{0}'?", source.name), diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index 48e0ef167d2..2f91e713b0d 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -50,7 +50,7 @@ export class PreferencesContribution implements IWorkbenchContribution { this.editorOpeningListener = dispose(this.editorOpeningListener); // install editor opening listener unless user has disabled this - if (!!this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value) { + if (!!this.configurationService.getValue(DEFAULT_SETTINGS_EDITOR_SETTING)) { this.editorOpeningListener = this.editorGroupService.onEditorOpening(e => this.onEditorOpening(e)); } } @@ -60,7 +60,7 @@ export class PreferencesContribution implements IWorkbenchContribution { if ( !resource || resource.scheme !== 'file' || // require a file path opening !endsWith(resource.fsPath, 'settings.json') || // file must end in settings.json - !this.configurationService.lookup(DEFAULT_SETTINGS_EDITOR_SETTING).value // user has not disabled default settings editor + !this.configurationService.getValue(DEFAULT_SETTINGS_EDITOR_SETTING) // user has not disabled default settings editor ) { return; } From 3f1ffd14c8cafde90de8fb165954527932e1dadd Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 11:57:22 +0200 Subject: [PATCH 125/394] Reload after editing --- .../configuration/node/configurationEditingService.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index b264dbd9662..d13b326bfc2 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -94,7 +94,9 @@ export class ConfigurationEditingService implements IConfigurationEditingService private writeToBuffer(model: editorCommon.IModel, operation: IConfigurationEditOperation, save: boolean): TPromise { const edit = this.getEdits(model, operation)[0]; if (this.applyEditsToBuffer(edit, model) && save) { - return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }); + return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }) + // Reload the configuration so that we make sure all parties are updated + .then(() => this.configurationService.reloadConfiguration()); } return TPromise.as(null); } From 907de42b3e7c52dc7c34d0785b1f00c74da43fe9 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 12:33:14 +0200 Subject: [PATCH 126/394] Fix tests --- src/vs/platform/configuration/common/configuration.ts | 7 +++++++ .../configuration/node/configurationService.ts | 10 +--------- .../test/common/testConfigurationService.ts | 5 +++-- .../configuration/node/configurationService.ts | 7 ++++--- .../test/node/configurationService.test.ts | 4 ++-- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 5cbe7665027..4ad222fdb0b 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -15,6 +15,13 @@ import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/co export const IConfigurationService = createDecorator('configurationService'); +export function isConfigurationOverrides(thing: any): thing is IConfigurationOverrides { + return thing + && typeof thing === 'object' + && (!thing.overrideIdentifier || typeof thing.overrideIdentifier === 'string') + && (!thing.resource || thing.resource instanceof URI); +} + export interface IConfigurationOverrides { overrideIdentifier?: string; resource?: URI; diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 035060db7de..19f78c792ab 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -8,23 +8,15 @@ import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare, isConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { CustomConfigurationModel, DefaultConfigurationModel, ConfigurationModel, Configuration, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import Event, { Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { onUnexpectedError } from 'vs/base/common/errors'; -import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { equals } from 'vs/base/common/objects'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -export function isConfigurationOverrides(thing: any): thing is IConfigurationOverrides { - return thing - && typeof thing === 'object' - && (!thing.overrideIdentifier || typeof thing.overrideIdentifier === 'string') - && (!thing.resource || thing.resource instanceof URI); -} - export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable { _serviceBrand: any; diff --git a/src/vs/platform/configuration/test/common/testConfigurationService.ts b/src/vs/platform/configuration/test/common/testConfigurationService.ts index 2410406e261..6e0a81519b3 100644 --- a/src/vs/platform/configuration/test/common/testConfigurationService.ts +++ b/src/vs/platform/configuration/test/common/testConfigurationService.ts @@ -9,7 +9,7 @@ import { TernarySearchTree } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { EventEmitter } from 'vs/base/common/eventEmitter'; -import { getConfigurationKeys, IConfigurationOverrides, IConfigurationService, getConfigurationValue } from 'vs/platform/configuration/common/configuration'; +import { getConfigurationKeys, IConfigurationOverrides, IConfigurationService, getConfigurationValue, isConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; export class TestConfigurationService extends EventEmitter implements IConfigurationService { public _serviceBrand: any; @@ -22,7 +22,8 @@ export class TestConfigurationService extends EventEmitter implements IConfigura return TPromise.as(this.getConfiguration()); } - public getConfiguration(section?: any, overrides?: any): C { + public getConfiguration(arg1?: any, arg2?: any): C { + const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; if (overrides && overrides.resource) { const configForResource = this.configurationByRoot.findSubstr(overrides.resource.fsPath); return configForResource || this.configuration; diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index f2ed3e415dc..b4902fe2e8e 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -24,10 +24,10 @@ import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { CustomConfigurationModel, ConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; -import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; -import { ConfigurationService as GlobalConfigurationService, isConfigurationOverrides } from 'vs/platform/configuration/node/configurationService'; +import { ConfigurationService as GlobalConfigurationService } from 'vs/platform/configuration/node/configurationService'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationNode, IConfigurationRegistry, Extensions, ConfigurationScope, settingsSchema, resourceSettingsSchema } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; @@ -160,7 +160,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat if (folder) { return this.reloadWorkspaceFolderConfiguration(folder, key); } - return this.loadConfiguration(); + return this.reloadUserConfiguration() + .then(() => this.loadConfiguration()); } inspect(key: string, overrides?: IConfigurationOverrides): { diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index bef7e75099f..5c6763edb10 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -178,7 +178,7 @@ suite('WorkspaceConfigurationService - Node', () => { return createService(workspaceDir, globalSettingsFile).then(service => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); - service.reloadConfiguration(service.getWorkspace().folders[0]).then(() => { + service.reloadConfiguration().then(() => { const config = service.getConfiguration<{ testworkbench: { editor: { tabs: boolean } } }>(); assert.equal(config.testworkbench.editor.tabs, true); @@ -263,7 +263,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.icons": false, "testworkbench.other.setting": true }'); fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); - service.reloadWorkspaceConfiguration().then(() => { + service.reloadConfiguration().then(() => { const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean }, other: { setting: string } } }>(); assert.equal(config.testworkbench.editor.icons, true); assert.equal(config.testworkbench.other.setting, true); From a71c987a4dd40fb5d05adcb9226747c30f613f2a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 Oct 2017 12:38:16 +0200 Subject: [PATCH 127/394] fix #35582 --- .../browser/goToDeclarationCommands.ts | 2 +- .../browser => message}/messageController.css | 0 .../browser => message}/messageController.ts | 6 +++++- .../preferences/browser/preferencesEditor.ts | 15 ++++++++++++++- .../preferences/browser/preferencesRenderers.ts | 2 +- 5 files changed, 21 insertions(+), 4 deletions(-) rename src/vs/editor/contrib/{goToDeclaration/browser => message}/messageController.css (100%) rename src/vs/editor/contrib/{goToDeclaration/browser => message}/messageController.ts (98%) diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands.ts index 0cede0a44db..5db1dae02f9 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands.ts @@ -22,7 +22,7 @@ import { ReferencesController } from 'vs/editor/contrib/referenceSearch/browser/ import { ReferencesModel } from 'vs/editor/contrib/referenceSearch/browser/referencesModel'; import { PeekContext } from 'vs/editor/contrib/referenceSearch/browser/peekViewWidget'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { MessageController } from './messageController'; +import { MessageController } from 'vs/editor/contrib/message/messageController'; import * as corePosition from 'vs/editor/common/core/position'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IProgressService } from 'vs/platform/progress/common/progress'; diff --git a/src/vs/editor/contrib/goToDeclaration/browser/messageController.css b/src/vs/editor/contrib/message/messageController.css similarity index 100% rename from src/vs/editor/contrib/goToDeclaration/browser/messageController.css rename to src/vs/editor/contrib/message/messageController.css diff --git a/src/vs/editor/contrib/goToDeclaration/browser/messageController.ts b/src/vs/editor/contrib/message/messageController.ts similarity index 98% rename from src/vs/editor/contrib/goToDeclaration/browser/messageController.ts rename to src/vs/editor/contrib/message/messageController.ts index 693722e4c52..ce5d45af58c 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/messageController.ts +++ b/src/vs/editor/contrib/message/messageController.ts @@ -47,10 +47,14 @@ export class MessageController { this._visible = MessageController.CONTEXT_SNIPPET_MODE.bindTo(contextKeyService); } - dispose() { + dispose(): void { this._visible.reset(); } + isVisible() { + return this._visible.get(); + } + showMessage(message: string, position: IPosition): void { alert(message); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 411b295653f..b65862ab507 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -58,6 +58,7 @@ import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; +import { MessageController } from 'vs/editor/contrib/message/messageController'; export class PreferencesEditorInput extends SideBySideEditorInput { public static ID: string = 'workbench.editorinputs.preferencesEditorInput'; @@ -722,7 +723,19 @@ export class DefaultPreferencesEditor extends BaseTextEditor { } public createEditorControl(parent: Builder, configuration: IEditorOptions): editorCommon.IEditor { - return this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent.getHTMLElement(), configuration); + const editor = this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent.getHTMLElement(), configuration); + + // Inform user about editor being readonly if user starts type + this.toUnbind.push(editor.onDidType(() => this.onDidType(editor))); + + return editor; + } + + private onDidType(editor: editorCommon.ICommonCodeEditor): void { + const messageController = MessageController.get(editor); + if (!messageController.isVisible()) { + messageController.showMessage(nls.localize('defaultEditorReadonly', "Edit in the right hand side editor to override defaults."), editor.getSelection().getPosition()); + } } protected getConfigurationOverrides(): IEditorOptions { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index d74dd56da46..94d5d61e4b9 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -413,7 +413,7 @@ class DefaultSettingsHeaderRenderer extends Disposable { public render(settingsGroups: ISettingsGroup[]) { if (settingsGroups.length) { - this.settingsHeaderWidget.setMessage(''); + this.settingsHeaderWidget.setMessage(nls.localize('defaultSettings', "Place your settings in the right hand side editor to override.")); } else { this.settingsHeaderWidget.setMessage(nls.localize('noSettingsFound', "No Settings Found.")); } From 65a2d30efe65b508577e3a8ecfeca8b07036c10a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 12:39:20 +0200 Subject: [PATCH 128/394] color - jsdoc and tiny tweaks for color provider api --- extensions/css/client/src/cssMain.ts | 6 +-- extensions/html/client/src/htmlMain.ts | 8 ++-- extensions/json/client/src/jsonMain.ts | 8 ++-- src/vs/vscode.d.ts | 2 + src/vs/vscode.proposed.d.ts | 43 ++++++++++++++++++- .../api/node/extHostLanguageFeatures.ts | 21 +++------ 6 files changed, 61 insertions(+), 27 deletions(-) diff --git a/extensions/css/client/src/cssMain.ts b/extensions/css/client/src/cssMain.ts index 6b43c68252f..e86425b2d81 100644 --- a/extensions/css/client/src/cssMain.ts +++ b/extensions/css/client/src/cssMain.ts @@ -66,10 +66,10 @@ export function activate(context: ExtensionContext) { }); }); }, - provideColorPresentations(document: TextDocument, colorInfo: ColorInformation): ColorPresentation[] | Thenable { + provideColorPresentations(color: Color, context): ColorPresentation[] | Thenable { let params: ColorPresentationParams = { - textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), - colorInfo: { range: client.code2ProtocolConverter.asRange(colorInfo.range), color: colorInfo.color } + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(context.document), + colorInfo: { range: client.code2ProtocolConverter.asRange(context.range), color } }; return client.sendRequest(ColorPresentationRequest.type, params).then(presentations => { return presentations.map(p => { diff --git a/extensions/html/client/src/htmlMain.ts b/extensions/html/client/src/htmlMain.ts index 2dc9899c125..4f355644a04 100644 --- a/extensions/html/client/src/htmlMain.ts +++ b/extensions/html/client/src/htmlMain.ts @@ -83,10 +83,10 @@ export function activate(context: ExtensionContext) { }); }); }, - provideColorPresentations(document: TextDocument, colorInfo: ColorInformation): Thenable { + provideColorPresentations(color, context): Thenable { let params: ColorPresentationParams = { - textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), - colorInfo: { range: client.code2ProtocolConverter.asRange(colorInfo.range), color: colorInfo.color } + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(context.document), + colorInfo: { range: client.code2ProtocolConverter.asRange(context.range), color } }; return client.sendRequest(ColorPresentationRequest.type, params).then(presentations => { return presentations.map(p => { @@ -175,4 +175,4 @@ function getPackageInfo(context: ExtensionContext): IPackageInfo { }; } return null; -} \ No newline at end of file +} diff --git a/extensions/json/client/src/jsonMain.ts b/extensions/json/client/src/jsonMain.ts index 1498820c33d..2509a46e385 100644 --- a/extensions/json/client/src/jsonMain.ts +++ b/extensions/json/client/src/jsonMain.ts @@ -145,10 +145,10 @@ export function activate(context: ExtensionContext) { }); }); }, - provideColorPresentations(document: TextDocument, colorInfo: ColorInformation): Thenable { + provideColorPresentations(color: Color, context): Thenable { let params: ColorPresentationParams = { - textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), - colorInfo: { range: client.code2ProtocolConverter.asRange(colorInfo.range), color: colorInfo.color } + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(context.document), + colorInfo: { range: client.code2ProtocolConverter.asRange(context.range), color } }; return client.sendRequest(ColorPresentationRequest.type, params).then(presentations => { return presentations.map(p => { @@ -288,4 +288,4 @@ function getPackageInfo(context: ExtensionContext): IPackageInfo { }; } return null; -} \ No newline at end of file +} diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 4c7756fbfcb..68b3d1b5d45 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2996,6 +2996,8 @@ declare module 'vscode' { resolveDocumentLink?(link: DocumentLink, token: CancellationToken): ProviderResult; } + + /** * A tuple of two characters, like a pair of * opening and closing brackets. diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index fd6f8cf68e3..ee6b4bbc923 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -194,6 +194,14 @@ declare module 'vscode' { */ readonly alpha: number; + /** + * Creates a new color instance. + * + * @param red The red component. + * @param green The green component. + * @param blue The bluew component. + * @param alpha The alpha component. + */ constructor(red: number, green: number, blue: number, alpha: number); } @@ -222,19 +230,30 @@ declare module 'vscode' { constructor(range: Range, color: Color); } + /** + * A color presentation object describes how a [`color`](#Color) should be represented as text and what + * edits are required to refer to it from source code. + * + * For some languages one color can have multiple presentations, e.g. css can represent the color red with + * the constant `Red`, the hex-value `#ff0000`, or in rgba and hsla forms. In csharp other representations + * apply, e.g `System.Drawing.Color.Red`. + */ export class ColorPresentation { + /** * The label of this color presentation. It will be shown on the color * picker header. By default this is also the text that is inserted when selecting * this color presentation. */ label: string; + /** * An [edit](#TextEdit) which is applied to a document when selecting * this presentation for the color. When `falsy` the [label](#ColorPresentation.label) * is used. */ textEdit?: TextEdit; + /** * An optional array of additional [text edits](#TextEdit) that are applied when * selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. @@ -254,6 +273,7 @@ declare module 'vscode' { * picking and modifying colors in the editor. */ export interface DocumentColorProvider { + /** * Provide colors for the given document. * @@ -263,13 +283,32 @@ declare module 'vscode' { * can be signaled by returning `undefined`, `null`, or an empty array. */ provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult; + /** - * Provide representations for a color. + * Provide [representations](#ColorPresentation) for a color. + * + * @param color The color to show and insert. + * @param context A context object with additional information + * @param token A cancellation token. + * @return An array of color presentations or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. */ - provideColorPresentations(document: TextDocument, colorInfo: ColorInformation, token: CancellationToken): ProviderResult; + provideColorPresentations(color: Color, context: { document: TextDocument, range: Range }, token: CancellationToken): ProviderResult; } export namespace languages { + + /** + * Register a color provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A color provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ export function registerColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable; } } diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 4a6a22e86f0..7718b667dd4 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { mixin } from 'vs/base/common/objects'; import * as vscode from 'vscode'; import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters'; -import { Range, Disposable, CompletionList, SnippetString } from 'vs/workbench/api/node/extHostTypes'; +import { Range, Disposable, CompletionList, SnippetString, Color } from 'vs/workbench/api/node/extHostTypes'; import { ISingleEditOperation } from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService'; @@ -721,19 +721,12 @@ class ColorProviderAdapter { }); } - provideColorPresentations(resource: URI, rawColorInfo: IRawColorInfo): TPromise { - let colorInfo: vscode.ColorInformation = { - range: TypeConverters.toRange(rawColorInfo.range), - color: { - red: rawColorInfo.color[0], - green: rawColorInfo.color[1], - blue: rawColorInfo.color[2], - alpha: rawColorInfo.color[3] - } - }; - const doc = this._documents.getDocumentData(resource).document; - return asWinJsPromise(token => this._provider.provideColorPresentations(doc, colorInfo, token)).then(value => { - return value.map(v => TypeConverters.ColorPresentation.from(v)); + provideColorPresentations(resource: URI, raw: IRawColorInfo): TPromise { + const document = this._documents.getDocumentData(resource).document; + const range = TypeConverters.toRange(raw.range); + const color = new Color(raw.color[0], raw.color[1], raw.color[2], raw.color[3]); + return asWinJsPromise(token => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => { + return value.map(TypeConverters.ColorPresentation.from); }); } } From 46b7697866e6eb87bebcfcc8f42107d24d672d37 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 12:42:54 +0200 Subject: [PATCH 129/394] color - move color provider api to stable api --- src/vs/vscode.d.ts | 138 +++++++++++++++++ src/vs/vscode.proposed.d.ts | 143 ------------------ src/vs/workbench/api/node/extHost.api.impl.ts | 9 +- 3 files changed, 142 insertions(+), 148 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 68b3d1b5d45..891b0b2289f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2996,7 +2996,132 @@ declare module 'vscode' { resolveDocumentLink?(link: DocumentLink, token: CancellationToken): ProviderResult; } + /** + * Represents a color in RGBA space. + */ + export class Color { + /** + * The red component of this color in the range [0-1]. + */ + readonly red: number; + + /** + * The green component of this color in the range [0-1]. + */ + readonly green: number; + + /** + * The blue component of this color in the range [0-1]. + */ + readonly blue: number; + + /** + * The alpha component of this color in the range [0-1]. + */ + readonly alpha: number; + + /** + * Creates a new color instance. + * + * @param red The red component. + * @param green The green component. + * @param blue The bluew component. + * @param alpha The alpha component. + */ + constructor(red: number, green: number, blue: number, alpha: number); + } + + /** + * Represents a color range from a document. + */ + export class ColorInformation { + + /** + * The range in the document where this color appers. + */ + range: Range; + + /** + * The actual color value for this color range. + */ + color: Color; + + /** + * Creates a new color range. + * + * @param range The range the color appears in. Must not be empty. + * @param color The value of the color. + * @param format The format in which this color is currently formatted. + */ + constructor(range: Range, color: Color); + } + + /** + * A color presentation object describes how a [`color`](#Color) should be represented as text and what + * edits are required to refer to it from source code. + * + * For some languages one color can have multiple presentations, e.g. css can represent the color red with + * the constant `Red`, the hex-value `#ff0000`, or in rgba and hsla forms. In csharp other representations + * apply, e.g `System.Drawing.Color.Red`. + */ + export class ColorPresentation { + + /** + * The label of this color presentation. It will be shown on the color + * picker header. By default this is also the text that is inserted when selecting + * this color presentation. + */ + label: string; + + /** + * An [edit](#TextEdit) which is applied to a document when selecting + * this presentation for the color. When `falsy` the [label](#ColorPresentation.label) + * is used. + */ + textEdit?: TextEdit; + + /** + * An optional array of additional [text edits](#TextEdit) that are applied when + * selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. + */ + additionalTextEdits?: TextEdit[]; + + /** + * Creates a new color presentation. + * + * @param label The label of this color presentation. + */ + constructor(label: string); + } + + /** + * The document color provider defines the contract between extensions and feature of + * picking and modifying colors in the editor. + */ + export interface DocumentColorProvider { + + /** + * Provide colors for the given document. + * + * @param document The document in which the command was invoked. + * @param token A cancellation token. + * @return An array of [color informations](#ColorInformation) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult; + + /** + * Provide [representations](#ColorPresentation) for a color. + * + * @param color The color to show and insert. + * @param context A context object with additional information + * @param token A cancellation token. + * @return An array of color presentations or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideColorPresentations(color: Color, context: { document: TextDocument, range: Range }, token: CancellationToken): ProviderResult; + } /** * A tuple of two characters, like a pair of @@ -5587,6 +5712,19 @@ declare module 'vscode' { */ export function registerDocumentLinkProvider(selector: DocumentSelector, provider: DocumentLinkProvider): Disposable; + /** + * Register a color provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A color provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable; + /** * Set a [language configuration](#LanguageConfiguration) for a language. * diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index ee6b4bbc923..0c5dba2a3e5 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -168,147 +168,4 @@ declare module 'vscode' { */ export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable; } - - /** - * Represents a color in RGBA space. - */ - export class Color { - - /** - * The red component of this color in the range [0-1]. - */ - readonly red: number; - - /** - * The green component of this color in the range [0-1]. - */ - readonly green: number; - - /** - * The blue component of this color in the range [0-1]. - */ - readonly blue: number; - - /** - * The alpha component of this color in the range [0-1]. - */ - readonly alpha: number; - - /** - * Creates a new color instance. - * - * @param red The red component. - * @param green The green component. - * @param blue The bluew component. - * @param alpha The alpha component. - */ - constructor(red: number, green: number, blue: number, alpha: number); - } - - /** - * Represents a color range from a document. - */ - export class ColorInformation { - - /** - * The range in the document where this color appers. - */ - range: Range; - - /** - * The actual color value for this color range. - */ - color: Color; - - /** - * Creates a new color range. - * - * @param range The range the color appears in. Must not be empty. - * @param color The value of the color. - * @param format The format in which this color is currently formatted. - */ - constructor(range: Range, color: Color); - } - - /** - * A color presentation object describes how a [`color`](#Color) should be represented as text and what - * edits are required to refer to it from source code. - * - * For some languages one color can have multiple presentations, e.g. css can represent the color red with - * the constant `Red`, the hex-value `#ff0000`, or in rgba and hsla forms. In csharp other representations - * apply, e.g `System.Drawing.Color.Red`. - */ - export class ColorPresentation { - - /** - * The label of this color presentation. It will be shown on the color - * picker header. By default this is also the text that is inserted when selecting - * this color presentation. - */ - label: string; - - /** - * An [edit](#TextEdit) which is applied to a document when selecting - * this presentation for the color. When `falsy` the [label](#ColorPresentation.label) - * is used. - */ - textEdit?: TextEdit; - - /** - * An optional array of additional [text edits](#TextEdit) that are applied when - * selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. - */ - additionalTextEdits?: TextEdit[]; - - /** - * Creates a new color presentation. - * - * @param label The label of this color presentation. - */ - constructor(label: string); - } - - /** - * The document color provider defines the contract between extensions and feature of - * picking and modifying colors in the editor. - */ - export interface DocumentColorProvider { - - /** - * Provide colors for the given document. - * - * @param document The document in which the command was invoked. - * @param token A cancellation token. - * @return An array of [color informations](#ColorInformation) or a thenable that resolves to such. The lack of a result - * can be signaled by returning `undefined`, `null`, or an empty array. - */ - provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult; - - /** - * Provide [representations](#ColorPresentation) for a color. - * - * @param color The color to show and insert. - * @param context A context object with additional information - * @param token A cancellation token. - * @return An array of color presentations or a thenable that resolves to such. The lack of a result - * can be signaled by returning `undefined`, `null`, or an empty array. - */ - provideColorPresentations(color: Color, context: { document: TextDocument, range: Range }, token: CancellationToken): ProviderResult; - } - - export namespace languages { - - /** - * Register a color provider. - * - * Multiple providers can be registered for a language. In that case providers are asked in - * parallel and the results are merged. A failing provider (rejected promise or exception) will - * not cause a failure of the whole operation. - * - * @param selector A selector that defines the documents this provider is applicable to. - * @param provider A color provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable; - } } diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 0df38e8773f..32af7291dfc 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -269,13 +269,12 @@ export function createApiFactory( registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { return languageFeatures.registerDocumentLinkProvider(selector, provider); }, + registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable { + return languageFeatures.registerColorProvider(selector, provider); + }, setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => { return languageFeatures.setLanguageConfiguration(language, configuration); - }, - // proposed API - registerColorProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider) => { - return languageFeatures.registerColorProvider(selector, provider); - }) + } }; // namespace: window From 37043bc9d28647e8dd40551e715e0aae9640cb9c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 14:46:40 +0200 Subject: [PATCH 130/394] deco - tooltip -> title --- src/vs/workbench/browser/labels.ts | 2 +- .../parts/markers/browser/markersFileDecorations.ts | 2 +- .../parts/scm/electron-browser/scmFileDecorations.ts | 2 +- .../workbench/services/decorations/browser/decorations.ts | 4 ++-- .../services/decorations/browser/decorationsService.ts | 6 +++--- .../decorations/test/browser/decorationsService.test.ts | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 08a68da883c..ec6920eed22 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -192,7 +192,7 @@ export class ResourceLabel extends IconLabel { } if (deco && deco.badgeClassName && this.options.fileDecorations.badges) { iconLabelOptions.badge = { - title: deco.tooltip, + title: deco.title, className: deco.badgeClassName, }; } diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts index 670e1db47da..e9a44a611ac 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts @@ -44,7 +44,7 @@ class MarkersDecorationsProvider implements IDecorationsProvider { return { weight: 100 * first.severity, - tooltip: markers.length === 1 ? localize('tooltip.1', "1 problem in this file") : localize('tooltip.N', "{0} problems in this file", markers.length), + title: markers.length === 1 ? localize('tooltip.1', "1 problem in this file") : localize('tooltip.N', "{0} problems in this file", markers.length), letter: markers.length.toString(), color: first.severity === Severity.Error ? editorErrorForeground : editorWarningForeground, }; diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index ebfd9f55cd9..75fcbab94b8 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -67,7 +67,7 @@ class SCMDecorationsProvider implements IDecorationsProvider { } return { weight: 100 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0), - tooltip: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label), + title: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label), color: resource.decorations.color, letter: resource.decorations.tooltip.charAt(0) }; diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 1c42c362433..25401fd795a 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -17,13 +17,13 @@ export interface IDecorationData { readonly color?: ColorIdentifier; readonly opacity?: number; readonly letter?: string; - readonly tooltip?: string; + readonly title?: string; } export interface IDecoration { readonly _decoBrand: undefined; readonly weight?: number; - readonly tooltip?: string; + readonly title?: string; readonly labelClassName?: string; readonly badgeClassName?: string; } diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index feb0ff47fe3..9792da756f4 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -93,10 +93,10 @@ class ResourceDecoration implements IDecoration { let result = new ResourceDecoration(data); if (Array.isArray(data)) { result.weight = data[0].weight; - result.tooltip = data.map(d => d.tooltip).join(', '); + result.title = data.map(d => d.title).join(', '); } else { result.weight = data.weight; - result.tooltip = data.tooltip; + result.title = data.title; } return result; } @@ -105,7 +105,7 @@ class ResourceDecoration implements IDecoration { _data: IDecorationData | IDecorationData[]; weight?: number; - tooltip?: string; + title?: string; labelClassName?: string; badgeClassName?: string; diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index 8135a7eceac..54f37ccf294 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -36,7 +36,7 @@ suite('DecorationsService', function () { return new Promise(resolve => { setTimeout(() => resolve({ color: 'someBlue', - tooltip: 'T' + title: 'T' })); }); } @@ -51,7 +51,7 @@ suite('DecorationsService', function () { assert.equal(e.affectsResource(uri), true); // sync result - assert.deepEqual(service.getDecoration(uri, false).tooltip, 'T'); + assert.deepEqual(service.getDecoration(uri, false).title, 'T'); assert.equal(callCounter, 1); }); }); @@ -71,7 +71,7 @@ suite('DecorationsService', function () { }); // trigger -> sync - assert.deepEqual(service.getDecoration(uri, false).tooltip, 'Z'); + assert.deepEqual(service.getDecoration(uri, false).title, 'Z'); assert.equal(callCounter, 1); }); @@ -89,7 +89,7 @@ suite('DecorationsService', function () { }); // trigger -> sync - assert.deepEqual(service.getDecoration(uri, false).tooltip, 'J'); + assert.deepEqual(service.getDecoration(uri, false).title, 'J'); assert.equal(callCounter, 1); // un-register -> ensure good event From 9cdb5bb4806c7f1e7971247a4eaf071819b8fd1f Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 Oct 2017 14:54:49 +0200 Subject: [PATCH 131/394] debug: enable / disable all breakpoints should not touch exception breakpoints fixes #36349 --- src/vs/workbench/parts/debug/common/debugModel.ts | 1 - .../parts/debug/electron-browser/debugViewer.ts | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 2859af8fc30..c8ef0226454 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -916,7 +916,6 @@ export class Model implements IModel { bp.verified = false; } }); - this.exceptionBreakpoints.forEach(ebp => ebp.enabled = enable); this.functionBreakpoints.forEach(fbp => fbp.enabled = enable); this._onDidChangeBreakpoints.fire(); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index d8104fbc3a2..521ebfd16d0 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -1062,11 +1062,12 @@ export class BreakpointsActionProvider implements IActionProvider { } public getSecondaryActions(tree: ITree, element: any): TPromise { - const actions: IAction[] = []; - - if (element instanceof Breakpoint || element instanceof FunctionBreakpoint) { - actions.push(this.instantiationService.createInstance(RemoveBreakpointAction, RemoveBreakpointAction.ID, RemoveBreakpointAction.LABEL)); + if (element instanceof ExceptionBreakpoint) { + return TPromise.as([]); } + + const actions: IAction[] = []; + actions.push(this.instantiationService.createInstance(RemoveBreakpointAction, RemoveBreakpointAction.ID, RemoveBreakpointAction.LABEL)); if (this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getFunctionBreakpoints().length > 1) { actions.push(this.instantiationService.createInstance(RemoveAllBreakpointsAction, RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL)); actions.push(new Separator()); From 10a0e425693dfdc949441aeccf50f0c0178f2565 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 Oct 2017 15:26:00 +0200 Subject: [PATCH 132/394] bump node debug version --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 9f7088b945e..e424881eaab 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -45,7 +45,7 @@ const nodeModules = ['electron', 'original-fs'] // Build const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.17.18' }, + { name: 'ms-vscode.node-debug', version: '1.18.1' }, { name: 'ms-vscode.node-debug2', version: '1.18.1' } ]; From 9a9c8c7afb7753fdf71bee9193718448ea8c8179 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 15:30:30 +0200 Subject: [PATCH 133/394] show message when no formatter is installed, #36303 --- .../editor/common/editorCommonExtensions.ts | 3 ++- .../contrib/format/browser/formatActions.ts | 19 ++++++++++++++++--- src/vs/editor/contrib/format/common/format.ts | 15 +++++++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/editorCommonExtensions.ts b/src/vs/editor/common/editorCommonExtensions.ts index fee9cdfbd3a..aaea4371983 100644 --- a/src/vs/editor/common/editorCommonExtensions.ts +++ b/src/vs/editor/common/editorCommonExtensions.ts @@ -153,6 +153,7 @@ export abstract class EditorCommand extends Command { export interface IEditorCommandMenuOptions { group?: string; order?: number; + when?: ContextKeyExpr; } export interface IActionOptions extends ICommandOptions { label: string; @@ -182,7 +183,7 @@ export abstract class EditorAction extends EditorCommand { id: this.id, title: this.label }, - when: this.precondition, + when: ContextKeyExpr.and(this.precondition, this.menuOpts.when), group: this.menuOpts.group, order: this.menuOpts.order }; diff --git a/src/vs/editor/contrib/format/browser/formatActions.ts b/src/vs/editor/contrib/format/browser/formatActions.ts index de620bc090b..62cd203a97b 100644 --- a/src/vs/editor/contrib/format/browser/formatActions.ts +++ b/src/vs/editor/contrib/format/browser/formatActions.ts @@ -13,7 +13,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { editorAction, ServicesAccessor, EditorAction, commonEditorContribution } from 'vs/editor/common/editorCommonExtensions'; import { OnTypeFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry } from 'vs/editor/common/modes'; -import { getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits } from '../common/format'; +import { getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits, NoProviderError } from '../common/format'; import { EditOperationsCommand } from '../common/formatCommand'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'; @@ -23,6 +23,7 @@ import { Range } from 'vs/editor/common/core/range'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { EditorState, CodeEditorStateFlag } from 'vs/editor/common/core/editorState'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { IMessageService, Severity } from 'vs/platform/message/common/message'; function alertFormattingEdits(edits: editorCommon.ISingleEditOperation[]): void { @@ -263,6 +264,7 @@ export abstract class AbstractFormatAction extends EditorAction { public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): TPromise { const workerService = accessor.get(IEditorWorkerService); + const messageService = accessor.get(IMessageService); const formattingPromise = this._getFormattingEdits(editor); if (!formattingPromise) { @@ -281,6 +283,15 @@ export abstract class AbstractFormatAction extends EditorAction { EditOperationsCommand.execute(editor, edits); alertFormattingEdits(edits); editor.focus(); + }, err => { + if (err instanceof Error && err.name === NoProviderError.Name) { + messageService.show( + Severity.Info, + nls.localize('no.provider', "Sorry, but there is no formatter for '{0}'-files installed.", editor.getModel().getLanguageIdentifier().language), + ); + } else { + throw err; + } }); } @@ -296,7 +307,7 @@ export class FormatDocumentAction extends AbstractFormatAction { id: 'editor.action.formatDocument', label: nls.localize('formatDocument.label', "Format Document"), alias: 'Format Document', - precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider), + precondition: EditorContextKeys.writable, kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_F, @@ -304,6 +315,7 @@ export class FormatDocumentAction extends AbstractFormatAction { linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I } }, menuOpts: { + when: EditorContextKeys.hasDocumentFormattingProvider, group: '1_modification', order: 1.3 } @@ -325,12 +337,13 @@ export class FormatSelectionAction extends AbstractFormatAction { id: 'editor.action.formatSelection', label: nls.localize('formatSelection.label', "Format Selection"), alias: 'Format Code', - precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentSelectionFormattingProvider, EditorContextKeys.hasNonEmptySelection), + precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasNonEmptySelection), kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_F) }, menuOpts: { + when: ContextKeyExpr.and(EditorContextKeys.hasDocumentSelectionFormattingProvider, EditorContextKeys.hasNonEmptySelection), group: '1_modification', order: 1.31 } diff --git a/src/vs/editor/contrib/format/common/format.ts b/src/vs/editor/contrib/format/common/format.ts index 0f8bb567719..37c0f0246fd 100644 --- a/src/vs/editor/contrib/format/common/format.ts +++ b/src/vs/editor/contrib/format/common/format.ts @@ -17,12 +17,23 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { asWinJsPromise, sequence } from 'vs/base/common/async'; import { Position } from 'vs/editor/common/core/position'; -export function getDocumentRangeFormattingEdits(model: IReadOnlyModel, range: Range, options: FormattingOptions): TPromise { +export class NoProviderError extends Error { + + static readonly Name = 'NOPRO'; + + constructor(message?: string) { + super(); + this.name = NoProviderError.Name; + this.message = message; + } +} + +export function getDocumentRangeFormattingEdits(model: IReadOnlyModel, range: Range, options: FormattingOptions): TPromise { const providers = DocumentRangeFormattingEditProviderRegistry.ordered(model); if (providers.length === 0) { - return TPromise.as(undefined); + return TPromise.wrapError(new NoProviderError()); } let result: TextEdit[]; From abff32ca6c1daf1e2b9bf02b9fff3f309b26e25d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 15:38:33 +0200 Subject: [PATCH 134/394] deco - tweak config listening --- .../electron-browser/scmFileDecorations.ts | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index 75fcbab94b8..02616fb2a13 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -13,7 +13,6 @@ import URI from 'vs/base/common/uri'; import Event, { Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; -import { equals } from 'vs/base/common/objects'; class SCMDecorationsProvider implements IDecorationsProvider { @@ -85,14 +84,13 @@ export class FileDecorations implements IWorkbenchContribution { private _providers = new Map(); private _configListener: IDisposable; private _repoListeners: IDisposable[]; - private _currentConfig: ISCMConfiguration; constructor( @IDecorationsService private _decorationsService: IDecorationsService, @IConfigurationService private _configurationService: IConfigurationService, @ISCMService private _scmService: ISCMService, ) { - this._configListener = this._configurationService.onDidUpdateConfiguration(this._update, this); + this._configListener = this._configurationService.onDidUpdateConfiguration(e => e.affectsConfiguration('scm.fileDecorations.enabled') && this._update()); this._update(); } @@ -108,20 +106,16 @@ export class FileDecorations implements IWorkbenchContribution { private _update(): void { const config = this._configurationService.getConfiguration('scm'); - if (!equals(config, this._currentConfig)) { - this._currentConfig = config; - - if (this._currentConfig.fileDecorations.enabled) { - this._scmService.repositories.forEach(this._onDidAddRepository, this); - this._repoListeners = [ - this._scmService.onDidAddRepository(this._onDidAddRepository, this), - this._scmService.onDidRemoveRepository(this._onDidRemoveRepository, this) - ]; - } else { - this._repoListeners = dispose(this._repoListeners); - this._providers.forEach(value => dispose(value)); - this._providers.clear(); - } + if (config.fileDecorations.enabled) { + this._scmService.repositories.forEach(this._onDidAddRepository, this); + this._repoListeners = [ + this._scmService.onDidAddRepository(this._onDidAddRepository, this), + this._scmService.onDidRemoveRepository(this._onDidRemoveRepository, this) + ]; + } else { + this._repoListeners = dispose(this._repoListeners); + this._providers.forEach(value => dispose(value)); + this._providers.clear(); } } From 5276a4fcc85370a7131fd0a2d5a0e8d357ff9287 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 15:47:19 +0200 Subject: [PATCH 135/394] deco - proper explorer update on config change --- .../parts/files/browser/views/explorerView.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index ca642768b2b..f522ebcea6d 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -33,7 +33,7 @@ import { IListService } from 'vs/platform/list/browser/listService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IProgressService } from 'vs/platform/progress/common/progress'; @@ -204,7 +204,7 @@ export class ExplorerView extends ViewsViewletPanel { this.disposables.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); // Also handle configuration updates - this.disposables.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), true))); + this.disposables.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), e))); }); } @@ -251,7 +251,7 @@ export class ExplorerView extends ViewsViewletPanel { } } - private onConfigurationUpdated(configuration: IFilesConfiguration, refresh?: boolean): void { + private onConfigurationUpdated(configuration: IFilesConfiguration, event?: IConfigurationChangeEvent): void { if (this.isDisposed) { return; // guard against possible race condition when config change causes recreate of views } @@ -270,8 +270,13 @@ export class ExplorerView extends ViewsViewletPanel { needsRefresh = true; } + if (event && !needsRefresh) { + needsRefresh = event.affectsConfiguration('explorer.decorations.colors') + || event.affectsConfiguration('explorer.decorations.badges'); + } + // Refresh viewer as needed - if (refresh && needsRefresh) { + if (needsRefresh) { this.doRefresh().done(null, errors.onUnexpectedError); } } From f704a6c7101f998a24690b8678c199ca96952921 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 Oct 2017 16:01:05 +0200 Subject: [PATCH 136/394] composite part: move pin / unpin / mode to compositePart --- .../parts/activitybar/activitybarActions.ts | 2 +- .../parts/activitybar/activitybarPart.ts | 60 ++----------- .../parts/compositebar/compositeBar.ts | 86 +++++++++++++------ 3 files changed, 70 insertions(+), 78 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index b20d15c85cb..20c50332d10 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -62,7 +62,7 @@ export class ViewletActivityAction extends ActivityAction { } } -export class OpenViewletAction extends Action { +export class ToggleViewletAction extends Action { constructor( private _viewlet: ViewletDescriptor, diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 857847afc19..c8c4dbafb07 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -15,7 +15,7 @@ import { ActionsOrientation, ActionBar, Separator } from 'vs/base/browser/ui/act import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity'; import { Registry } from 'vs/platform/registry/common/platform'; import { Part } from 'vs/workbench/browser/part'; -import { ToggleViewletPinnedAction, GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, OpenViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { ToggleViewletPinnedAction, GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, ToggleViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IActivityBarService, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; import { IPartService, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService'; @@ -64,9 +64,12 @@ export class ActivitybarPart extends Part implements IActivityBarService { orientation: ActionsOrientation.VERTICAL, composites: this.viewletService.getViewlets(), getCompositeSize: (compositeId: string) => ActivitybarPart.ACTIVITY_ACTION_HEIGHT, + openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true), getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)), getCompositePinnedAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletPinnedAction, this.viewletService.getViewlet(compositeId)), - getOpenCompositeAction: (compositeId: string) => this.instantiationService.createInstance(OpenViewletAction, this.viewletService.getViewlet(compositeId)) + getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), + getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), + hidePart: () => this.partService.setSideBarHidden(true) }); this.registerListeners(); } @@ -78,7 +81,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Deactivate viewlet action on close this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId()))); - this.toUnbind.push(this.compositeBar.onDidDropComposite(data => this.move(data.compositeId, data.toCompositeId))); this.toUnbind.push(this.compositeBar.onDidContextMenu(e => this.showContextMenu(e))); } @@ -176,44 +178,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } public unpin(viewletId: string): void { - if (!this.compositeBar.isPinned(viewletId)) { - return; - } - - const activeViewlet = this.viewletService.getActiveViewlet(); - const defaultViewletId = this.viewletService.getDefaultViewletId(); - const visibleViewlets = this.compositeBar.getVisibleComposites(); - - let unpinPromise: TPromise; - - // Case: viewlet is not the active one or the active one is a different one - // Solv: we do nothing - if (!activeViewlet || activeViewlet.getId() !== viewletId) { - unpinPromise = TPromise.as(null); - } - - // Case: viewlet is not the default viewlet and default viewlet is still showing - // Solv: we open the default viewlet - else if (defaultViewletId !== viewletId && this.compositeBar.isPinned(defaultViewletId)) { - unpinPromise = this.viewletService.openViewlet(defaultViewletId, true); - } - - // Case: we closed the last visible viewlet - // Solv: we hide the sidebar - else if (visibleViewlets.length === 1) { - unpinPromise = this.partService.setSideBarHidden(true); - } - - // Case: we closed the default viewlet - // Solv: we open the next visible viewlet from top - else { - unpinPromise = this.viewletService.openViewlet(visibleViewlets.filter(viewletId => viewletId !== viewletId)[0], true); - } - - unpinPromise.then(() => { - // then remove from pinned and update switcher - this.compositeBar.unpin(viewletId); - }); + this.compositeBar.unpin(viewletId); } public isPinned(viewletId: string): boolean { @@ -221,21 +186,10 @@ export class ActivitybarPart extends Part implements IActivityBarService { } public pin(viewletId: string, update = true): void { - if (this.isPinned(viewletId)) { - return; - } - - // first open that viewlet - this.viewletService.openViewlet(viewletId, true) - .then(() => this.compositeBar.pin(viewletId, update)); + this.compositeBar.pin(viewletId, update); } public move(viewletId: string, toViewletId: string): void { - // Make sure a moved viewlet gets pinned - if (!this.isPinned(viewletId)) { - this.pin(viewletId, false /* defer update, we take care of it */); - } - this.compositeBar.move(viewletId, toViewletId); } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 18b83e8938e..fac2c91cf0c 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -12,15 +12,13 @@ import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; import { Dimension } from 'vs/base/browser/builder'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IBadge } from 'vs/workbench/services/activity/common/activityBarService'; -import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import Event, { Emitter } from 'vs/base/common/event'; import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { TPromise } from 'vs/base/common/winjs.base'; export interface ICompositeBarOptions { label: 'icon' | 'name'; @@ -29,14 +27,16 @@ export interface ICompositeBarOptions { composites: { id: string, name: string }[]; getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; - getOpenCompositeAction: (compositeId: string) => Action; + getOnCompositeClickAction: (compositeId: string) => Action; + openComposite: (compositeId: string) => TPromise; + getDefaultCompositeId: () => string; getCompositeSize: (compositeId: string) => number; + hidePart: () => TPromise; } export class CompositeBar { private _onDidContextMenu: Emitter; - private _onDidDropComposite: Emitter<{ compositeId: string, toCompositeId: string }>; private dimension: Dimension; private toDispose: IDisposable[]; @@ -55,11 +55,8 @@ export class CompositeBar { constructor( private options: ICompositeBarOptions, - @IContextMenuService private contextMenuService: IContextMenuService, @IInstantiationService private instantiationService: IInstantiationService, @IStorageService private storageService: IStorageService, - @IPartService private partService: IPartService, - @IThemeService themeService: IThemeService, ) { this.toDispose = []; this.compositeIdToActionItems = Object.create(null); @@ -67,7 +64,6 @@ export class CompositeBar { this.compositeIdToActivityStack = Object.create(null); this._onDidContextMenu = new Emitter(); - this._onDidDropComposite = new Emitter<{ compositeId: string, toCompositeId: string }>(); const pinnedComposites = JSON.parse(this.storageService.get(this.options.storageId, StorageScope.GLOBAL, null)) as string[]; if (pinnedComposites) { @@ -81,10 +77,6 @@ export class CompositeBar { return this._onDidContextMenu.event; } - public get onDidDropComposite(): Event<{ compositeId: string, toCompositeId: string }> { - return this._onDidDropComposite.event; - } - public activateComposite(id: string): void { if (this.compositeIdToActions[id]) { this.compositeIdToActions[id].activate(); @@ -184,7 +176,7 @@ export class CompositeBar { const targetId = this.pinnedComposites[this.pinnedComposites.length - 1]; if (targetId !== draggedCompositeId) { - this._onDidDropComposite.fire({ compositeId: draggedCompositeId, toCompositeId: this.pinnedComposites[this.pinnedComposites.length - 1] }); + this.move(draggedCompositeId, this.pinnedComposites[this.pinnedComposites.length - 1]); } } })); @@ -279,7 +271,7 @@ export class CompositeBar { () => this.getOverflowingComposites(), () => this.activeCompositeId, (compositeId: string) => this.compositeIdToActivityStack[compositeId] && this.compositeIdToActivityStack[compositeId][0].badge, - this.options.getOpenCompositeAction + this.options.getOnCompositeClickAction ); this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: true, icon: true }); @@ -297,7 +289,7 @@ export class CompositeBar { return this.options.composites.filter(c => overflowingIds.indexOf(c.id) !== -1); } - public getVisibleComposites(): string[] { + private getVisibleComposites(): string[] { return Object.keys(this.compositeIdToActions); } @@ -326,10 +318,46 @@ export class CompositeBar { } public unpin(compositeId: string): void { - const index = this.pinnedComposites.indexOf(compositeId); - this.pinnedComposites.splice(index, 1); + if (!this.isPinned(compositeId)) { + return; + } - this.updateCompositeSwitcher(); + const defaultCompositeId = this.options.getDefaultCompositeId(); + const visibleComposites = this.getVisibleComposites(); + + let unpinPromise: TPromise; + + // Case: composite is not the active one or the active one is a different one + // Solv: we do nothing + if (!this.activeCompositeId || this.activeCompositeId !== compositeId) { + unpinPromise = TPromise.as(null); + } + + // Case: composite is not the default composite and default composite is still showing + // Solv: we open the default composite + else if (defaultCompositeId !== compositeId && this.isPinned(defaultCompositeId)) { + unpinPromise = this.options.openComposite(defaultCompositeId); + } + + // Case: we closed the last visible composite + // Solv: we hide the part + else if (visibleComposites.length === 1) { + unpinPromise = this.options.hidePart(); + } + + // Case: we closed the default composite + // Solv: we open the next visible composite from top + else { + unpinPromise = this.options.openComposite(visibleComposites.filter(cid => cid !== compositeId)[0]); + } + + unpinPromise.then(() => { + // then remove from pinned and update switcher + const index = this.pinnedComposites.indexOf(compositeId); + this.pinnedComposites.splice(index, 1); + + this.updateCompositeSwitcher(); + }); } public isPinned(compositeId: string): boolean { @@ -337,15 +365,25 @@ export class CompositeBar { } public pin(compositeId: string, update = true): void { - this.pinnedComposites.push(compositeId); - this.pinnedComposites = arrays.distinct(this.pinnedComposites); - - if (update) { - this.updateCompositeSwitcher(); + if (this.isPinned(compositeId)) { + return; } + + this.options.openComposite(compositeId).then(() => { + this.pinnedComposites.push(compositeId); + this.pinnedComposites = arrays.distinct(this.pinnedComposites); + + if (update) { + this.updateCompositeSwitcher(); + } + }); } public move(compositeId: string, toCompositeId: string): void { + // Make sure a moved composite gets pinned + if (!this.isPinned(compositeId)) { + this.pin(compositeId, false /* defer update, we take care of it */); + } const fromIndex = this.pinnedComposites.indexOf(compositeId); const toIndex = this.pinnedComposites.indexOf(toCompositeId); From 3170a7f5f9f1ec83d8af413841d42d8500b352be Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 16:07:40 +0200 Subject: [PATCH 137/394] Do not overload getConfiguration for sending it to extension host. Use getConfigurationData --- src/vs/platform/configuration/common/configuration.ts | 2 ++ .../configuration/node/configurationService.ts | 6 +++++- .../api/electron-browser/mainThreadConfiguration.ts | 2 +- .../configuration/node/configurationService.ts | 10 ++++++---- .../extensions/electron-browser/extensionHost.ts | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 4ad222fdb0b..5f50cf05077 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -50,6 +50,8 @@ export interface IConfigurationService { onDidUpdateConfiguration: Event; + getConfigurationData(): IConfigurationData; + getConfiguration(): T; getConfiguration(section: string): T; getConfiguration(overrides: IConfigurationOverrides): T; diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 19f78c792ab..6b1d5954fa5 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -8,7 +8,7 @@ import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare, isConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration'; import { CustomConfigurationModel, DefaultConfigurationModel, ConfigurationModel, Configuration, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import Event, { Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -52,6 +52,10 @@ export class ConfigurationService extends Disposable implements IConfigurationSe return this._configuration; } + getConfigurationData(): IConfigurationData { + return this.configuration.toData(); + } + getConfiguration(): T getConfiguration(section: string): T getConfiguration(overrides: IConfigurationOverrides): T diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 46648b2b1ae..71f54113cfd 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -29,7 +29,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); this._configurationListener = configurationService.onDidUpdateConfiguration(() => { - proxy.$acceptConfigurationChanged(configurationService.getConfiguration()); + proxy.$acceptConfigurationChanged(configurationService.getConfigurationData()); }); } diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index b4902fe2e8e..5c83bdddbbb 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -24,7 +24,7 @@ import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { CustomConfigurationModel, ConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; -import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration'; import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { ConfigurationService as GlobalConfigurationService } from 'vs/platform/configuration/node/configurationService'; @@ -128,6 +128,10 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // Workspace Configuration Service Impl + getConfigurationData(): IConfigurationData { + return this._configuration.toData(); + } + getConfiguration(): T getConfiguration(section: string): T getConfiguration(overrides: IConfigurationOverrides): T @@ -135,9 +139,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat getConfiguration(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : void 0; const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; - const contents = this._configuration.getSection(section, overrides); - return typeof contents === 'object' ? { toJSON: () => this._configuration.toData(), ...contents } - : contents; + return this._configuration.getSection(section, overrides); } getValue(key: string, overrides?: IConfigurationOverrides): T { diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 553e69ad627..d4b17a7fbc3 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -360,7 +360,7 @@ export class ExtensionHostProcessWorker { }, workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace(), extensions: extensionDescriptions, - configuration: this._configurationService.getConfiguration(), + configuration: this._configurationService.getConfigurationData(), telemetryInfo }; return r; From 8f4e125ab8204f88d782478a98e4e588f5390333 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 16:09:19 +0200 Subject: [PATCH 138/394] Fix compilation errors --- src/vs/editor/standalone/browser/simpleServices.ts | 4 ++++ .../configuration/test/common/testConfigurationService.ts | 4 ++++ .../telemetry/test/electron-browser/telemetryService.test.ts | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 4705eac59a4..abc268c123e 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -493,6 +493,10 @@ export class SimpleConfigurationService implements IConfigurationService { public reloadConfiguration(): TPromise { return TPromise.as(null); } + + public getConfigurationData() { + return null; + } } export class SimpleResourceConfigurationService implements ITextResourceConfigurationService { diff --git a/src/vs/platform/configuration/test/common/testConfigurationService.ts b/src/vs/platform/configuration/test/common/testConfigurationService.ts index 6e0a81519b3..52363535b85 100644 --- a/src/vs/platform/configuration/test/common/testConfigurationService.ts +++ b/src/vs/platform/configuration/test/common/testConfigurationService.ts @@ -82,4 +82,8 @@ export class TestConfigurationService extends EventEmitter implements IConfigura workspaceFolder: [] }; } + + public getConfigurationData() { + return null; + } } diff --git a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts index 45173045d9a..d97577a72b3 100644 --- a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts @@ -698,7 +698,8 @@ suite('TelemetryService', () => { }, keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; }, onDidUpdateConfiguration: emitter.event, - reloadConfiguration() { return null; } + reloadConfiguration() { return null; }, + getConfigurationData() { return null; } }); assert.equal(service.isOptedIn, false); From 42e1d19ab5206aca4886eb7d4d1766dc0fbff97b Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 Oct 2017 16:16:23 +0200 Subject: [PATCH 139/394] composite bar polish css classes --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 4 ++-- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index c8c4dbafb07..72b3f6e451a 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -112,10 +112,10 @@ export class ActivitybarPart extends Part implements IActivityBarService { const $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action - this.compositeBar.create($result.clone().getHTMLElement()); + this.compositeBar.create($('.viewlets').appendTo($result).getHTMLElement()); // Top Actionbar with action items for each viewlet action - this.createGlobalActivityActionBar($result.getHTMLElement()); + this.createGlobalActivityActionBar($('.global-activity').appendTo($result).getHTMLElement()); return $result; } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index fac2c91cf0c..12c90a5638a 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -153,6 +153,7 @@ export class CompositeBar { } public create(container: HTMLElement): void { + dom.addClass(container, 'composite-bar'); this.compositeSwitcherBar = new ActionBar(container, { actionItemProvider: (action: Action) => action instanceof CompositeOverflowActivityAction ? this.compositeOverflowActionItem : this.compositeIdToActionItems[action.id], orientation: this.options.orientation, From 9613370d5f8bdbf9e350946ce3284381e95b859d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 Oct 2017 16:19:23 +0200 Subject: [PATCH 140/394] update title area faster when opening a new group --- .../parts/editor/editorGroupsControl.ts | 41 ++++++++++++------- .../browser/parts/editor/editorPart.ts | 22 ++++++++-- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts index ff6acd7892e..9f8ff8ce901 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts @@ -73,6 +73,7 @@ export interface IEditorGroupsControl { getInstantiationService(position: Position): IInstantiationService; getProgressBar(position: Position): ProgressBar; updateProgress(position: Position, state: ProgressState): void; + updateTitleAreaControls(): void; layout(dimension: Dimension): void; layout(position: Position): void; @@ -321,7 +322,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro public show(editor: BaseEditor, position: Position, preserveActive: boolean, ratio?: number[]): void { const visibleEditorCount = this.getVisibleEditorCount(); - const currentActivePosition = this.getActivePosition(); // Store into editor bucket this.visibleEditors[position] = editor; @@ -392,7 +392,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.sashOne.layout(); this.layoutContainers(); - this.updateInactiveEditorGroupActions(currentActivePosition); // prevent some ugly flickering when opening a group } // Adjust layout: []|[] -> []|[]|[!] @@ -406,7 +405,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.sashTwo.layout(); this.layoutContainers(); - this.updateInactiveEditorGroupActions(currentActivePosition); // prevent some ugly flickering when opening a group } // Show editor container @@ -2065,18 +2063,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } } - private updateInactiveEditorGroupActions(position: Position): void { - const activePosition = this.getActivePosition(); - if (activePosition === position) { - return; // this position is actually active - } - - const titleArea = this.getTitleAreaControl(position); - if (titleArea) { - titleArea.updateEditorActionsToolbar(); - } - } - public getInstantiationService(position: Position): IInstantiationService { return this.getFromContainer(position, EditorGroupsControl.INSTANTIATION_SERVICE_KEY); } @@ -2089,6 +2075,31 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro return this.getFromContainer(position, EditorGroupsControl.TITLE_AREA_CONTROL_KEY); } + public updateTitleAreaControls(): void { + POSITIONS.forEach(position => { + const group = this.stacks.groupAt(position); + if (!group) { + return; + } + + const titleControl = this.getTitleAreaControl(position); + if (!titleControl) { + return; + } + + // Make sure the active group is shown in the title and refresh it + if (group.isActive) { + titleControl.setContext(group); + titleControl.refresh(true); + } + + // For inactive groups, just refresh the toolbar + else { + titleControl.updateEditorActionsToolbar(); + } + }); + } + private getFromContainer(position: Position, key: string): any { const silo = this.silos[position]; diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index e1a28c2dd1d..07f8e82161f 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -372,7 +372,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // This can however cause a race condition where the stacks model indicates the opened editor is there // while the UI is not yet ready. Clients have to deal with this fact and we have to make sure that the // stacks model gets updated if any of the UI updating fails with an error. - const group = this.ensureGroup(position, !options || !options.preserveFocus); + const [group, newGroupOpened] = this.ensureGroup(position, !options || !options.preserveFocus); const pinned = !this.tabOptions.previewEditors || (options && (options.pinned || typeof options.index === 'number')) || input.isDirty(); const active = (group.count === 0) || !options || !options.inactive; @@ -401,7 +401,19 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService } // Set input to editor - return this.doSetInput(group, editor, input, options, monitor); + const inputPromise = this.doSetInput(group, editor, input, options, monitor); + + // A new active group got opened. Since this involves updating the title area controls to show + // the new editor and actions we trigger a direct update of title controls from here to avoid + // some UI flickering if we rely on the event handlers that all use schedulers. + // The reason we can trigger this now is that after the input is set to the editor group, the + // resource context is updated and the correct number of actions will be resolved from the title + // area. + if (newGroupOpened && this.stacks.isActive(group)) { + this.editorGroupsControl.updateTitleAreaControls(); + } + + return inputPromise; } private doShowEditor(group: EditorGroup, descriptor: IEditorDescriptor, input: EditorInput, options: EditorOptions, ratio: number[], monitor: ProgressMonitor): BaseEditor { @@ -1523,9 +1535,11 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService array[from] = empty; } - private ensureGroup(position: Position, activate = true): EditorGroup { + private ensureGroup(position: Position, activate = true): [EditorGroup, boolean /* new group opened */] { + let newGroupOpened = false; let group = this.stacks.groupAt(position); if (!group) { + newGroupOpened = true; // Race condition: it could be that someone quickly opens editors one after // the other and we are asked to open an editor in position 2 before position @@ -1548,7 +1562,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.stacks.setActive(group); } - return group; + return [group, newGroupOpened]; } private modifyGroups(modification: () => void) { From 10c5d96af2a9ddfe63a1dea396e2cc8d38eca9d3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 18:04:00 +0200 Subject: [PATCH 141/394] Fix issue in IntervalTree.resolveNode --- src/vs/editor/common/model/intervalTree.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index b1e0cb4fa44..f62dfd2ba3e 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -149,6 +149,7 @@ export class IntervalTree { } public resolveNode(node: IntervalNode, cachedVersionId: number): void { + const initialNode = node; let delta = 0; while (node !== this.root) { if (node === node.parent.right) { @@ -157,9 +158,9 @@ export class IntervalTree { node = node.parent; } - const nodeStart = node.start + delta; - const nodeEnd = node.end + delta; - node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); + const nodeStart = initialNode.start + delta; + const nodeEnd = initialNode.end + delta; + initialNode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); } public assertInvariants(): void { From e7ae7d781e4460461065fa9947be67011bed6485 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 18:05:31 +0200 Subject: [PATCH 142/394] Fix issue in changeDecoration --- src/vs/editor/common/model/textModelWithDecorations.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 2b9befae2f9..5579578d5ff 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -842,7 +842,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; this._tree.delete(node); - + node.start = startOffset; + node.end = endOffset; + node.maxEnd = endOffset; node.setCachedOffsets(startOffset, endOffset, this.getVersionId()); node.range = range; this._tree.insert(node); From bfedda7b2fd07c209b8271282c1654a2a676ecdf Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 18:07:14 +0200 Subject: [PATCH 143/394] Adjust tests for USE_NEW_DECORATIONS --- .../editor/common/model/textModelWithDecorations.ts | 2 +- .../snippet/test/browser/snippetSession.test.ts | 13 +++++++++++-- .../test/common/model/modelDecorations.test.ts | 9 +++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 5579578d5ff..00d521007fa 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -19,7 +19,7 @@ import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; -const USE_NEW_DECORATIONS = false; +export const USE_NEW_DECORATIONS = false; export const ClassName = { EditorInfoDecoration: 'infosquiggly', diff --git a/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts b/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts index 2bb0c11006d..d29f6908dc9 100644 --- a/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts +++ b/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts @@ -12,6 +12,7 @@ import { SnippetSession } from 'vs/editor/contrib/snippet/browser/snippetSession import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { mockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { Model } from 'vs/editor/common/model/model'; +import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; suite('SnippetSession', function () { @@ -234,9 +235,17 @@ suite('SnippetSession', function () { assertSelections(editor, new Selection(1, 10, 1, 10), new Selection(2, 14, 2, 14)); session.prev(); - assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); + if (USE_NEW_DECORATIONS) { + assertSelections(editor, new Selection(1, 7, 1, 10), new Selection(2, 11, 2, 14)); + } else { + assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); + } session.prev(); - assertSelections(editor, new Selection(1, 4, 1, 4), new Selection(2, 8, 2, 8)); + if (USE_NEW_DECORATIONS) { + assertSelections(editor, new Selection(1, 4, 1, 7), new Selection(2, 8, 2, 11)); + } else { + assertSelections(editor, new Selection(1, 4, 1, 4), new Selection(2, 8, 2, 8)); + } session.prev(); assertSelections(editor, new Selection(1, 1, 1, 4), new Selection(2, 5, 2, 8)); }); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 1699981d0da..4d0c3bbbe95 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -10,6 +10,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; import { Model } from 'vs/editor/common/model/model'; +import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; // --------- utils @@ -1094,7 +1095,11 @@ suite('deltaDecorations', () => { assert.equal(initialIds.length, decorations.length, 'returns expected cnt of ids'); assert.equal(initialIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(initialIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); + if (!USE_NEW_DECORATIONS) { assert.equal(2 * initialIds.length, model._getMarkersCount(), 'does not leak markers'); + } else { + assert.equal(0, model._getMarkersCount(), 'does not leak markers'); + } actualDecorations.sort((a, b) => strcmp(a.id, b.id)); decorations.sort((a, b) => strcmp(a.id, b.id)); assert.deepEqual(actualDecorations, decorations); @@ -1105,7 +1110,11 @@ suite('deltaDecorations', () => { assert.equal(newIds.length, newDecorations.length, 'returns expected cnt of ids'); assert.equal(newIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(newIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); + if (!USE_NEW_DECORATIONS) { assert.equal(2 * newIds.length, model._getMarkersCount(), 'does not leak markers'); + } else { + assert.equal(0, model._getMarkersCount(), 'does not leak markers'); + } actualNewDecorations.sort((a, b) => strcmp(a.id, b.id)); newDecorations.sort((a, b) => strcmp(a.id, b.id)); assert.deepEqual(actualDecorations, decorations); From 167c2e739b7cba51a9435ac4b7ed1f82bd467924 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 18:09:54 +0200 Subject: [PATCH 144/394] Always emit a model decorations changed event when the model is being edited --- src/vs/editor/common/model/textModelWithDecorations.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 00d521007fa..5232e03aaa4 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -137,7 +137,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _currentMarkersTracker: MarkersTracker; private _currentMarkersTrackerCnt: number; - private _tree: IntervalTree; + protected _tree: IntervalTree; private _treeDecorations: { [decorationId: string]: IntervalNode; }; private _decorations: { [decorationId: string]: InternalDecoration; }; @@ -587,13 +587,13 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _handleTrackedMarkers(markersTracker: MarkersTracker): void { let changedInternalDecorationIds = markersTracker.getDecorationIds(); if (changedInternalDecorationIds.length === 0) { + this.emitModelDecorationsChangedEvent(); return; } changedInternalDecorationIds.sort(); let previousInternalDecorationId: number = 0; - let somethingChanged = false; for (let i = 0, len = changedInternalDecorationIds.length; i < len; i++) { let internalDecorationId = changedInternalDecorationIds[i]; if (internalDecorationId === previousInternalDecorationId) { @@ -611,12 +611,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed let endMarker = decoration.endMarker.position; let range = TextModelWithDecorations._createRangeFromMarkers(startMarker, endMarker); decoration.setRange(this._multiLineDecorationsMap, range); - somethingChanged = true; } - if (somethingChanged) { - this.emitModelDecorationsChangedEvent(); - } + this.emitModelDecorationsChangedEvent(); } private static _createRangeFromMarkers(startPosition: Position, endPosition: Position): Range { From 45a7108337c0ba3d0bc33469429a14043177f40c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 Oct 2017 19:01:50 +0200 Subject: [PATCH 145/394] :lipstick: --- .../parts/editor/editorGroupsControl.ts | 23 ++++++++++--------- .../browser/parts/editor/editorPart.ts | 13 +++++++---- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts index 9f8ff8ce901..af1a3ec1a9d 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts @@ -73,7 +73,7 @@ export interface IEditorGroupsControl { getInstantiationService(position: Position): IInstantiationService; getProgressBar(position: Position): ProgressBar; updateProgress(position: Position, state: ProgressState): void; - updateTitleAreaControls(): void; + updateTitleAreas(refreshActive?: boolean): void; layout(dimension: Dimension): void; layout(position: Position): void; @@ -2075,7 +2075,13 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro return this.getFromContainer(position, EditorGroupsControl.TITLE_AREA_CONTROL_KEY); } - public updateTitleAreaControls(): void { + private getFromContainer(position: Position, key: string): any { + const silo = this.silos[position]; + + return silo ? silo.child().getProperty(key) : void 0; + } + + public updateTitleAreas(refreshActive?: boolean): void { POSITIONS.forEach(position => { const group = this.stacks.groupAt(position); if (!group) { @@ -2087,25 +2093,20 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro return; } - // Make sure the active group is shown in the title and refresh it - if (group.isActive) { + // Make sure the active group is shown in the title + // and refresh it if we are instructed to refresh it + if (refreshActive && group.isActive) { titleControl.setContext(group); titleControl.refresh(true); } - // For inactive groups, just refresh the toolbar + // Otherwise, just refresh the toolbar else { titleControl.updateEditorActionsToolbar(); } }); } - private getFromContainer(position: Position, key: string): any { - const silo = this.silos[position]; - - return silo ? silo.child().getProperty(key) : void 0; - } - public updateProgress(position: Position, state: ProgressState): void { const progressbar = this.getProgressBar(position); if (!progressbar) { diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 07f8e82161f..3b01b41686a 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -327,10 +327,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Some conditions under which we prevent the request if ( - !input || // no input - position === null || // invalid position - !this.editorGroupsControl || // too early - this.editorGroupsControl.isDragging() // pending editor DND + !input || // no input + position === null || // invalid position + !this.editorGroupsControl || // too early + this.editorGroupsControl.isDragging() // pending editor DND ) { return TPromise.as(null); } @@ -410,7 +410,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // resource context is updated and the correct number of actions will be resolved from the title // area. if (newGroupOpened && this.stacks.isActive(group)) { - this.editorGroupsControl.updateTitleAreaControls(); + this.editorGroupsControl.updateTitleAreas(true /* refresh new active group */); } return inputPromise; @@ -655,6 +655,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Explicitly trigger the focus changed handler because the side by side control will not trigger it unless // the user is actively changing focus with the mouse from left/top to right/bottom. this.onGroupFocusChanged(); + + // Update title area sync to avoid some flickering with actions + this.editorGroupsControl.updateTitleAreas(); } } From 1a37562eb7c4cd3f3794c1e647d94271bde721ba Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 19:31:36 +0200 Subject: [PATCH 146/394] Implement IntervalTree.acceptReplace --- src/vs/editor/common/model/intervalTree.ts | 282 +++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index f62dfd2ba3e..584bd513e5a 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -19,6 +19,17 @@ export const ClassName = { EditorErrorDecoration: 'errorsquiggly' }; +/** + * Describes the behavior of decorations when typing/editing near their edges. + * Note: Please do not edit the values, as they very carefully match `DecorationRangeBehavior` + */ +export const enum TrackedRangeStickiness { + AlwaysGrowsWhenTypingAtEdges = 0, + NeverGrowsWhenTypingAtEdges = 1, + GrowsOnlyWhenTypingBefore = 2, + GrowsOnlyWhenTypingAfter = 3, +} + export const enum NodeColor { Red, Black @@ -40,6 +51,7 @@ export class IntervalNode implements IModelDecoration { public ownerId: number; public options: ModelDecorationOptions; public isForValidation: boolean; + public stickiness: TrackedRangeStickiness; public cachedVersionId: number; public cachedAbsoluteStart: number; @@ -63,6 +75,7 @@ export class IntervalNode implements IModelDecoration { this.ownerId = 0; this.options = null; this.isForValidation = false; + this.stickiness = TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges; this.cachedVersionId = 0; this.cachedAbsoluteStart = start; @@ -78,6 +91,7 @@ export class IntervalNode implements IModelDecoration { this.options.className === ClassName.EditorErrorDecoration || this.options.className === ClassName.EditorWarningDecoration ); + this.stickiness = this.options.stickiness; } public setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void { @@ -163,6 +177,32 @@ export class IntervalTree { initialNode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId); } + public acceptReplace(offset: number, length: number, textLength: number, forceMoveMarkers: boolean): void { + // Our strategy is to remove all directly impacted nodes, and then add them back to the tree. + + // (1) collect all nodes that are intersecting this edit as nodes of interest + const nodesOfInterest = searchForEditing(this, offset, offset + length); + + // (2) remove all nodes that are intersecting this edit + for (let i = 0, len = nodesOfInterest.length; i < len; i++) { + const node = nodesOfInterest[i]; + rbTreeDelete(this, node); + } + + // (3) edit all tree nodes except the nodes of interest + noOverlapReplace(this, offset, offset + length, textLength); + + // (4) edit the nodes of interest and insert them back in the tree + for (let i = 0, len = nodesOfInterest.length; i < len; i++) { + const node = nodesOfInterest[i]; + node.start = node.cachedAbsoluteStart; + node.end = node.cachedAbsoluteEnd; + nodeAcceptEdit(0, node, node.start, node.end, offset, (offset + length), textLength, forceMoveMarkers); + node.maxEnd = node.end; + rbTreeInsert(this, node); + } + } + public assertInvariants(): void { assert(SENTINEL.color === NodeColor.Black); assert(SENTINEL.parent === SENTINEL); @@ -180,6 +220,10 @@ export class IntervalTree { } public print(): void { + if (this.root === SENTINEL) { + console.log(`~~ empty`); + return; + } let out: string[] = []; this._print(this.root, '', 0, out); console.log(out.join('')); @@ -200,6 +244,244 @@ export class IntervalTree { } } + +//#region Editing + +const enum MarkerMoveSemantics { + MarkerDefined = 0, + ForceMove = 1, + ForceStay = 2 +} + +function adjustMarkerBeforeColumn(markerOffset: number, markerStickToPreviousCharacter: boolean, checkOffset: number, moveSemantics: MarkerMoveSemantics): boolean { + if (markerOffset < checkOffset) { + return true; + } + if (markerOffset > checkOffset) { + return false; + } + if (moveSemantics === MarkerMoveSemantics.ForceMove) { + return false; + } + if (moveSemantics === MarkerMoveSemantics.ForceStay) { + return true; + } + return markerStickToPreviousCharacter; +}; + +function nodeAcceptEdit(delta: number, node: IntervalNode, nodeStart: number, nodeEnd: number, start: number, end: number, textLength: number, forceMoveMarkers: boolean): void { + const startStickToPreviousCharacter = ( + node.stickiness === TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges + || node.stickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore + ); + const endStickToPreviousCharacter = ( + node.stickiness === TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges + || node.stickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore + ); + + const deletingCnt = (end - start); + const insertingCnt = textLength; + const commonLength = Math.min(deletingCnt, insertingCnt); + + let startDone = false; + let endDone = false; + + { + const moveSemantics = forceMoveMarkers ? MarkerMoveSemantics.ForceMove : (deletingCnt > 0 ? MarkerMoveSemantics.ForceStay : MarkerMoveSemantics.MarkerDefined); + if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start, moveSemantics)) { + startDone = true; + } + if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start, moveSemantics)) { + endDone = true; + } + } + + if (commonLength > 0 && !forceMoveMarkers) { + const moveSemantics = (deletingCnt > insertingCnt ? MarkerMoveSemantics.ForceStay : MarkerMoveSemantics.MarkerDefined); + if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start + commonLength, moveSemantics)) { + startDone = true; + } + if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start + commonLength, moveSemantics)) { + endDone = true; + } + } + + { + const moveSemantics = forceMoveMarkers ? MarkerMoveSemantics.ForceMove : MarkerMoveSemantics.MarkerDefined; + if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, end, moveSemantics)) { + const desiredStart = start + insertingCnt; + node.start = desiredStart - delta; + startDone = true; + } + if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, end, moveSemantics)) { + const desiredEnd = start + insertingCnt; + node.end = desiredEnd - delta; + endDone = true; + } + } + + // Finish + const deltaColumn = (insertingCnt - deletingCnt); + if (!startDone) { + const desiredStart = Math.max(0, nodeStart + deltaColumn); + node.start = desiredStart - delta; + startDone = true; + } + if (!endDone) { + const desiredEnd = Math.max(0, nodeEnd + deltaColumn); + node.end = desiredEnd - delta; + endDone = true; + } + + if (node.start > node.end) { + node.end = node.start; + } +} + +function searchForEditing(T: IntervalTree, start: number, end: number): IntervalNode[] { + // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + // Now, it is known that two intervals A and B overlap only when both + // A.low <= B.high and A.high >= B.low. When searching the trees for + // nodes overlapping with a given interval, you can immediately skip: + // a) all nodes to the right of nodes whose low value is past the end of the given interval. + // b) all nodes that have their maximum 'high' value below the start of the given interval. + let node = T.root; + let delta = 0; + let nodeMaxEnd = 0; + let nodeStart = 0; + let nodeEnd = 0; + let result: IntervalNode[] = []; + let resultLen = 0; + while (node !== SENTINEL) { + if (node.visited) { + // going up from this node + node.left.visited = false; + node.right.visited = false; + if (node === node.parent.right) { + delta -= node.parent.delta; + } + node = node.parent; + continue; + } + + if (!node.left.visited) { + // first time seeing this node + nodeMaxEnd = delta + node.maxEnd; + if (nodeMaxEnd < start) { + // cover case b) from above + // there is no need to search this node or its children + node.visited = true; + continue; + } + + if (node.left !== SENTINEL) { + // go left + node = node.left; + continue; + } + } + + // handle current node + nodeStart = delta + node.start; + if (nodeStart > end) { + // cover case a) from above + // there is no need to search this node or its right subtree + node.visited = true; + continue; + } + + nodeEnd = delta + node.end; + if (nodeEnd >= start) { + node.setCachedOffsets(nodeStart, nodeEnd, 0); + result[resultLen++] = node; + } + node.visited = true; + + if (node.right !== SENTINEL && !node.right.visited) { + // go right + delta += node.delta; + node = node.right; + continue; + } + } + + if (T.root) { + T.root.visited = false; + } + + return result; +} + +function noOverlapReplace(T: IntervalTree, start: number, end: number, textLength: number): void { + // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + // Now, it is known that two intervals A and B overlap only when both + // A.low <= B.high and A.high >= B.low. When searching the trees for + // nodes overlapping with a given interval, you can immediately skip: + // a) all nodes to the right of nodes whose low value is past the end of the given interval. + // b) all nodes that have their maximum 'high' value below the start of the given interval. + let node = T.root; + let delta = 0; + let nodeMaxEnd = 0; + let nodeStart = 0; + while (node !== SENTINEL) { + if (node.visited) { + // going up from this node + node.left.visited = false; + node.right.visited = false; + if (node === node.parent.right) { + delta -= node.parent.delta; + } + recomputeMaxEnd(node); + node = node.parent; + continue; + } + + if (!node.left.visited) { + // first time seeing this node + nodeMaxEnd = delta + node.maxEnd; + if (nodeMaxEnd < start) { + // cover case b) from above + // there is no need to search this node or its children + node.visited = true; + continue; + } + + if (node.left !== SENTINEL) { + // go left + node = node.left; + continue; + } + } + + // handle current node + nodeStart = delta + node.start; + if (nodeStart > end) { + node.start += (textLength - (end - start)); + node.end += (textLength - (end - start)); + node.delta += (textLength - (end - start)); + // cover case a) from above + // there is no need to search this node or its right subtree + node.visited = true; + continue; + } + + node.visited = true; + + if (node.right !== SENTINEL && !node.right.visited) { + // go right + delta += node.delta; + node = node.right; + continue; + } + } + + if (T.root) { + T.root.visited = false; + } +} + +//#endregion + //#region Searching function nodeCount(T: IntervalTree): number { From a4ae83754b19ca38a027954183e65250b50fe4e2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 16 Oct 2017 19:38:54 +0200 Subject: [PATCH 147/394] fix decorations service test --- .../decorations/test/browser/decorationsService.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index 54f37ccf294..21708a3b55d 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -66,7 +66,7 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return { color: 'someBlue', tooltip: 'Z' }; + return { color: 'someBlue', title: 'Z' }; } }); @@ -84,7 +84,7 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return { color: 'someBlue', tooltip: 'J' }; + return { color: 'someBlue', title: 'J' }; } }); From b179e24a85494d64aa231c6b35c91fe045b3a8d0 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 20:43:51 +0200 Subject: [PATCH 148/394] Update interval tree when edits occur --- .../editor/common/model/editableTextModel.ts | 10 +- src/vs/editor/common/model/intervalTree.ts | 23 +-- .../common/model/textModelWithDecorations.ts | 7 + .../common/model/editableTextModel.test.ts | 160 +++++++++--------- .../common/model/modelDecorations.test.ts | 4 +- 5 files changed, 112 insertions(+), 92 deletions(-) diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index 66566d1092b..e8c617fc2c2 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -23,6 +23,7 @@ export interface IValidatedEditOperation { sortIndex: number; identifier: editorCommon.ISingleEditOperationIdentifier; range: Range; + rangeOffset: number; rangeLength: number; lines: string[]; forceMoveMarkers: boolean; @@ -249,6 +250,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito sortIndex: 0, identifier: operations[0].identifier, range: entireEditRange, + rangeOffset: this.getOffsetAt(entireEditRange.getStartPosition()), rangeLength: this.getValueLengthInRange(entireEditRange), lines: result.join('').split('\n'), forceMoveMarkers: forceMoveMarkers, @@ -288,6 +290,8 @@ export class EditableTextModel extends TextModelWithDecorations implements edito return []; } + this._ensureLineStarts(); + let mightContainRTL = this._mightContainRTL; let mightContainNonBasicASCII = this._mightContainNonBasicASCII; let canReduceOperations = true; @@ -310,6 +314,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito sortIndex: i, identifier: op.identifier, range: validatedRange, + rangeOffset: this.getOffsetAt(validatedRange.getStartPosition()), rangeLength: this.getValueLengthInRange(validatedRange), lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, forceMoveMarkers: op.forceMoveMarkers, @@ -675,12 +680,15 @@ export class EditableTextModel extends TextModelWithDecorations implements edito ); } + const text = (op.lines ? op.lines.join(this.getEOL()) : ''); contentChanges.push({ range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), rangeLength: op.rangeLength, - text: op.lines ? op.lines.join(this.getEOL()) : '' + text: text }); + this._tree.acceptReplace(op.rangeOffset, op.rangeLength, text.length, op.forceMoveMarkers); + // console.log('AFTER:'); // console.log('<<<\n' + this._lines.map(l => l.text).join('\n') + '\n>>>'); } diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 584bd513e5a..b73d5adb293 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -197,7 +197,7 @@ export class IntervalTree { const node = nodesOfInterest[i]; node.start = node.cachedAbsoluteStart; node.end = node.cachedAbsoluteEnd; - nodeAcceptEdit(0, node, node.start, node.end, offset, (offset + length), textLength, forceMoveMarkers); + nodeAcceptEdit(node, offset, (offset + length), textLength, forceMoveMarkers); node.maxEnd = node.end; rbTreeInsert(this, node); } @@ -269,7 +269,11 @@ function adjustMarkerBeforeColumn(markerOffset: number, markerStickToPreviousCha return markerStickToPreviousCharacter; }; -function nodeAcceptEdit(delta: number, node: IntervalNode, nodeStart: number, nodeEnd: number, start: number, end: number, textLength: number, forceMoveMarkers: boolean): void { +/** + * This is a lot more complicated than strictly necessary to maintain the same behaviour + * as when decorations were implemented using two markers. + */ +function nodeAcceptEdit(node: IntervalNode, start: number, end: number, textLength: number, forceMoveMarkers: boolean): void { const startStickToPreviousCharacter = ( node.stickiness === TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges || node.stickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore @@ -283,7 +287,10 @@ function nodeAcceptEdit(delta: number, node: IntervalNode, nodeStart: number, no const insertingCnt = textLength; const commonLength = Math.min(deletingCnt, insertingCnt); + const nodeStart = node.start; let startDone = false; + + const nodeEnd = node.end; let endDone = false; { @@ -309,13 +316,11 @@ function nodeAcceptEdit(delta: number, node: IntervalNode, nodeStart: number, no { const moveSemantics = forceMoveMarkers ? MarkerMoveSemantics.ForceMove : MarkerMoveSemantics.MarkerDefined; if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, end, moveSemantics)) { - const desiredStart = start + insertingCnt; - node.start = desiredStart - delta; + node.start = start + insertingCnt; startDone = true; } if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, end, moveSemantics)) { - const desiredEnd = start + insertingCnt; - node.end = desiredEnd - delta; + node.end = start + insertingCnt; endDone = true; } } @@ -323,13 +328,11 @@ function nodeAcceptEdit(delta: number, node: IntervalNode, nodeStart: number, no // Finish const deltaColumn = (insertingCnt - deletingCnt); if (!startDone) { - const desiredStart = Math.max(0, nodeStart + deltaColumn); - node.start = desiredStart - delta; + node.start = Math.max(0, nodeStart + deltaColumn); startDone = true; } if (!endDone) { - const desiredEnd = Math.max(0, nodeEnd + deltaColumn); - node.end = desiredEnd - delta; + node.end = Math.max(0, nodeEnd + deltaColumn); endDone = true; } diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 5232e03aaa4..bcece192514 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -169,6 +169,10 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._decorations = null; this._internalDecorations = null; this._multiLineDecorationsMap = null; + + this._tree = null; + this._treeDecorations = null; + super.dispose(); } @@ -179,6 +183,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._decorations = Object.create(null); this._internalDecorations = Object.create(null); this._multiLineDecorationsMap = Object.create(null); + + this._tree = new IntervalTree(); + this._treeDecorations = Object.create(null); } private static _shouldStartMarkerSticksToPreviousCharacter(stickiness: editorCommon.TrackedRangeStickiness): boolean { diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 6166f3eb8e5..266b6b67f05 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -15,12 +15,13 @@ import { IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvent suite('EditorModel - EditableTextModel._getInverseEdits', () => { - function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeLength: number, text: string[]): IValidatedEditOperation { + function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, text: string[]): IValidatedEditOperation { return { sortIndex: 0, identifier: null, range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), - rangeLength: rangeLength, + rangeOffset: 0, + rangeLength: 0, lines: text, forceMoveMarkers: false, isAutoWhitespaceEdit: false @@ -39,7 +40,7 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('single insert', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello']) + editOp(1, 1, 1, 1, ['hello']) ], [ inverseEditOp(1, 1, 1, 6) @@ -50,8 +51,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('Bug 19872: Undo is funky', () => { assertInverseEdits( [ - editOp(2, 1, 2, 2, 0, ['']), - editOp(3, 1, 4, 2, 0, ['']) + editOp(2, 1, 2, 2, ['']), + editOp(3, 1, 4, 2, ['']) ], [ inverseEditOp(2, 1, 2, 1), @@ -63,8 +64,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two single unrelated inserts', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello']), - editOp(2, 1, 2, 1, 0, ['world']) + editOp(1, 1, 1, 1, ['hello']), + editOp(2, 1, 2, 1, ['world']) ], [ inverseEditOp(1, 1, 1, 6), @@ -76,8 +77,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two single inserts 1', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello']), - editOp(1, 2, 1, 2, 0, ['world']) + editOp(1, 1, 1, 1, ['hello']), + editOp(1, 2, 1, 2, ['world']) ], [ inverseEditOp(1, 1, 1, 6), @@ -89,8 +90,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two single inserts 2', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello']), - editOp(1, 4, 1, 4, 0, ['world']) + editOp(1, 1, 1, 1, ['hello']), + editOp(1, 4, 1, 4, ['world']) ], [ inverseEditOp(1, 1, 1, 6), @@ -102,7 +103,7 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('multiline insert', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello', 'world']) + editOp(1, 1, 1, 1, ['hello', 'world']) ], [ inverseEditOp(1, 1, 2, 6) @@ -113,8 +114,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two unrelated multiline inserts', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello', 'world']), - editOp(2, 1, 2, 1, 0, ['how', 'are', 'you?']), + editOp(1, 1, 1, 1, ['hello', 'world']), + editOp(2, 1, 2, 1, ['how', 'are', 'you?']), ], [ inverseEditOp(1, 1, 2, 6), @@ -126,8 +127,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two multiline inserts 1', () => { assertInverseEdits( [ - editOp(1, 1, 1, 1, 0, ['hello', 'world']), - editOp(1, 2, 1, 2, 0, ['how', 'are', 'you?']), + editOp(1, 1, 1, 1, ['hello', 'world']), + editOp(1, 2, 1, 2, ['how', 'are', 'you?']), ], [ inverseEditOp(1, 1, 2, 6), @@ -139,7 +140,7 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('single delete', () => { assertInverseEdits( [ - editOp(1, 1, 1, 6, 0, null) + editOp(1, 1, 1, 6, null) ], [ inverseEditOp(1, 1, 1, 1) @@ -150,8 +151,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two single unrelated deletes', () => { assertInverseEdits( [ - editOp(1, 1, 1, 6, 0, null), - editOp(2, 1, 2, 6, 0, null) + editOp(1, 1, 1, 6, null), + editOp(2, 1, 2, 6, null) ], [ inverseEditOp(1, 1, 1, 1), @@ -163,8 +164,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two single deletes 1', () => { assertInverseEdits( [ - editOp(1, 1, 1, 6, 0, null), - editOp(1, 7, 1, 12, 0, null) + editOp(1, 1, 1, 6, null), + editOp(1, 7, 1, 12, null) ], [ inverseEditOp(1, 1, 1, 1), @@ -176,8 +177,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two single deletes 2', () => { assertInverseEdits( [ - editOp(1, 1, 1, 6, 0, null), - editOp(1, 9, 1, 14, 0, null) + editOp(1, 1, 1, 6, null), + editOp(1, 9, 1, 14, null) ], [ inverseEditOp(1, 1, 1, 1), @@ -189,7 +190,7 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('multiline delete', () => { assertInverseEdits( [ - editOp(1, 1, 2, 6, 0, null) + editOp(1, 1, 2, 6, null) ], [ inverseEditOp(1, 1, 1, 1) @@ -200,8 +201,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two unrelated multiline deletes', () => { assertInverseEdits( [ - editOp(1, 1, 2, 6, 0, null), - editOp(3, 1, 5, 5, 0, null), + editOp(1, 1, 2, 6, null), + editOp(3, 1, 5, 5, null), ], [ inverseEditOp(1, 1, 1, 1), @@ -213,8 +214,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two multiline deletes 1', () => { assertInverseEdits( [ - editOp(1, 1, 2, 6, 0, null), - editOp(2, 7, 4, 5, 0, null), + editOp(1, 1, 2, 6, null), + editOp(2, 7, 4, 5, null), ], [ inverseEditOp(1, 1, 1, 1), @@ -226,7 +227,7 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('single replace', () => { assertInverseEdits( [ - editOp(1, 1, 1, 6, 0, ['Hello world']) + editOp(1, 1, 1, 6, ['Hello world']) ], [ inverseEditOp(1, 1, 1, 12) @@ -237,8 +238,8 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('two replaces', () => { assertInverseEdits( [ - editOp(1, 1, 1, 6, 0, ['Hello world']), - editOp(1, 7, 1, 8, 0, ['How are you?']), + editOp(1, 1, 1, 6, ['Hello world']), + editOp(1, 7, 1, 8, ['How are you?']), ], [ inverseEditOp(1, 1, 1, 12), @@ -250,9 +251,9 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { test('many edits', () => { assertInverseEdits( [ - editOp(1, 2, 1, 2, 0, ['', ' ']), - editOp(1, 5, 1, 6, 0, ['']), - editOp(1, 9, 1, 9, 0, ['', '']) + editOp(1, 2, 1, 2, ['', ' ']), + editOp(1, 5, 1, 6, ['']), + editOp(1, 9, 1, 9, ['', '']) ], [ inverseEditOp(1, 2, 2, 3), @@ -265,11 +266,12 @@ suite('EditorModel - EditableTextModel._getInverseEdits', () => { suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { - function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeLength: number, text: string[]): IValidatedEditOperation { + function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeOffset: number, rangeLength: number, text: string[]): IValidatedEditOperation { return { sortIndex: 0, identifier: null, range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), + rangeOffset: rangeOffset, rangeLength: rangeLength, lines: text, forceMoveMarkers: false, @@ -297,9 +299,9 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '1' ], [ - editOp(1, 3, 1, 3, 0, [' new line', 'No longer']) + editOp(1, 3, 1, 3, 2, 0, [' new line', 'No longer']) ], - editOp(1, 3, 1, 3, 0, [' new line', 'No longer']) + editOp(1, 3, 1, 3, 2, 0, [' new line', 'No longer']) ); }); @@ -311,11 +313,11 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '', '1' ], [ - editOp(1, 1, 1, 3, 0, ['Your']), - editOp(1, 4, 1, 4, 0, ['Interesting ']), - editOp(2, 3, 2, 6, 0, null) + editOp(1, 1, 1, 3, 0, 2, ['Your']), + editOp(1, 4, 1, 4, 3, 0, ['Interesting ']), + editOp(2, 3, 2, 6, 16, 3, null) ], - editOp(1, 1, 2, 6, 19, [ + editOp(1, 1, 2, 6, 0, 19, [ 'Your Interesting First Line', '\t\t' ])); @@ -331,10 +333,10 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '1' ], [ - editOp(1, 3, 1, 3, 0, ['', '', '', '', '']), - editOp(3, 15, 3, 15, 0, ['a', 'b']) + editOp(1, 3, 1, 3, 2, 0, ['', '', '', '', '']), + editOp(3, 15, 3, 15, 45, 0, ['a', 'b']) ], - editOp(1, 3, 3, 15, 43, [ + editOp(1, 3, 3, 15, 2, 43, [ '', '', '', @@ -357,9 +359,9 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '1' ], [ - editOp(1, 1, 1, 1, 0, ['']) + editOp(1, 1, 1, 1, 0, 0, ['']) ], - editOp(1, 1, 1, 1, 0, ['']) + editOp(1, 1, 1, 1, 0, 0, ['']) ); }); @@ -373,10 +375,10 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '123' ], [ - editOp(2, 1, 2, 3, 0, ['\t']), - editOp(3, 1, 3, 5, 0, ['']) + editOp(2, 1, 2, 3, 14, 2, ['\t']), + editOp(3, 1, 3, 5, 31, 4, ['']) ], - editOp(2, 1, 3, 5, 21, ['\tMy Second Line', '']) + editOp(2, 1, 3, 5, 14, 21, ['\tMy Second Line', '']) ); }); @@ -386,11 +388,11 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '{"x" : 1}' ], [ - editOp(1, 2, 1, 2, 0, ['\n ']), - editOp(1, 5, 1, 6, 0, ['']), - editOp(1, 9, 1, 9, 0, ['\n']) + editOp(1, 2, 1, 2, 1, 0, ['\n ']), + editOp(1, 5, 1, 6, 4, 1, ['']), + editOp(1, 9, 1, 9, 8, 0, ['\n']) ], - editOp(1, 2, 1, 9, 7, [ + editOp(1, 2, 1, 9, 1, 7, [ '', ' "x": 1', '' @@ -406,11 +408,11 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '}' ], [ - editOp(1, 2, 2, 3, 0, ['']), - editOp(2, 6, 2, 6, 0, [' ']), - editOp(2, 9, 3, 1, 0, ['']) + editOp(1, 2, 2, 3, 1, 3, ['']), + editOp(2, 6, 2, 6, 7, 0, [' ']), + editOp(2, 9, 3, 1, 10, 1, ['']) ], - editOp(1, 2, 3, 1, 10, ['"x" : 1']) + editOp(1, 2, 3, 1, 1, 10, ['"x" : 1']) ); }); @@ -424,10 +426,10 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { '}' ], [ - editOp(1, 2, 2, 1, 0, ['', '\t']), - editOp(2, 11, 4, 1, 0, ['', '\t']) + editOp(1, 2, 2, 1, 1, 1, ['', '\t']), + editOp(2, 11, 4, 1, 12, 2, ['', '\t']) ], - editOp(1, 2, 4, 1, 13, [ + editOp(1, 2, 4, 1, 1, 13, [ '', '\t"a": true,', '\t' @@ -446,12 +448,12 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { 'and the last line' ], [ - editOp(1, 5, 3, 1, 0, [' text', 'some more text', 'some more text']), - editOp(3, 2, 4, 1, 0, ['o more lines', 'asd', 'asd', 'asd']), - editOp(5, 1, 5, 6, 0, ['zzzzzzzz']), - editOp(5, 11, 6, 16, 0, ['1', '2', '3', '4']) + editOp(1, 5, 3, 1, 4, 21, [' text', 'some more text', 'some more text']), + editOp(3, 2, 4, 1, 26, 23, ['o more lines', 'asd', 'asd', 'asd']), + editOp(5, 1, 5, 6, 50, 5, ['zzzzzzzz']), + editOp(5, 11, 6, 16, 60, 22, ['1', '2', '3', '4']) ], - editOp(1, 5, 6, 16, 78, [ + editOp(1, 5, 6, 16, 4, 78, [ ' text', 'some more text', 'some more textno more lines', @@ -475,17 +477,17 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { ' ,"e": /*comment*/ [null] }', ], [ - editOp(1, 1, 1, 2, 0, ['']), - editOp(1, 3, 1, 10, 0, ['', ' ']), - editOp(1, 16, 2, 14, 0, ['', ' ']), - editOp(2, 18, 3, 9, 0, ['', ' ']), - editOp(3, 22, 4, 9, 0, ['']), - editOp(4, 10, 4, 10, 0, ['', ' ']), - editOp(4, 28, 4, 28, 0, ['', ' ']), - editOp(4, 32, 4, 32, 0, ['', ' ']), - editOp(4, 33, 4, 34, 0, ['', '']) + editOp(1, 1, 1, 2, 0, 1, ['']), + editOp(1, 3, 1, 10, 2, 7, ['', ' ']), + editOp(1, 16, 2, 14, 15, 14, ['', ' ']), + editOp(2, 18, 3, 9, 33, 9, ['', ' ']), + editOp(3, 22, 4, 9, 55, 9, ['']), + editOp(4, 10, 4, 10, 65, 0, ['', ' ']), + editOp(4, 28, 4, 28, 83, 0, ['', ' ']), + editOp(4, 32, 4, 32, 87, 0, ['', ' ']), + editOp(4, 33, 4, 34, 88, 1, ['', '']) ], - editOp(1, 1, 4, 34, 89, [ + editOp(1, 1, 4, 34, 0, 89, [ '{', ' "d": [', ' null', @@ -505,11 +507,11 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { ' ,def' ], [ - editOp(1, 1, 1, 4, 0, ['']), - editOp(1, 7, 2, 2, 0, ['']), - editOp(2, 3, 2, 3, 0, ['', '']) + editOp(1, 1, 1, 4, 0, 3, ['']), + editOp(1, 7, 2, 2, 6, 2, ['']), + editOp(2, 3, 2, 3, 9, 0, ['', '']) ], - editOp(1, 1, 2, 3, 9, [ + editOp(1, 1, 2, 3, 0, 9, [ 'abc,', '' ]) diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 4d0c3bbbe95..8e808191925 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -1096,7 +1096,7 @@ suite('deltaDecorations', () => { assert.equal(initialIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(initialIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); if (!USE_NEW_DECORATIONS) { - assert.equal(2 * initialIds.length, model._getMarkersCount(), 'does not leak markers'); + assert.equal(2 * initialIds.length, model._getMarkersCount(), 'does not leak markers'); } else { assert.equal(0, model._getMarkersCount(), 'does not leak markers'); } @@ -1111,7 +1111,7 @@ suite('deltaDecorations', () => { assert.equal(newIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(newIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); if (!USE_NEW_DECORATIONS) { - assert.equal(2 * newIds.length, model._getMarkersCount(), 'does not leak markers'); + assert.equal(2 * newIds.length, model._getMarkersCount(), 'does not leak markers'); } else { assert.equal(0, model._getMarkersCount(), 'does not leak markers'); } From d4408e2bdd2cfee7bb7f5b9d8dacb06edcc02273 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 22:13:48 +0200 Subject: [PATCH 149/394] Optimize deltaDecorations --- src/vs/editor/common/model/intervalTree.ts | 10 ++ .../common/model/textModelWithDecorations.ts | 141 ++++++++---------- 2 files changed, 75 insertions(+), 76 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index b73d5adb293..9b6970da508 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -85,6 +85,16 @@ export class IntervalNode implements IModelDecoration { this.visited = false; } + public reset(versionId: number, start: number, end: number, range: Range): void { + this.start = start; + this.end = end; + this.maxEnd = end; + this.cachedVersionId = versionId; + this.cachedAbsoluteStart = start; + this.cachedAbsoluteEnd = end; + this.range = range; + } + public setOptions(options: ModelDecorationOptions) { this.options = options; this.isForValidation = ( diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index bcece192514..b4289f3aedd 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -228,7 +228,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed let changeAccessor: editorCommon.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: editorCommon.IModelDecorationOptions): string => { if (USE_NEW_DECORATIONS) { - return this._deltaDecorationsImpl2(decorationsTracker, [], this._normalizeDeltaDecorations2(ownerId, [{ range: range, options: options }]))[0]; + return this._deltaDecorationsImpl2(decorationsTracker, ownerId, [], [{ range: range, options: options }])[0]; } return this._addDecorationImpl(decorationsTracker, ownerId, this.validateRange(range), _normalizeOptions(options)); }, @@ -248,14 +248,14 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed }, removeDecoration: (id: string): void => { if (USE_NEW_DECORATIONS) { - this._deltaDecorationsImpl2(decorationsTracker, [id], []); + this._deltaDecorationsImpl2(decorationsTracker, ownerId, [id], []); return; } this._removeDecorationImpl(decorationsTracker, id); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { if (USE_NEW_DECORATIONS) { - return this._deltaDecorationsImpl2(decorationsTracker, oldDecorations, this._normalizeDeltaDecorations2(ownerId, newDecorations)); + return this._deltaDecorationsImpl2(decorationsTracker, ownerId, oldDecorations, newDecorations); } return this._deltaDecorationsImpl(decorationsTracker, ownerId, oldDecorations, this._normalizeDeltaDecorations(newDecorations)); } @@ -679,30 +679,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return result; } - private _normalizeDeltaDecorations2(ownerId: number, deltaDecorations: editorCommon.IModelDeltaDecoration[]): IntervalNode[] { - this._ensureLineStarts(); - - const versionId = this.getVersionId(); - let result = new Array(deltaDecorations.length); - for (let i = 0, len = deltaDecorations.length; i < len; i++) { - const dec = deltaDecorations[i]; - const range = this._validateRangeRelaxedNoAllocations(dec.range); - const options = _normalizeOptions(dec.options); - - const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; - const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; - - const node = new IntervalNode(null, startOffset, endOffset); - node.ownerId = ownerId; - node.cachedVersionId = versionId; - node.range = range; - node.setOptions(options); - - result[i] = node; - } - return result; - } - private _externalDecorationId(internalId: number): string { return `${this._instanceId};${internalId}`; } @@ -790,25 +766,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return decorationIds; } - private _addDecorationsImpl2(decorationsTracker: DecorationsTracker, newDecorations: IntervalNode[]): string[] { - - let decorationIds: string[] = new Array(newDecorations.length); - for (let i = 0, len = newDecorations.length; i < len; i++) { - const node = newDecorations[i]; - const internalDecorationId = (++this._lastDecorationId); - const decorationId = this._externalDecorationId(internalDecorationId); - node.id = decorationId; - - this._tree.insert(node); - this._treeDecorations[decorationId] = node; - decorationIds[i] = decorationId; - } - - decorationsTracker.markDidAddDecorations(); - - return decorationIds; - } - private _changeDecorationImpl(decorationsTracker: DecorationsTracker, decorationId: string, newRange: Range): void { let decoration = this._decorations[decorationId]; if (!decoration) { @@ -846,11 +803,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; this._tree.delete(node); - node.start = startOffset; - node.end = endOffset; - node.maxEnd = endOffset; - node.setCachedOffsets(startOffset, endOffset, this.getVersionId()); - node.range = range; + node.reset(this.getVersionId(), startOffset, endOffset, range); this._tree.insert(node); decorationsTracker.markDidChangeDecorations(); @@ -926,23 +879,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } } - private _removeDecorationsImpl2(decorationsTracker: DecorationsTracker, decorationIds: string[]): void { - for (let i = 0, len = decorationIds.length; i < len; i++) { - const decorationId = decorationIds[i]; - const node = this._treeDecorations[decorationId]; - if (!node) { - continue; - } - - this._tree.delete(node); - delete this._treeDecorations[decorationId]; - } - - if (decorationsTracker) { - decorationsTracker.markDidRemoveDecorations(); - } - } - private _resolveOldDecorations(oldDecorations: string[]): InternalDecoration[] { let result: InternalDecoration[] = []; for (let i = 0, len = oldDecorations.length; i < len; i++) { @@ -1045,16 +981,69 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return result; } - private _deltaDecorationsImpl2(decorationsTracker: DecorationsTracker, oldDecorationsIds: string[], newDecorations: IntervalNode[]): string[] { - // TODO@interval: is it worth it to compare? - if (oldDecorationsIds.length > 0) { - this._removeDecorationsImpl2(decorationsTracker, oldDecorationsIds); + private _deltaDecorationsImpl2(decorationsTracker: DecorationsTracker, ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { + this._ensureLineStarts(); + const versionId = this.getVersionId(); + + const oldDecorationsLen = oldDecorationsIds.length; + let oldDecorationIndex = 0; + + const newDecorationsLen = newDecorations.length; + let newDecorationIndex = 0; + + let result = new Array(newDecorationsLen); + while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) { + + let node: IntervalNode = null; + + if (oldDecorationIndex < oldDecorationsLen) { + // (1) get ourselves an old node + do { + node = this._treeDecorations[oldDecorationsIds[oldDecorationIndex++]]; + } while (!node && oldDecorationIndex < oldDecorationsLen); + + // (2) remove the node from the tree (if it exists) + if (node) { + this._tree.delete(node); + } + } + + if (newDecorationIndex < newDecorationsLen) { + // (3) create a new node if necessary + if (!node) { + const internalDecorationId = (++this._lastDecorationId); + const decorationId = this._externalDecorationId(internalDecorationId); + node = new IntervalNode(decorationId, 0, 0); + this._treeDecorations[decorationId] = node; + } + + // (4) initialize node + const newDecoration = newDecorations[newDecorationIndex]; + const range = this._validateRangeRelaxedNoAllocations(newDecoration.range); + const options = _normalizeOptions(newDecoration.options); + const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; + + node.ownerId = ownerId; + node.reset(versionId, startOffset, endOffset, range); + node.setOptions(options); + + this._tree.insert(node); + + result[newDecorationIndex] = node.id; + + newDecorationIndex++; + } else { + if (node) { + delete this._treeDecorations[node.id]; + } + } } - if (newDecorations.length > 0) { - return this._addDecorationsImpl2(decorationsTracker, newDecorations); - } - return []; + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + + return result; } } From 324650128e3ec2442a88cf031a3207ff2a39262a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 16 Oct 2017 22:48:45 +0200 Subject: [PATCH 150/394] Add fast path for vscode.TextEditor.setDecorations --- src/vs/editor/common/commonCodeEditor.ts | 21 ++++++++++++++ src/vs/editor/common/editorCommon.ts | 5 ++++ .../api/electron-browser/mainThreadEditor.ts | 11 ++++++++ .../api/electron-browser/mainThreadEditors.ts | 8 ++++++ src/vs/workbench/api/node/extHost.protocol.ts | 1 + .../workbench/api/node/extHostTextEditor.ts | 28 +++++++++++++++---- .../api/node/extHostTypeConverters.ts | 2 +- .../api/extHostTextEditor.test.ts | 1 + 8 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 2c38ec938d2..4881d847e08 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -30,6 +30,7 @@ import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/ed import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { VerticalRevealType } from 'vs/editor/common/view/viewEvents'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; let EDITOR_ID = 0; @@ -856,6 +857,26 @@ export abstract class CommonCodeEditor extends Disposable implements editorCommo this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations); } + public setDecorationsFast(decorationTypeKey: string, ranges: IRange[]): void { + + // remove decoration sub types that are no longer used, deregister decoration type if necessary + let oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {}; + for (let subType in oldDecorationsSubTypes) { + this._removeDecorationType(decorationTypeKey + '-' + subType); + } + this._decorationTypeSubtypes[decorationTypeKey] = {}; + + const opts = ModelDecorationOptions.createDynamic(this._resolveDecorationOptions(decorationTypeKey, false)); + let newModelDecorations: editorCommon.IModelDeltaDecoration[] = new Array(ranges.length); + for (let i = 0, len = ranges.length; i < len; i++) { + newModelDecorations[i] = { range: ranges[i], options: opts }; + } + + // update all decorations + let oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || []; + this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations); + } + public removeDecorations(decorationTypeKey: string): void { // remove decorations for type and sub type let oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey]; diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index e0f3ad0a160..837485b70a9 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -1984,6 +1984,11 @@ export interface ICommonCodeEditor extends IEditor { */ setDecorations(decorationTypeKey: string, ranges: IDecorationOptions[]): void; + /** + * @internal + */ + setDecorationsFast(decorationTypeKey: string, ranges: IRange[]): void; + /** * @internal */ diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts index 0da01725b17..bc23649dbe8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts @@ -244,6 +244,17 @@ export class MainThreadTextEditor { this._codeEditor.setDecorations(key, ranges); } + public setDecorationsFast(key: string, _ranges: number[]): void { + if (!this._codeEditor) { + return; + } + let ranges: Range[] = []; + for (let i = 0, len = Math.floor(_ranges.length / 4); i < len; i++) { + ranges[i] = new Range(_ranges[4 * i], _ranges[4 * i + 1], _ranges[4 * i + 2], _ranges[4 * i + 3]); + } + this._codeEditor.setDecorationsFast(key, ranges); + } + public revealRange(range: IRange, revealType: TextEditorRevealType): void { if (!this._codeEditor) { return; diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts index df3174ae67c..6787006461b 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts @@ -195,6 +195,14 @@ export class MainThreadEditors implements MainThreadEditorsShape { return TPromise.as(null); } + $trySetDecorationsFast(id: string, key: string, ranges: string): TPromise { + if (!this._documentsAndEditors.getEditor(id)) { + return TPromise.wrapError(disposed(`TextEditor(${id})`)); + } + this._documentsAndEditors.getEditor(id).setDecorationsFast(key, /*TODO: marshaller is too slow*/JSON.parse(ranges)); + return TPromise.as(null); + } + $tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise { if (!this._documentsAndEditors.getEditor(id)) { return TPromise.wrapError(disposed(`TextEditor(${id})`)); diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index a3d65955516..0dfea1602f3 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -210,6 +210,7 @@ export interface MainThreadEditorsShape extends IDisposable { $tryHideEditor(id: string): TPromise; $trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise; $trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise; + $trySetDecorationsFast(id: string, key: string, ranges: string): TPromise; $tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise; $trySetSelections(id: string, selections: ISelection[]): TPromise; $tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise; diff --git a/src/vs/workbench/api/node/extHostTextEditor.ts b/src/vs/workbench/api/node/extHostTextEditor.ts index 763969acc96..9872ac721fd 100644 --- a/src/vs/workbench/api/node/extHostTextEditor.ts +++ b/src/vs/workbench/api/node/extHostTextEditor.ts @@ -416,11 +416,29 @@ export class ExtHostTextEditor implements vscode.TextEditor { setDecorations(decorationType: vscode.TextEditorDecorationType, ranges: Range[] | vscode.DecorationOptions[]): void { this._runOnProxy( - () => this._proxy.$trySetDecorations( - this._id, - decorationType.key, - TypeConverters.fromRangeOrRangeWithMessage(ranges) - ) + () => { + if (TypeConverters.isDecorationOptionsArr(ranges)) { + return this._proxy.$trySetDecorations( + this._id, + decorationType.key, + TypeConverters.fromRangeOrRangeWithMessage(ranges) + ); + } else { + let _ranges: number[] = new Array(4 * ranges.length); + for (let i = 0, len = ranges.length; i < len; i++) { + const range = ranges[i]; + _ranges[4 * i] = range.start.line + 1; + _ranges[4 * i + 1] = range.start.character + 1; + _ranges[4 * i + 2] = range.end.line + 1; + _ranges[4 * i + 3] = range.end.character + 1; + } + return this._proxy.$trySetDecorationsFast( + this._id, + decorationType.key, + /*TODO: marshaller is too slow*/JSON.stringify(_ranges) + ); + } + } ); } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index 54c80ba84c4..ca9561d8d25 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -139,7 +139,7 @@ function isDecorationOptions(something: any): something is vscode.DecorationOpti return (typeof something.range !== 'undefined'); } -function isDecorationOptionsArr(something: vscode.Range[] | vscode.DecorationOptions[]): something is vscode.DecorationOptions[] { +export function isDecorationOptionsArr(something: vscode.Range[] | vscode.DecorationOptions[]): something is vscode.DecorationOptions[] { if (something.length === 0) { return true; } diff --git a/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts index 402466a620e..48d6e46c0c7 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts @@ -61,6 +61,7 @@ suite('ExtHostTextEditorOptions', () => { $tryShowEditor: undefined, $tryHideEditor: undefined, $trySetDecorations: undefined, + $trySetDecorationsFast: undefined, $tryRevealRange: undefined, $trySetSelections: undefined, $tryApplyEdits: undefined, From b5774640f1c056c115027f5755c78e7496fbfc47 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 23:01:02 +0200 Subject: [PATCH 151/394] Use IConfigurationService.updateValue instead of IConfigurationEditingService --- .../configuration/common/configuration.ts | 6 +- .../common/configurationModels.ts | 10 ++-- .../mainThreadConfiguration.ts | 9 ++- src/vs/workbench/api/node/extHost.protocol.ts | 3 +- .../api/node/extHostConfiguration.ts | 5 +- .../actions/toggleActivityBarVisibility.ts | 8 +-- .../browser/actions/toggleSidebarPosition.ts | 10 ++-- .../actions/toggleStatusbarVisibility.ts | 8 +-- .../browser/parts/editor/editorStatus.ts | 21 ++----- src/vs/workbench/electron-browser/actions.ts | 33 ++++------- src/vs/workbench/electron-browser/window.ts | 5 +- .../electron-browser/accessibility.ts | 9 +-- .../electron-browser/toggleMinimap.ts | 6 +- .../toggleMultiCursorModifier.ts | 12 +--- .../toggleRenderControlCharacter.ts | 6 +- .../toggleRenderWhitespace.ts | 6 +- .../electron-browser/extensionTipsService.ts | 8 +-- .../node/extensionsWorkbenchService.ts | 6 +- .../parts/files/browser/explorerViewlet.ts | 2 - .../parts/files/browser/fileActions.ts | 13 ++--- .../files/browser/views/explorerViewer.ts | 8 +-- .../preferences/browser/preferencesEditor.ts | 6 +- .../browser/preferencesRenderers.ts | 30 +++------- .../preferences/browser/preferencesService.ts | 17 +++--- .../preferences/browser/preferencesWidgets.ts | 6 +- .../parts/preferences/common/preferences.ts | 5 +- .../preferences/common/preferencesModels.ts | 2 +- .../electron-browser/task.contribution.ts | 25 +++----- .../parts/terminal/common/terminalService.ts | 2 +- .../electron-browser/terminalService.ts | 7 +-- .../electron-browser/themes.contribution.ts | 2 +- .../page/electron-browser/welcomePage.ts | 6 +- .../node/configurationEditingService.ts | 4 +- .../node/configurationService.ts | 30 ++-------- .../node/configurationEditingService.test.ts | 4 ++ .../themes/common/workbenchThemeService.ts | 2 +- .../electron-browser/workbenchThemeService.ts | 7 +-- .../api/extHostConfiguration.test.ts | 4 +- .../api/mainThreadConfiguration.test.ts | 58 +++++++++---------- 39 files changed, 153 insertions(+), 258 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 5f50cf05077..fd78d7e71a1 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -28,10 +28,10 @@ export interface IConfigurationOverrides { } export enum ConfigurationTarget { - DEFAULT = 1, - USER, + USER = 1, WORKSPACE, WORKSPACE_FOLDER, + DEFAULT, MEMORY } @@ -62,7 +62,7 @@ export interface IConfigurationService { updateValue(key: string, value: any): TPromise; updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise; updateValue(key: string, value: any, target: ConfigurationTarget): TPromise; - updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise; + updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget, donotNotifyError?: boolean): TPromise; reloadConfiguration(): TPromise; reloadConfiguration(folder: IWorkspaceFolder): TPromise; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index a7e62338321..7bfc0852a5e 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -310,12 +310,12 @@ export class Configuration { getSection(section: string = '', overrides: IConfigurationOverrides = {}): C { const configModel = this.getConsolidateConfigurationModel(overrides); - return Object.freeze(section ? configModel.getSectionContents(section) : configModel.contents); + return objects.clone(section ? configModel.getSectionContents(section) : configModel.contents); } getValue(key: string, overrides: IConfigurationOverrides = {}): any { const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); - return Object.freeze(getConfigurationValue(consolidateConfigurationModel.contents, key)); + return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); } updateValue(key: string, value: any, overrides: IConfigurationOverrides = {}): void { @@ -352,7 +352,7 @@ export class Configuration { const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration; - return Object.freeze({ + return objects.clone({ default: getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key), user: getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key), workspace: this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0, //Check on workspace exists or not because _workspaceConfiguration is never null @@ -369,12 +369,12 @@ export class Configuration { workspaceFolder: string[]; } { const folderConfigurationModel = this.getFolderConfigurationModelForResource(); - return { + return objects.clone({ default: this._defaults.keys, user: this._user.keys, workspace: this._workspaceConfiguration.keys, workspaceFolder: folderConfigurationModel ? folderConfigurationModel.keys : [] - }; + }); } private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 71f54113cfd..79d793d416c 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -11,9 +11,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @extHostNamedCustomer(MainContext.MainThreadConfiguration) export class MainThreadConfiguration implements MainThreadConfigurationShape { @@ -22,9 +22,8 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { constructor( extHostContext: IExtHostContext, - @IConfigurationEditingService private readonly _configurationEditingService: IConfigurationEditingService, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService + @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService ) { const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); @@ -47,14 +46,14 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { private writeConfiguration(target: ConfigurationTarget, key: string, value: any, resource: URI): TPromise { target = target !== null && target !== undefined ? target : this.deriveConfigurationTarget(key, resource); - return this._configurationEditingService.writeConfiguration(target, { key, value }, { donotNotifyError: true, scopes: { resource } }); + return this.configurationService.updateValue(key, value, { resource }, target, true); } private deriveConfigurationTarget(key: string, resource: URI): ConfigurationTarget { if (resource && this._workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.RESOURCE) { - return ConfigurationTarget.FOLDER; + return ConfigurationTarget.WORKSPACE_FOLDER; } } return ConfigurationTarget.WORKSPACE; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index db5a8dd1a97..d07165fce5a 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -28,8 +28,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import { ITextSource } from 'vs/editor/common/model/textSource'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IConfigurationData } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 6d3aee7186e..55677b2d360 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -11,9 +11,8 @@ import { WorkspaceConfiguration } from 'vscode'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol'; import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes'; -import { IConfigurationData } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { Configuration } from 'vs/platform/configuration/common/configurationModels'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; function lookUp(tree: any, key: string) { if (key) { @@ -72,7 +71,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { switch (arg) { case ExtHostConfigurationTarget.Global: return ConfigurationTarget.USER; case ExtHostConfigurationTarget.Workspace: return ConfigurationTarget.WORKSPACE; - case ExtHostConfigurationTarget.WorkspaceFolder: return ConfigurationTarget.FOLDER; + case ExtHostConfigurationTarget.WorkspaceFolder: return ConfigurationTarget.WORKSPACE_FOLDER; } } diff --git a/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts b/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts index bd78ed75df5..9ae30a6d59b 100644 --- a/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts +++ b/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts @@ -10,7 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; export class ToggleActivityBarVisibilityAction extends Action { @@ -24,7 +24,7 @@ export class ToggleActivityBarVisibilityAction extends Action { id: string, label: string, @IPartService private partService: IPartService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label); @@ -35,9 +35,7 @@ export class ToggleActivityBarVisibilityAction extends Action { const visibility = this.partService.isVisible(Parts.ACTIVITYBAR_PART); const newVisibilityValue = !visibility; - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ToggleActivityBarVisibilityAction.activityBarVisibleKey, value: newVisibilityValue }); - - return TPromise.as(null); + return this.configurationService.updateValue(ToggleActivityBarVisibilityAction.activityBarVisibleKey, newVisibilityValue, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/browser/actions/toggleSidebarPosition.ts b/src/vs/workbench/browser/actions/toggleSidebarPosition.ts index 6e62c166319..fc94e997424 100644 --- a/src/vs/workbench/browser/actions/toggleSidebarPosition.ts +++ b/src/vs/workbench/browser/actions/toggleSidebarPosition.ts @@ -10,8 +10,8 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IPartService, Position } from 'vs/workbench/services/part/common/partService'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export class ToggleSidebarPositionAction extends Action { @@ -24,20 +24,18 @@ export class ToggleSidebarPositionAction extends Action { id: string, label: string, @IPartService private partService: IPartService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label); - this.enabled = !!this.partService && !!this.configurationEditingService; + this.enabled = !!this.partService && !!this.configurationService; } public run(): TPromise { const position = this.partService.getSideBarPosition(); const newPositionValue = (position === Position.LEFT) ? 'right' : 'left'; - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ToggleSidebarPositionAction.sidebarPositionConfigurationKey, value: newPositionValue }); - - return TPromise.as(null); + return this.configurationService.updateValue(ToggleSidebarPositionAction.sidebarPositionConfigurationKey, newPositionValue, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts b/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts index ddaadd0e277..5949ea28756 100644 --- a/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts +++ b/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts @@ -10,7 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; export class ToggleStatusbarVisibilityAction extends Action { @@ -24,7 +24,7 @@ export class ToggleStatusbarVisibilityAction extends Action { id: string, label: string, @IPartService private partService: IPartService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label); @@ -35,9 +35,7 @@ export class ToggleStatusbarVisibilityAction extends Action { const visibility = this.partService.isVisible(Parts.STATUSBAR_PART); const newVisibilityValue = !visibility; - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ToggleStatusbarVisibilityAction.statusbarVisibleKey, value: newVisibilityValue }); - - return TPromise.as(null); + return this.configurationService.updateValue(ToggleStatusbarVisibilityAction.statusbarVisibleKey, newVisibilityValue, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index ab16b258da8..ee23ffe9df8 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -23,7 +23,6 @@ import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorIn import { IFileEditorInput, EncodingMode, IEncodingSupport, toResource, SideBySideEditorInput } from 'vs/workbench/common/editor'; import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IEditorAction, ICommonCodeEditor, EndOfLineSequence, IModel } from 'vs/editor/common/editorCommon'; import { IModelLanguageChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents'; import { TrimTrailingWhitespaceAction } from 'vs/editor/contrib/linesOperations/common/linesOperations'; @@ -56,6 +55,7 @@ import { widgetShadow, editorWidgetBackground } from 'vs/platform/theme/common/c // TODO@Sandeep layer breaker // tslint:disable-next-line:import-patterns import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; function toEditorWithEncodingSupport(input: IEditorInput): IEncodingSupport { if (input instanceof SideBySideEditorInput) { @@ -793,14 +793,12 @@ export class ChangeModeAction extends Action { @IModeService private modeService: IModeService, @IModelService private modelService: IModelService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService, @IQuickOpenService private quickOpenService: IQuickOpenService, @IPreferencesService private preferencesService: IPreferencesService, @IInstantiationService private instantiationService: IInstantiationService, @ICommandService private commandService: ICommandService, - @IUntitledEditorService private untitledEditorService: IUntitledEditorService, - @IConfigurationEditingService private configurationEditService: IConfigurationEditingService + @IUntitledEditorService private untitledEditorService: IUntitledEditorService ) { super(actionId, actionLabel); } @@ -989,8 +987,7 @@ export class ChangeModeAction extends Action { currentAssociations[associationKey] = language.id; - // Write config - this.configurationEditingService.writeConfiguration(target, { key: ChangeModeAction.FILE_ASSOCIATION_KEY, value: currentAssociations }); + this.configurationService.updateValue(ChangeModeAction.FILE_ASSOCIATION_KEY, currentAssociations, target); } }); }); @@ -1229,7 +1226,7 @@ class ScreenReaderDetectedExplanation { anchorElement: HTMLElement, @IThemeService private readonly themeService: IThemeService, @IContextViewService private readonly contextViewService: IContextViewService, - @IConfigurationEditingService private readonly configurationEditingService: IConfigurationEditingService, + @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, ) { this._isDisposed = false; this._toDispose = []; @@ -1281,20 +1278,14 @@ class ScreenReaderDetectedExplanation { const yesBtn = $('div.button', {}, nls.localize('screenReaderDetectedExplanation.answerYes', "Yes")); this._toDispose.push(addDisposableListener(yesBtn, 'click', () => { - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { - key: 'editor.accessibilitySupport', - value: 'on' - }); + this.configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER); this.contextViewService.hideContextView(); })); domNode.appendChild(yesBtn); const noBtn = $('div.button', {}, nls.localize('screenReaderDetectedExplanation.answerNo', "No")); this._toDispose.push(addDisposableListener(noBtn, 'click', () => { - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { - key: 'editor.accessibilitySupport', - value: 'off' - }); + this.configurationService.updateValue('editor.accessibilitySupport', 'off', ConfigurationTarget.USER); this.contextViewService.hideContextView(); })); domNode.appendChild(noBtn); diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 70406345142..95281cf2338 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -20,8 +20,7 @@ import errors = require('vs/base/common/errors'); import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IExtensionManagementService, LocalExtensionType, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import paths = require('vs/base/common/paths'); @@ -157,8 +156,7 @@ export class ToggleMenuBarAction extends Action { id: string, label: string, @IMessageService private messageService: IMessageService, - @IConfigurationService private configurationService: IConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label); } @@ -176,7 +174,7 @@ export class ToggleMenuBarAction extends Action { newVisibilityValue = 'default'; } - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ToggleMenuBarAction.menuBarVisibilityKey, value: newVisibilityValue }); + this.configurationService.updateValue(ToggleMenuBarAction.menuBarVisibilityKey, newVisibilityValue, ConfigurationTarget.USER); return TPromise.as(null); } @@ -202,18 +200,12 @@ export abstract class BaseZoomAction extends Action { constructor( id: string, label: string, - @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService ) { super(id, label); } protected setConfiguredZoomLevel(level: number): void { - let target = ConfigurationTarget.USER; - if (typeof this.configurationService.inspect(BaseZoomAction.SETTING_KEY).workspace === 'number') { - target = ConfigurationTarget.WORKSPACE; - } - level = Math.round(level); // when reaching smallest zoom, prevent fractional zoom levels const applyZoom = () => { @@ -225,7 +217,7 @@ export abstract class BaseZoomAction extends Action { browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false); }; - this.configurationEditingService.writeConfiguration(target, { key: BaseZoomAction.SETTING_KEY, value: level }, { donotNotifyError: true }).done(() => applyZoom(), error => applyZoom()); + this.configurationService.updateValue(BaseZoomAction.SETTING_KEY, level).done(() => applyZoom()); } } @@ -237,10 +229,9 @@ export class ZoomInAction extends BaseZoomAction { constructor( id: string, label: string, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService + @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService ) { - super(id, label, configurationService, configurationEditingService); + super(id, label, configurationService); } public run(): TPromise { @@ -258,10 +249,9 @@ export class ZoomOutAction extends BaseZoomAction { constructor( id: string, label: string, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService + @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService ) { - super(id, label, configurationService, configurationEditingService); + super(id, label, configurationService); } public run(): TPromise { @@ -279,10 +269,9 @@ export class ZoomResetAction extends BaseZoomAction { constructor( id: string, label: string, - @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService + @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService ) { - super(id, label, configurationService, configurationEditingService); + super(id, label, configurationService); } public run(): TPromise { diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index d90e9c76efc..e1dfbbe2a03 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -29,7 +29,6 @@ import { IWindowsService, IWindowService, IWindowSettings, IPath, IOpenFileReque import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ITitleService } from 'vs/workbench/services/title/common/titleService'; import { IWorkbenchThemeService, VS_HC_THEME, VS_DARK_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService'; import * as browser from 'vs/base/browser/browser'; @@ -47,6 +46,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; const TextInputActions: IAction[] = [ new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && TPromise.as(true)), @@ -81,7 +81,6 @@ export class ElectronWindow extends Themable { @ITitleService private titleService: ITitleService, @IWorkbenchThemeService protected themeService: IWorkbenchThemeService, @IMessageService private messageService: IMessageService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @ICommandService private commandService: ICommandService, @IExtensionService private extensionService: IExtensionService, @IViewletService private viewletService: IViewletService, @@ -511,7 +510,7 @@ export class ElectronWindow extends Themable { newAutoSaveValue = AutoSaveConfiguration.AFTER_DELAY; } - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ElectronWindow.AUTO_SAVE_SETTING, value: newAutoSaveValue }); + this.configurationService.updateValue(ElectronWindow.AUTO_SAVE_SETTING, newAutoSaveValue, ConfigurationTarget.USER); } public dispose(): void { diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.ts b/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.ts index ddbc5ae45e6..aaf8113fe70 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.ts @@ -25,10 +25,9 @@ import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorWidgetBackground, widgetShadow, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import * as editorOptions from 'vs/editor/common/config/editorOptions'; import * as platform from 'vs/base/common/platform'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import URI from 'vs/base/common/uri'; @@ -87,7 +86,6 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget { @IContextKeyService private _contextKeyService: IContextKeyService, @IKeybindingService private _keybindingService: IKeybindingService, @IConfigurationService private _configurationService: IConfigurationService, - @IConfigurationEditingService private _configurationEditingService: IConfigurationEditingService, @IOpenerService private _openerService: IOpenerService ) { super(); @@ -124,10 +122,7 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget { if (e.equals(KeyMod.CtrlCmd | KeyCode.KEY_E)) { alert(nls.localize('emergencyConfOn', "Now changing the setting `editor.accessibilitySupport` to 'on'.")); - this._configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { - key: 'editor.accessibilitySupport', - value: 'on' - }); + this._configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER); e.preventDefault(); e.stopPropagation(); diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/toggleMinimap.ts b/src/vs/workbench/parts/codeEditor/electron-browser/toggleMinimap.ts index 86cdf51939a..247b6b2e73b 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/toggleMinimap.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/toggleMinimap.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @editorAction export class ToggleMinimapAction extends EditorAction { @@ -22,10 +22,10 @@ export class ToggleMinimapAction extends EditorAction { } public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - const configurationEditingService = accessor.get(IConfigurationEditingService); + const configurationService = accessor.get(IConfigurationService); const newValue = !editor.getConfiguration().viewInfo.minimap.enabled; - configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'editor.minimap.enabled', value: newValue }); + configurationService.updateValue('editor.minimap.enabled', newValue, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.ts b/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.ts index 214f40e3a53..a2022660076 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.ts @@ -10,8 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export class ToggleMultiCursorModifierAction extends Action { @@ -23,21 +22,16 @@ export class ToggleMultiCursorModifierAction extends Action { constructor( id: string, label: string, - @IConfigurationService private configurationService: IConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label); - - this.enabled = !!this.configurationService && !!this.configurationEditingService; } public run(): TPromise { const editorConf = this.configurationService.getConfiguration<{ multiCursorModifier: 'ctrlCmd' | 'alt' }>('editor'); const newValue: 'ctrlCmd' | 'alt' = (editorConf.multiCursorModifier === 'ctrlCmd' ? 'alt' : 'ctrlCmd'); - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ToggleMultiCursorModifierAction.multiCursorModifierConfigurationKey, value: newValue }); - - return TPromise.as(null); + return this.configurationService.updateValue(ToggleMultiCursorModifierAction.multiCursorModifierConfigurationKey, newValue, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderControlCharacter.ts b/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderControlCharacter.ts index dc51edcbf3d..5eff950044a 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderControlCharacter.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderControlCharacter.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @editorAction export class ToggleRenderControlCharacterAction extends EditorAction { @@ -22,10 +22,10 @@ export class ToggleRenderControlCharacterAction extends EditorAction { } public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - const configurationEditingService = accessor.get(IConfigurationEditingService); + const configurationService = accessor.get(IConfigurationService); let newRenderControlCharacters = !editor.getConfiguration().viewInfo.renderControlCharacters; - configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'editor.renderControlCharacters', value: newRenderControlCharacters }); + configurationService.updateValue('editor.renderControlCharacters', newRenderControlCharacters, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderWhitespace.ts b/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderWhitespace.ts index 1ce47241da5..c95eca4cc60 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderWhitespace.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/toggleRenderWhitespace.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @editorAction export class ToggleRenderWhitespaceAction extends EditorAction { @@ -22,7 +22,7 @@ export class ToggleRenderWhitespaceAction extends EditorAction { } public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - const configurationEditingService = accessor.get(IConfigurationEditingService); + const configurationService = accessor.get(IConfigurationService); let renderWhitespace = editor.getConfiguration().viewInfo.renderWhitespace; let newRenderWhitespace: string; @@ -32,6 +32,6 @@ export class ToggleRenderWhitespaceAction extends EditorAction { newRenderWhitespace = 'none'; } - configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'editor.renderWhitespace', value: newRenderWhitespace }); + configurationService.updateValue('editor.renderWhitespace', newRenderWhitespace, ConfigurationTarget.USER); } } diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index a365c3fe77d..c6f10cffca4 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -23,8 +23,7 @@ import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace } from 'vs/platf import { Schemas } from 'vs/base/common/network'; import { IFileService } from 'vs/platform/files/common/files'; import { IExtensionsConfiguration, ConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import * as pfs from 'vs/base/node/pfs'; import * as os from 'os'; @@ -59,7 +58,6 @@ export class ExtensionTipsService implements IExtensionTipsService { @IFileService private fileService: IFileService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IConfigurationService private configurationService: IConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @IMessageService private messageService: IMessageService, @ITelemetryService private telemetryService: ITelemetryService ) { @@ -449,9 +447,7 @@ export class ExtensionTipsService implements IExtensionTipsService { } private setIgnoreRecommendationsConfig(configVal: boolean) { - let target = ConfigurationTarget.USER; - const configKey = 'extensions.ignoreRecommendations'; - this.configurationEditingService.writeConfiguration(target, { key: configKey, value: configVal }); + this.configurationService.updateValue('extensions.ignoreRecommendations', configVal, ConfigurationTarget.USER); if (configVal) { const ignoreWorkspaceRecommendationsStorageKey = 'extensionsAssistant/workspaceRecommendationsIgnore'; this.storageService.store(ignoreWorkspaceRecommendationsStorageKey, true, StorageScope.WORKSPACE); diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 91edacaad0a..b55058ebf56 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -24,9 +24,8 @@ import { } from 'vs/platform/extensionManagement/common/extensionManagement'; import { getGalleryExtensionIdFromLocal, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IWindowService } from 'vs/platform/windows/common/windows'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IChoiceService, IMessageService } from 'vs/platform/message/common/message'; import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; @@ -323,7 +322,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { @IExtensionManagementService private extensionService: IExtensionManagementService, @IExtensionGalleryService private galleryService: IExtensionGalleryService, @IConfigurationService private configurationService: IConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @ITelemetryService private telemetryService: ITelemetryService, @IMessageService private messageService: IMessageService, @IChoiceService private choiceService: IChoiceService, @@ -464,7 +462,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { if (this.isAutoUpdateEnabled === autoUpdate) { return TPromise.as(null); } - return this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'extensions.autoUpdate', value: autoUpdate }); + return this.configurationService.updateValue('extensions.autoUpdate', autoUpdate, ConfigurationTarget.USER); } private eventuallySyncWithGallery(immediate = false): void { diff --git a/src/vs/workbench/parts/files/browser/explorerViewlet.ts b/src/vs/workbench/parts/files/browser/explorerViewlet.ts index 74da9b16cd4..340a269b289 100644 --- a/src/vs/workbench/parts/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/browser/explorerViewlet.ts @@ -14,7 +14,6 @@ import { Builder } from 'vs/base/browser/builder'; import { VIEWLET_ID, ExplorerViewletVisibleContext, IFilesConfiguration, OpenEditorsVisibleContext, OpenEditorsVisibleCondition } from 'vs/workbench/parts/files/common/files'; import { PersistentViewsViewlet, ViewsViewletPanel, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ActionRunner, FileViewletState } from 'vs/workbench/parts/files/browser/views/explorerViewer'; import { ExplorerView, IExplorerViewOptions } from 'vs/workbench/parts/files/browser/views/explorerView'; import { EmptyView } from 'vs/workbench/parts/files/browser/views/emptyView'; @@ -51,7 +50,6 @@ export class ExplorerViewlet extends PersistentViewsViewlet { @IConfigurationService private configurationService: IConfigurationService, @IInstantiationService protected instantiationService: IInstantiationService, @IContextKeyService contextKeyService: IContextKeyService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @IThemeService themeService: IThemeService, @IContextMenuService contextMenuService: IContextMenuService, @IExtensionService extensionService: IExtensionService diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index 5204850eaee..c56c5a48fa7 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -49,8 +49,7 @@ import { withFocusedFilesExplorer, revealInOSCommand, revealInExplorerCommand, c import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { once } from 'vs/base/common/event'; export interface IEditableData { @@ -641,8 +640,7 @@ export class BaseDeleteFileAction extends BaseFileAction { @IFileService fileService: IFileService, @IMessageService messageService: IMessageService, @ITextFileService textFileService: ITextFileService, - @IConfigurationService private configurationService: IConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label, fileService, messageService, textFileService); @@ -746,7 +744,7 @@ export class BaseDeleteFileAction extends BaseFileAction { // Check for confirmation checkbox let updateConfirmSettingsPromise: TPromise = TPromise.as(void 0); if (confirmation.checkboxChecked === true) { - updateConfirmSettingsPromise = this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: BaseDeleteFileAction.CONFIRM_DELETE_SETTING_KEY, value: false }); + updateConfirmSettingsPromise = this.configurationService.updateValue(BaseDeleteFileAction.CONFIRM_DELETE_SETTING_KEY, false, ConfigurationTarget.USER); } return updateConfirmSettingsPromise.then(() => { @@ -792,10 +790,9 @@ export class MoveFileToTrashAction extends BaseDeleteFileAction { @IFileService fileService: IFileService, @IMessageService messageService: IMessageService, @ITextFileService textFileService: ITextFileService, - @IConfigurationService configurationService: IConfigurationService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService + @IConfigurationService configurationService: IConfigurationService ) { - super(MoveFileToTrashAction.ID, nls.localize('delete', "Delete"), tree, element, true, fileService, messageService, textFileService, configurationService, configurationEditingService); + super(MoveFileToTrashAction.ID, nls.localize('delete', "Delete"), tree, element, true, fileService, messageService, textFileService, configurationService); } } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 4878cedef0b..a095ecd2a5a 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -37,7 +37,7 @@ import { DragMouseEvent, IMouseEvent } from 'vs/base/browser/mouseEvent'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -57,7 +57,6 @@ import { distinct } from 'vs/base/common/arrays'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { getPathLabel } from 'vs/base/common/labels'; import { extractResources } from 'vs/base/browser/dnd'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; export class FileDataSource implements IDataSource { constructor( @@ -746,8 +745,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { @IBackupFileService private backupFileService: IBackupFileService, @IWindowService private windowService: IWindowService, @IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService, - @IEnvironmentService private environmentService: IEnvironmentService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService + @IEnvironmentService private environmentService: IEnvironmentService ) { super(stat => this.statToResource(stat)); @@ -967,7 +965,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // Check for confirmation checkbox let updateConfirmSettingsPromise: TPromise = TPromise.as(void 0); if (confirmation.checkboxChecked === true) { - updateConfirmSettingsPromise = this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: FileDragAndDrop.CONFIRM_DND_SETTING_KEY, value: false }); + updateConfirmSettingsPromise = this.configurationService.updateValue(FileDragAndDrop.CONFIRM_DND_SETTING_KEY, false, ConfigurationTarget.USER); } return updateConfirmSettingsPromise.then(() => { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index b65862ab507..44875020629 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -39,7 +39,6 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { VSash } from 'vs/base/browser/ui/sash/sash'; import { Widget } from 'vs/base/browser/ui/widget'; @@ -59,6 +58,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { MessageController } from 'vs/editor/contrib/message/messageController'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export class PreferencesEditorInput extends SideBySideEditorInput { public static ID: string = 'workbench.editorinputs.preferencesEditorInput'; @@ -248,7 +248,7 @@ export class PreferencesEditor extends BaseEditor { } if (this.workspaceContextService.getWorkspaceFolder(resource)) { - return ConfigurationTarget.FOLDER; + return ConfigurationTarget.WORKSPACE_FOLDER; } return null; @@ -918,7 +918,7 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl return this.instantiationService.createInstance(UserSettingsRenderer, this.editor, settingsModel, defaultSettingsModel); case ConfigurationTarget.WORKSPACE: return this.instantiationService.createInstance(WorkspaceSettingsRenderer, this.editor, settingsModel, defaultSettingsModel); - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: return this.instantiationService.createInstance(FolderSettingsRenderer, this.editor, settingsModel, defaultSettingsModel); } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 1d69bbae93b..02c4e1a85c6 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -22,7 +22,6 @@ import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/bro import { SettingsGroupTitleWidget, EditPreferenceWidget, SettingsHeaderWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RangeHighlightDecorations } from 'vs/workbench/common/editor/rangeDecorations'; -import { IConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IMarkerService, IMarkerData } from 'vs/platform/markers/common/markers'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; @@ -32,7 +31,7 @@ import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorE import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { MarkdownString } from 'vs/base/common/htmlContent'; -import { overrideIdentifierFromKey } from 'vs/platform/configuration/common/configuration'; +import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export interface IPreferencesRenderer extends IDisposable { preferencesModel: IPreferencesEditorModel; @@ -72,7 +71,7 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend @IPreferencesService protected preferencesService: IPreferencesService, @ITelemetryService private telemetryService: ITelemetryService, @ITextFileService private textFileService: ITextFileService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, + @IConfigurationService private configurationService: IConfigurationService, @IMessageService private messageService: IMessageService, @IInstantiationService protected instantiationService: IInstantiationService ) { @@ -116,19 +115,8 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend this.telemetryService.publicLog('defaultSettingsActions.copySetting', { userConfigurationKeys: [key] }); const overrideIdentifier = source.overrideOf ? overrideIdentifierFromKey(source.overrideOf.key) : null; const resource = this.preferencesModel.uri; - this.configurationEditingService.writeConfiguration(this.preferencesModel.configurationTarget, { key, value }, { donotSave: this.textFileService.isDirty(resource), donotNotifyError: true, scopes: { overrideIdentifier, resource } }) - .then(() => this.onSettingUpdated(source), error => { - this.messageService.show(Severity.Error, this.toErrorMessage(error, this.preferencesModel.configurationTarget)); - }); - } - - private toErrorMessage(error: ConfigurationEditingError, target: ConfigurationTarget): string { - switch (error.code) { - case ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION: { - return nls.localize('errorInvalidConfiguration', "Unable to write into settings. Correct errors/warnings in the file and try again."); - }; - } - return error.message; + this.configurationService.updateValue(key, value, { overrideIdentifier, resource }, this.preferencesModel.configurationTarget) + .then(() => this.onSettingUpdated(source)); } private onModelChanged(): void { @@ -192,11 +180,11 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I @IPreferencesService preferencesService: IPreferencesService, @ITelemetryService telemetryService: ITelemetryService, @ITextFileService textFileService: ITextFileService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService, + @IConfigurationService configurationService: IConfigurationService, @IMessageService messageService: IMessageService, @IInstantiationService instantiationService: IInstantiationService ) { - super(editor, preferencesModel, associatedPreferencesModel, preferencesService, telemetryService, textFileService, configurationEditingService, messageService, instantiationService); + super(editor, preferencesModel, associatedPreferencesModel, preferencesService, telemetryService, textFileService, configurationService, messageService, instantiationService); this.untrustedSettingRenderer = this._register(instantiationService.createInstance(UnsupportedWorkspaceSettingsRenderer, editor, preferencesModel)); this.workspaceConfigurationRenderer = this._register(instantiationService.createInstance(WorkspaceConfigurationRenderer, editor, preferencesModel)); } @@ -220,11 +208,11 @@ export class FolderSettingsRenderer extends UserSettingsRenderer implements IPre @IPreferencesService preferencesService: IPreferencesService, @ITelemetryService telemetryService: ITelemetryService, @ITextFileService textFileService: ITextFileService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService, + @IConfigurationService configurationService: IConfigurationService, @IMessageService messageService: IMessageService, @IInstantiationService instantiationService: IInstantiationService ) { - super(editor, preferencesModel, associatedPreferencesModel, preferencesService, telemetryService, textFileService, configurationEditingService, messageService, instantiationService); + super(editor, preferencesModel, associatedPreferencesModel, preferencesService, telemetryService, textFileService, configurationService, messageService, instantiationService); this.unsupportedWorkbenchSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedWorkbenchSettingsRenderer, editor, preferencesModel)); } @@ -809,7 +797,7 @@ class EditSettingRenderer extends Disposable { return true; } if (configurationNode.type === 'boolean' || configurationNode.enum) { - if ((this.masterSettingsModel).configurationTarget !== ConfigurationTarget.FOLDER) { + if ((this.masterSettingsModel).configurationTarget !== ConfigurationTarget.WORKSPACE_FOLDER) { return true; } if (configurationNode.scope === ConfigurationScope.RESOURCE) { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index c3f74852cee..fdf08f805c2 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -26,7 +26,6 @@ import { IMessageService, Severity, IChoiceService } from 'vs/platform/message/c import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel, defaultKeybindingsContents, WorkspaceConfigModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -40,6 +39,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; const emptyEditableSettingsContent = '{\n}'; @@ -66,7 +66,6 @@ export class PreferencesService extends Disposable implements IPreferencesServic @IEnvironmentService private environmentService: IEnvironmentService, @ITelemetryService private telemetryService: ITelemetryService, @ITextModelService private textModelResolverService: ITextModelService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @IExtensionService private extensionService: IExtensionService, @IKeybindingService keybindingService: IKeybindingService, @IModelService private modelService: IModelService, @@ -107,7 +106,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } getFolderSettingsResource(resource: URI): URI { - return this.getEditableSettingsURI(ConfigurationTarget.FOLDER, resource); + return this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, resource); } resolveContent(uri: URI): TPromise { @@ -170,7 +169,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - return this.createEditableSettingsEditorModel(ConfigurationTarget.FOLDER, uri); + return this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE_FOLDER, uri); } return TPromise.wrap>(null); @@ -189,7 +188,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } openFolderSettings(folder: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { - return this.doOpenSettings(ConfigurationTarget.FOLDER, this.getEditableSettingsURI(ConfigurationTarget.FOLDER, folder), options, position); + return this.doOpenSettings(ConfigurationTarget.WORKSPACE_FOLDER, this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, folder), options, position); } switchSettings(target: ConfigurationTarget, resource: URI): TPromise { @@ -270,7 +269,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private getDefaultSettingsResource(configurationTarget: ConfigurationTarget): URI { - if (configurationTarget === ConfigurationTarget.FOLDER) { + if (configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) { return this.defaultResourceSettingsResource; } return this.defaultSettingsResource; @@ -278,7 +277,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic private getPreferencesEditorInputName(target: ConfigurationTarget, resource: URI): string { const name = getSettingsTargetName(target, resource, this.contextService); - return target === ConfigurationTarget.FOLDER ? nls.localize('folderSettingsName', "{0} (Folder Settings)", name) : name; + return target === ConfigurationTarget.WORKSPACE_FOLDER ? nls.localize('folderSettingsName', "{0} (Folder Settings)", name) : name; } private getOrCreateEditableSettingsEditorInput(target: ConfigurationTarget, resource: URI): TPromise { @@ -322,7 +321,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } const workspace = this.contextService.getWorkspace(); return workspace.configuration || workspace.folders[0].toResource(FOLDER_SETTINGS_PATH); - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: const folder = this.contextService.getWorkspaceFolder(resource); return folder ? folder.toResource(FOLDER_SETTINGS_PATH) : null; } @@ -389,7 +388,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } return { lineNumber: setting.valueRange.startLineNumber, column: setting.valueRange.startColumn + 1 }; } - return this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: languageKey, value: {} }, { donotSave: true }) + return this.configurationService.updateValue(languageKey, {}, ConfigurationTarget.USER) .then(() => { setting = settingsModel.getPreference(languageKey); let content = eol + this.spaces(2, configuration) + eol + this.spaces(1, configuration); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index f2df5ec870c..81cc7dbdf4f 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -32,9 +32,9 @@ import { ISelectBoxStyles, defaultStyles } from 'vs/base/browser/ui/selectBox/se import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { Color } from 'vs/base/common/color'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { MarkdownString } from 'vs/base/common/htmlContent'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export class SettingsHeaderWidget extends Widget implements IViewZone { @@ -313,7 +313,7 @@ export class SettingsTargetsWidget extends Widget { private updateLabel(): void { this.targetLabel.textContent = getSettingsTargetName(this._configuartionTarget, this._uri, this.workspaceContextService); - const details = ConfigurationTarget.FOLDER === this._configuartionTarget ? localize('folderSettingsDetails', "Folder Settings") : ''; + const details = ConfigurationTarget.WORKSPACE_FOLDER === this._configuartionTarget ? localize('folderSettingsDetails', "Folder Settings") : ''; this.targetDetails.textContent = details; DOM.toggleClass(this.targetDetails, 'empty', !details); } @@ -358,7 +358,7 @@ export class SettingsTargetsWidget extends Widget { actions.push(...workspaceFolders.map((folder, index) => { return { id: 'folderSettingsTarget' + index, - label: getSettingsTargetName(ConfigurationTarget.FOLDER, folder.uri, this.workspaceContextService), + label: getSettingsTargetName(ConfigurationTarget.WORKSPACE_FOLDER, folder.uri, this.workspaceContextService), checked: this._uri.toString() === folder.uri.toString(), enabled: true, run: () => this.onTargetClicked(folder.uri) diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index d75d4737b73..4bd6f7acdef 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -11,9 +11,9 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IEditor, Position, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IKeybindingItemEntry } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel'; import { IRange } from 'vs/editor/common/core/range'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { join } from 'vs/base/common/paths'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export interface ISettingsGroup { id: string; @@ -107,10 +107,11 @@ export function getSettingsTargetName(target: ConfigurationTarget, resource: URI return localize('userSettingsTarget', "User Settings"); case ConfigurationTarget.WORKSPACE: return localize('workspaceSettingsTarget', "Workspace Settings"); - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: const folder = workspaceContextService.getWorkspaceFolder(resource); return folder ? folder.name : ''; } + return ''; } export const CONTEXT_SETTINGS_EDITOR = new RawContextKey('inSettingsEditor', false); diff --git a/src/vs/workbench/parts/preferences/common/preferencesModels.ts b/src/vs/workbench/parts/preferences/common/preferencesModels.ts index f17231a589b..1233bd69199 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesModels.ts @@ -18,7 +18,6 @@ import { EditorModel } from 'vs/workbench/common/editor'; import { IConfigurationNode, IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN, IConfigurationPropertySchema, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { ISettingsEditorModel, IKeybindingsEditorModel, ISettingsGroup, ISetting, IFilterResult, ISettingsSection } from 'vs/workbench/parts/preferences/common/preferences'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IMatch, or, matchesContiguousSubString, matchesPrefix, matchesCamelCase, matchesWords } from 'vs/base/common/filters'; import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; import { IRange } from 'vs/editor/common/core/range'; @@ -26,6 +25,7 @@ import { ITextFileService, StateChange } from 'vs/workbench/services/textfile/co import { TPromise } from 'vs/base/common/winjs.base'; import { Queue } from 'vs/base/common/async'; import { IFileService } from 'vs/platform/files/common/files'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; class SettingMatches { diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 69ae1d21ee8..3ccba8cd491 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -35,7 +35,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IMessageService, IChoiceService } from 'vs/platform/message/common/message'; import { IMarkerService, MarkerStatistics } from 'vs/platform/markers/common/markers'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -63,7 +63,6 @@ import Constants from 'vs/workbench/parts/markers/common/constants'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; -import { IConfigurationEditingService, ConfigurationTarget, IConfigurationValue } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -551,7 +550,6 @@ class TaskService extends EventEmitter implements ITaskService { private modeService: IModeService; private configurationService: IConfigurationService; - private configurationEditingService: IConfigurationEditingService; private markerService: IMarkerService; private outputService: IOutputService; private messageService: IMessageService; @@ -582,7 +580,6 @@ class TaskService extends EventEmitter implements ITaskService { private _outputChannel: IOutputChannel; constructor( @IModeService modeService: IModeService, @IConfigurationService configurationService: IConfigurationService, - @IConfigurationEditingService configurationEditingService: IConfigurationEditingService, @IMarkerService markerService: IMarkerService, @IOutputService outputService: IOutputService, @IMessageService messageService: IMessageService, @IChoiceService choiceService: IChoiceService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, @@ -604,7 +601,6 @@ class TaskService extends EventEmitter implements ITaskService { super(); this.modeService = modeService; this.configurationService = configurationService; - this.configurationEditingService = configurationEditingService; this.markerService = markerService; this.outputService = outputService; this.messageService = messageService; @@ -1108,32 +1104,25 @@ class TaskService extends EventEmitter implements ITaskService { } promise = this.fileService.createFile(workspaceFolder.toResource('.vscode/tasks.json'), content).then(() => { }); } else { - let value: IConfigurationValue = { key: undefined, value: undefined }; // We have a global task configuration if (index === -1) { if (properties.problemMatcher !== void 0) { fileConfig.problemMatcher = properties.problemMatcher; - value.key = 'tasks.problemMatchers'; - value.value = fileConfig.problemMatcher; - promise = this.writeConfiguration(workspaceFolder, value); + promise = this.writeConfiguration(workspaceFolder, 'tasks.problemMatchers', fileConfig.problemMatcher); } else if (properties.group !== void 0) { fileConfig.group = properties.group; - value.key = 'tasks.group'; - value.value = fileConfig.group; - promise = this.writeConfiguration(workspaceFolder, value); + promise = this.writeConfiguration(workspaceFolder, 'tasks.group', fileConfig.group); } } else { if (!Array.isArray(fileConfig.tasks)) { fileConfig.tasks = []; } - value.key = 'tasks.tasks'; - value.value = fileConfig.tasks; if (index === void 0) { fileConfig.tasks.push(toCustomize); } else { fileConfig.tasks[index] = toCustomize; } - promise = this.writeConfiguration(workspaceFolder, value); + promise = this.writeConfiguration(workspaceFolder, 'tasks.tasks', fileConfig.tasks); } }; if (!promise) { @@ -1162,11 +1151,11 @@ class TaskService extends EventEmitter implements ITaskService { }); } - private writeConfiguration(workspaceFolder: IWorkspaceFolder, value: IConfigurationValue): TPromise { + private writeConfiguration(workspaceFolder: IWorkspaceFolder, key: string, value: any): TPromise { if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { - return this.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, value); + return this.configurationService.updateValue(key, value, { resource: workspaceFolder.uri }, ConfigurationTarget.WORKSPACE); } else if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - return this.configurationEditingService.writeConfiguration(ConfigurationTarget.FOLDER, value, { scopes: { resource: workspaceFolder.uri } }); + return this.configurationService.updateValue(key, value, { resource: workspaceFolder.uri }, ConfigurationTarget.WORKSPACE_FOLDER); } else { return undefined; } diff --git a/src/vs/workbench/parts/terminal/common/terminalService.ts b/src/vs/workbench/parts/terminal/common/terminalService.ts index 305ac98c424..5ccb2a29e65 100644 --- a/src/vs/workbench/parts/terminal/common/terminalService.ts +++ b/src/vs/workbench/parts/terminal/common/terminalService.ts @@ -43,7 +43,7 @@ export abstract class TerminalService implements ITerminalService { constructor( @IContextKeyService private _contextKeyService: IContextKeyService, - @IConfigurationService private _configurationService: IConfigurationService, + @IConfigurationService protected _configurationService: IConfigurationService, @IPanelService protected _panelService: IPanelService, @IPartService private _partService: IPartService, @ILifecycleService lifecycleService: ILifecycleService diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index 512c65ed2d4..66d5340d584 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -11,8 +11,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IQuickOpenService, IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal'; import { TerminalService as AbstractTerminalService } from 'vs/workbench/parts/terminal/common/terminalService'; @@ -39,7 +38,6 @@ export class TerminalService extends AbstractTerminalService implements ITermina @IInstantiationService private _instantiationService: IInstantiationService, @IWindowService private _windowService: IWindowService, @IQuickOpenService private _quickOpenService: IQuickOpenService, - @IConfigurationEditingService private _configurationEditingService: IConfigurationEditingService, @IChoiceService private _choiceService: IChoiceService, @IStorageService private _storageService: IStorageService, @IMessageService private _messageService: IMessageService @@ -163,8 +161,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina return null; } const shell = value.description; - const configChange = { key: 'terminal.integrated.shell.windows', value: shell }; - return this._configurationEditingService.writeConfiguration(ConfigurationTarget.USER, configChange).then(() => shell); + return this._configurationService.updateValue('terminal.integrated.shell.windows', shell, ConfigurationTarget.USER).then(() => shell); }); }); } diff --git a/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts b/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts index 10069d1f991..d8f6bebd750 100644 --- a/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts +++ b/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts @@ -20,11 +20,11 @@ import { VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/parts/extensions/co import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { Delayer } from 'vs/base/common/async'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IColorRegistry, Extensions as ColorRegistryExtensions } from 'vs/platform/theme/common/colorRegistry'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Color } from 'vs/base/common/color'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export class SelectColorThemeAction extends Action { diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index c54020a8d3f..dff17826c3b 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -19,8 +19,7 @@ import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -237,7 +236,6 @@ class WelcomePage { @IWindowsService private windowsService: IWindowsService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IConfigurationService private configurationService: IConfigurationService, - @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService, @IEnvironmentService private environmentService: IEnvironmentService, @IMessageService private messageService: IMessageService, @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, @@ -279,7 +277,7 @@ class WelcomePage { showOnStartup.setAttribute('checked', 'checked'); } showOnStartup.addEventListener('click', e => { - this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: configurationKey, value: showOnStartup.checked ? 'welcomePage' : 'newUntitledFile' }); + this.configurationService.updateValue(configurationKey, showOnStartup.checked ? 'welcomePage' : 'newUntitledFile', ConfigurationTarget.USER); }); recentlyOpened.then(({ workspaces }) => { diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index d13b326bfc2..b264dbd9662 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -94,9 +94,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService private writeToBuffer(model: editorCommon.IModel, operation: IConfigurationEditOperation, save: boolean): TPromise { const edit = this.getEdits(model, operation)[0]; if (this.applyEditsToBuffer(edit, model) && save) { - return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }) - // Reload the configuration so that we make sure all parties are updated - .then(() => this.configurationService.reloadConfiguration()); + return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ }); } return TPromise.as(null); } diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 5c83bdddbbb..76c93c968ee 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -150,11 +150,11 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise updateValue(key: string, value: any, target: ConfigurationTarget): TPromise updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise - updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { + updateValue(key: string, value: any, arg3?: any, arg4?: any, donotNotifyError?: any): TPromise { assert.ok(this.configurationEditingService, 'Workbench is not initialized yet'); const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0; const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3); - return target ? this.writeConfigurationValue(key, value, target, overrides) + return target ? this.writeConfigurationValue(key, value, target, overrides, donotNotifyError) : TPromise.as(null); } @@ -463,23 +463,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat })]); } - private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides): TPromise { + private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides, donotNotifyError: boolean): TPromise { if (target === ConfigurationTarget.DEFAULT) { return TPromise.wrapError(new Error('Invalid configuration target')); } - let currentTargetValue = this.getTargetValue(key, target, overrides); - if (equals(currentTargetValue, value)) { - return TPromise.as(null); - } - if (target === ConfigurationTarget.MEMORY) { this._configuration.updateValue(key, value, overrides); this.triggerConfigurationChange(new ConfigurationChangeEvent().change(overrides.overrideIdentifier ? [keyFromOverrideIdentifier(overrides.overrideIdentifier)] : [key], overrides.resource), target); return TPromise.as(null); } - return this.configurationEditingService.writeConfiguration(this.toEditableConfigurationTarget(target), { key, value }, { scopes: overrides }) + return this.configurationEditingService.writeConfiguration(this.toEditableConfigurationTarget(target), { key, value }, { scopes: overrides, donotNotifyError }) .then(() => { switch (target) { case ConfigurationTarget.USER: @@ -543,23 +538,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } } - private getTargetValue(key: string, target: ConfigurationTarget, overrides?: IConfigurationOverrides): any { - const inspect = this.inspect(key, overrides); - switch (target) { - case ConfigurationTarget.DEFAULT: - return inspect.default; - case ConfigurationTarget.USER: - return inspect.user; - case ConfigurationTarget.WORKSPACE: - return inspect.workspace; - case ConfigurationTarget.WORKSPACE_FOLDER: - return inspect.workspaceFolder; - case ConfigurationTarget.MEMORY: - return inspect.memory; - } - return void 0; - } - private getTargetConfiguration(target: ConfigurationTarget): any { switch (target) { case ConfigurationTarget.DEFAULT: diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index b486834f14e..ca8bf742618 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -224,6 +224,7 @@ suite('ConfigurationEditingService', () => { test('write one setting - empty file', () => { return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }) + .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); const parsed = json.parse(contents); @@ -235,6 +236,7 @@ suite('ConfigurationEditingService', () => { test('write one setting - existing file', () => { fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }'); return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }) + .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); const parsed = json.parse(contents); @@ -249,6 +251,7 @@ suite('ConfigurationEditingService', () => { test('write workspace standalone setting - empty file', () => { return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' }) + .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); const contents = fs.readFileSync(target).toString('utf8'); @@ -263,6 +266,7 @@ suite('ConfigurationEditingService', () => { const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']); fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }'); return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'launch.service.testSetting', value: 'value' }) + .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const contents = fs.readFileSync(target).toString('utf8'); const parsed = json.parse(contents); diff --git a/src/vs/workbench/services/themes/common/workbenchThemeService.ts b/src/vs/workbench/services/themes/common/workbenchThemeService.ts index 2334ac25ae4..f8f97e35a74 100644 --- a/src/vs/workbench/services/themes/common/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/common/workbenchThemeService.ts @@ -7,9 +7,9 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; import Event from 'vs/base/common/event'; -import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { Color } from 'vs/base/common/color'; import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; export const IWorkbenchThemeService = createDecorator('themeService'); diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 233dab9d10f..702a85b0baf 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -14,8 +14,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Registry } from 'vs/platform/registry/common/platform'; import errors = require('vs/base/common/errors'); -import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IMessageService } from 'vs/platform/message/common/message'; @@ -507,7 +506,7 @@ colorThemeSchema.register(); fileIconThemeSchema.register(); class ConfigurationWriter { - constructor( @IConfigurationService private configurationService: IConfigurationService, @IConfigurationEditingService private configurationEditingService: IConfigurationEditingService) { + constructor( @IConfigurationService private configurationService: IConfigurationService) { } public writeConfiguration(key: string, value: any, settingsTarget: ConfigurationTarget): TPromise { @@ -526,7 +525,7 @@ class ConfigurationWriter { return TPromise.as(null); // nothing to do } } - return this.configurationEditingService.writeConfiguration(settingsTarget, { key, value }); + return this.configurationService.updateValue(key, value, settingsTarget); } } diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index 54fa31a10d4..098ad1ccde8 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -11,11 +11,11 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; import { MainThreadConfigurationShape } from 'vs/workbench/api/node/extHost.protocol'; import { TPromise } from 'vs/base/common/winjs.base'; -import { ConfigurationTarget, ConfigurationEditingErrorCode, ConfigurationEditingError } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { TestThreadService } from './testThreadService'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; suite('ExtHostConfiguration', function () { @@ -394,7 +394,7 @@ suite('ExtHostConfiguration', function () { const shape = new class extends mock() { $updateConfigurationOption(target: ConfigurationTarget, key: string, value: any): TPromise { - return TPromise.wrapError(new ConfigurationEditingError('Unknown Key', ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY)); // something !== OK + return TPromise.wrapError(new Error('Unknown Key')); // something !== OK } }; diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts index 425dd180872..5cd09140d48 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts @@ -13,13 +13,11 @@ import { Extensions, IConfigurationRegistry, ConfigurationScope } from 'vs/platf import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { MainThreadConfiguration } from 'vs/workbench/api/electron-browser/mainThreadConfiguration'; -import { ConfigurationTarget, IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { OneGetThreadService } from './testThreadService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; -suite('ExtHostConfiguration', function () { +suite('MainThreadConfiguration', function () { let instantiationService: TestInstantiationService; let target: sinon.SinonSpy; @@ -47,12 +45,12 @@ suite('ExtHostConfiguration', function () { }); setup(() => { - instantiationService = new TestInstantiationService(); - instantiationService.stub(IConfigurationService, new TestConfigurationService()); - target = sinon.spy(); - instantiationService.stub(IConfigurationEditingService, ConfigurationEditingService); - instantiationService.stub(IConfigurationEditingService, 'writeConfiguration', target); + + instantiationService = new TestInstantiationService(); + instantiationService.stub(IConfigurationService, WorkspaceService); + instantiationService.stub(IConfigurationService, 'onDidUpdateConfiguration', sinon.mock()); + instantiationService.stub(IConfigurationService, 'updateValue', target); }); test('update resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { @@ -61,7 +59,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { @@ -70,7 +68,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { @@ -79,7 +77,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { @@ -88,7 +86,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () { @@ -97,7 +95,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { @@ -106,7 +104,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { @@ -115,7 +113,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update resource configuration without configuration target defaults to folder', function () { @@ -124,7 +122,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.FOLDER, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE_FOLDER, target.args[0][3]); }); test('update configuration with user configuration target', function () { @@ -133,7 +131,7 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(ConfigurationTarget.USER, 'extHostConfiguration.window', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.USER, target.args[0][0]); + assert.equal(ConfigurationTarget.USER, target.args[0][3]); }); test('update configuration with workspace configuration target', function () { @@ -142,16 +140,16 @@ suite('ExtHostConfiguration', function () { testObject.$updateConfigurationOption(ConfigurationTarget.WORKSPACE, 'extHostConfiguration.window', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('update configuration with folder configuration target', function () { instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); - testObject.$updateConfigurationOption(ConfigurationTarget.FOLDER, 'extHostConfiguration.window', 'value', URI.file('abc')); + testObject.$updateConfigurationOption(ConfigurationTarget.WORKSPACE_FOLDER, 'extHostConfiguration.window', 'value', URI.file('abc')); - assert.equal(ConfigurationTarget.FOLDER, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE_FOLDER, target.args[0][3]); }); test('remove resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { @@ -160,7 +158,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { @@ -169,7 +167,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { @@ -178,7 +176,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { @@ -187,7 +185,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () { @@ -196,7 +194,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { @@ -205,7 +203,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc')); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { @@ -214,7 +212,7 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null); - assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE, target.args[0][3]); }); test('remove configuration without configuration target defaults to folder', function () { @@ -223,6 +221,6 @@ suite('ExtHostConfiguration', function () { testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc')); - assert.equal(ConfigurationTarget.FOLDER, target.args[0][0]); + assert.equal(ConfigurationTarget.WORKSPACE_FOLDER, target.args[0][3]); }); }); From fe37067d31a50799274c6fe392bf7fe7c410f3f6 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 16 Oct 2017 23:07:05 +0200 Subject: [PATCH 152/394] Clean up - Remove configuration target in configuration editing service - Remove configuration editing service --- .../workbench/electron-browser/workbench.ts | 7 -- .../common/configurationEditing.ts | 104 ------------------ .../node/configurationEditingService.ts | 84 ++++++++++++-- .../node/configurationService.ts | 18 +-- .../node/configurationEditingService.test.ts | 5 +- 5 files changed, 78 insertions(+), 140 deletions(-) delete mode 100644 src/vs/workbench/services/configuration/common/configurationEditing.ts diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 6f009ebb6d6..8f5e5fbe60d 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -46,8 +46,6 @@ import { ContextMenuService } from 'vs/workbench/services/contextview/electron-b import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configurationService'; -import { IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; @@ -177,7 +175,6 @@ export class Workbench implements IPartService { private contextKeyService: IContextKeyService; private keybindingService: IKeybindingService; private backupFileService: IBackupFileService; - private configurationEditingService: IConfigurationEditingService; private fileService: IFileService; private titlebarPart: TitlebarPart; private activitybarPart: ActivitybarPart; @@ -597,10 +594,6 @@ export class Workbench implements IPartService { const jsonEditingService = this.instantiationService.createInstance(JSONEditingService); serviceCollection.set(IJSONEditingService, jsonEditingService); - // Configuration Editing - this.configurationEditingService = this.instantiationService.createInstance(ConfigurationEditingService); - serviceCollection.set(IConfigurationEditingService, this.configurationEditingService); - // Workspace Editing serviceCollection.set(IWorkspaceEditingService, new SyncDescriptor(WorkspaceEditingService)); diff --git a/src/vs/workbench/services/configuration/common/configurationEditing.ts b/src/vs/workbench/services/configuration/common/configurationEditing.ts deleted file mode 100644 index 5cd14ca3229..00000000000 --- a/src/vs/workbench/services/configuration/common/configurationEditing.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { TPromise } from 'vs/base/common/winjs.base'; -import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; - -export const IConfigurationEditingService = createDecorator('configurationEditingService'); - -export enum ConfigurationEditingErrorCode { - - /** - * Error when trying to write a configuration key that is not registered. - */ - ERROR_UNKNOWN_KEY, - - /** - * Error when trying to write an invalid folder configuration key to folder settings. - */ - ERROR_INVALID_FOLDER_CONFIGURATION, - - /** - * Error when trying to write to user target but not supported for provided key. - */ - ERROR_INVALID_USER_TARGET, - - /** - * Error when trying to write a configuration key to folder target - */ - ERROR_INVALID_FOLDER_TARGET, - - /** - * Error when trying to write to the workspace configuration without having a workspace opened. - */ - ERROR_NO_WORKSPACE_OPENED, - - /** - * Error when trying to write and save to the configuration file while it is dirty in the editor. - */ - ERROR_CONFIGURATION_FILE_DIRTY, - - /** - * Error when trying to write to a configuration file that contains JSON errors. - */ - ERROR_INVALID_CONFIGURATION -} - -export class ConfigurationEditingError extends Error { - constructor(message: string, public code: ConfigurationEditingErrorCode) { - super(message); - } -} - -export enum ConfigurationTarget { - - /** - * Targets the user configuration file for writing. - */ - USER, - - /** - * Targets the workspace configuration file for writing. This only works if a workspace is opened. - */ - WORKSPACE, - - /** - * Targets the folder configuration file for writing. This only works if a workspace is opened. - */ - FOLDER -} - -export interface IConfigurationValue { - key: string; - value: any; -} - -export interface IConfigurationEditingOptions { - /** - * If `true`, do not saves the configuration. Default is `false`. - */ - donotSave?: boolean; - /** - * If `true`, do not notifies the error to user by showing the message box. Default is `false`. - */ - donotNotifyError?: boolean; - /** - * Scope of configuration to be written into. - */ - scopes?: IConfigurationOverrides; -} - -export interface IConfigurationEditingService { - - _serviceBrand: ServiceIdentifier; - - /** - * Allows to write the configuration value to either the user or workspace configuration file and save it if asked to save. - * The returned promise will be in error state in any of the error cases from [ConfigurationEditingErrorCode](#ConfigurationEditingErrorCode) - */ - writeConfiguration(target: ConfigurationTarget, value: IConfigurationValue, options?: IConfigurationEditingOptions): TPromise; -} \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index b264dbd9662..e4b1cd4e7a0 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -23,16 +23,79 @@ import { Selection } from 'vs/editor/common/core/selection'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; -import { ConfigurationTarget, ConfigurationEditingErrorCode, ConfigurationEditingError, IConfigurationValue, IConfigurationEditingOptions, IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IChoiceService, IMessageService, Severity } from 'vs/platform/message/common/message'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +export enum ConfigurationEditingErrorCode { + + /** + * Error when trying to write a configuration key that is not registered. + */ + ERROR_UNKNOWN_KEY, + + /** + * Error when trying to write an invalid folder configuration key to folder settings. + */ + ERROR_INVALID_FOLDER_CONFIGURATION, + + /** + * Error when trying to write to user target but not supported for provided key. + */ + ERROR_INVALID_USER_TARGET, + + /** + * Error when trying to write a configuration key to folder target + */ + ERROR_INVALID_FOLDER_TARGET, + + /** + * Error when trying to write to the workspace configuration without having a workspace opened. + */ + ERROR_NO_WORKSPACE_OPENED, + + /** + * Error when trying to write and save to the configuration file while it is dirty in the editor. + */ + ERROR_CONFIGURATION_FILE_DIRTY, + + /** + * Error when trying to write to a configuration file that contains JSON errors. + */ + ERROR_INVALID_CONFIGURATION +} + +export class ConfigurationEditingError extends Error { + constructor(message: string, public code: ConfigurationEditingErrorCode) { + super(message); + } +} + +export interface IConfigurationValue { + key: string; + value: any; +} + +export interface IConfigurationEditingOptions { + /** + * If `true`, do not saves the configuration. Default is `false`. + */ + donotSave?: boolean; + /** + * If `true`, do not notifies the error to user by showing the message box. Default is `false`. + */ + donotNotifyError?: boolean; + /** + * Scope of configuration to be written into. + */ + scopes?: IConfigurationOverrides; +} + interface IConfigurationEditOperation extends IConfigurationValue { target: ConfigurationTarget; jsonPath: json.JSONPath; @@ -50,7 +113,7 @@ interface ConfigurationEditingOptions extends IConfigurationEditingOptions { force?: boolean; } -export class ConfigurationEditingService implements IConfigurationEditingService { +export class ConfigurationEditingService { public _serviceBrand: any; @@ -190,7 +253,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService case ConfigurationTarget.WORKSPACE: this.commandService.executeCommand('workbench.action.openWorkspaceSettings'); break; - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: if (operation.resource) { const workspaceFolder = this.contextService.getWorkspaceFolder(operation.resource); if (workspaceFolder) { @@ -234,7 +297,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService return nls.localize('errorInvalidConfiguration', "Unable to write into user settings. Please open **User Settings** file to correct errors/warnings in it and try again."); case ConfigurationTarget.WORKSPACE: return nls.localize('errorInvalidConfigurationWorkspace', "Unable to write into workspace settings. Please open **Workspace Settings** file to correct errors/warnings in the file and try again."); - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name; return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open **Folder Settings** file under **{0}** folder to correct errors/warnings in it and try again.", workspaceFolderName); } @@ -252,7 +315,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService return nls.localize('errorConfigurationFileDirty', "Unable to write into user settings because the file is dirty. Please save the **User Settings** file and try again."); case ConfigurationTarget.WORKSPACE: return nls.localize('errorConfigurationFileDirtyWorkspace', "Unable to write into workspace settings because the file is dirty. Please save the **Workspace Settings** file and try again."); - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name; return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the **Folder Settings** file under **{0}** folder and try again.", workspaceFolderName); } @@ -267,9 +330,10 @@ export class ConfigurationEditingService implements IConfigurationEditingService return nls.localize('userTarget', "User Settings"); case ConfigurationTarget.WORKSPACE: return nls.localize('workspaceTarget', "Workspace Settings"); - case ConfigurationTarget.FOLDER: + case ConfigurationTarget.WORKSPACE_FOLDER: return nls.localize('folderTarget', "Folder Settings"); } + return ''; } private getEdits(model: editorCommon.IModel, edit: IConfigurationEditOperation): Edit[] { @@ -325,11 +389,11 @@ export class ConfigurationEditingService implements IConfigurationEditingService } // Target cannot be workspace or folder if no workspace opened - if ((target === ConfigurationTarget.WORKSPACE || target === ConfigurationTarget.FOLDER) && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { + if ((target === ConfigurationTarget.WORKSPACE || target === ConfigurationTarget.WORKSPACE_FOLDER) && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return this.wrapError(ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED, target, operation); } - if (target === ConfigurationTarget.FOLDER) { + if (target === ConfigurationTarget.WORKSPACE_FOLDER) { if (!operation.resource) { return this.wrapError(ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_TARGET, target, operation); } @@ -416,7 +480,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService } } - if (target === ConfigurationTarget.FOLDER) { + if (target === ConfigurationTarget.WORKSPACE_FOLDER) { if (resource) { const folder = this.contextService.getWorkspaceFolder(resource); if (folder) { diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 76c93c968ee..d83c8b0d642 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -37,7 +37,6 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; -import { IConfigurationEditingService, ConfigurationTarget as EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; @@ -74,7 +73,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat protected readonly _onDidChangeWorkbenchState: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkbenchState: Event = this._onDidChangeWorkbenchState.event; - private configurationEditingService: IConfigurationEditingService; + private configurationEditingService: ConfigurationEditingService; constructor(private environmentService: IEnvironmentService, private workspacesService: IWorkspacesService, private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME) { super(); @@ -474,7 +473,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return TPromise.as(null); } - return this.configurationEditingService.writeConfiguration(this.toEditableConfigurationTarget(target), { key, value }, { scopes: overrides, donotNotifyError }) + return this.configurationEditingService.writeConfiguration(target, { key, value }, { scopes: overrides, donotNotifyError }) .then(() => { switch (target) { case ConfigurationTarget.USER: @@ -518,19 +517,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return ConfigurationTarget.USER; } - private toEditableConfigurationTarget(target: ConfigurationTarget): EditableConfigurationTarget { - switch (target) { - case ConfigurationTarget.USER: - return EditableConfigurationTarget.USER; - case ConfigurationTarget.WORKSPACE: - return EditableConfigurationTarget.WORKSPACE; - case ConfigurationTarget.WORKSPACE_FOLDER: - return EditableConfigurationTarget.FOLDER; - default: - return EditableConfigurationTarget.WORKSPACE; - } - } - private triggerConfigurationChange(configurationEvent: ConfigurationChangeEvent, target: ConfigurationTarget): void { if (configurationEvent.affectedKeys.length) { configurationEvent.telemetryData(target, this.getTargetConfiguration(target)); diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index ca8bf742618..bc24a60429e 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -23,11 +23,10 @@ import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { FileService } from 'vs/workbench/services/files/node/fileService'; -import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; -import { ConfigurationTarget, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditing'; +import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { IFileService } from 'vs/platform/files/common/files'; import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; From a101ae181774824799b704f82966b61a9e43aa92 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 16 Oct 2017 14:24:51 -0700 Subject: [PATCH 153/394] Change a few more ts providers to use async --- .../src/features/definitionProviderBase.ts | 22 +++++++++---------- .../src/features/documentHighlightProvider.ts | 18 ++++++++++----- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/extensions/typescript/src/features/definitionProviderBase.ts b/extensions/typescript/src/features/definitionProviderBase.ts index bf5ffabd704..ee3a086a4fa 100644 --- a/extensions/typescript/src/features/definitionProviderBase.ts +++ b/extensions/typescript/src/features/definitionProviderBase.ts @@ -13,7 +13,7 @@ export default class TypeScriptDefinitionProviderBase { constructor( private client: ITypescriptServiceClient) { } - protected getSymbolLocations( + protected async getSymbolLocations( definitionType: 'definition' | 'implementation' | 'typeDefinition', document: TextDocument, position: Position, @@ -21,24 +21,24 @@ export default class TypeScriptDefinitionProviderBase { ): Promise { const filepath = this.client.normalizePath(document.uri); if (!filepath) { - return Promise.resolve(null); + return null; } + const args = vsPositionToTsFileLocation(filepath, position); - return this.client.execute(definitionType, args, token).then(response => { + try { + const response = await this.client.execute(definitionType, args, token); const locations: Proto.FileSpan[] = (response && response.body) || []; if (!locations || locations.length === 0) { return []; } return locations.map(location => { const resource = this.client.asUrl(location.file); - if (resource === null) { - return null; - } else { - return new Location(resource, tsTextSpanToVsRange(location)); - } - }).filter(x => x !== null) as Location[]; - }, () => { + return !resource + ? null + : new Location(resource, tsTextSpanToVsRange(location)); + }).filter(x => x) as Location[]; + } catch { return []; - }); + } } } \ No newline at end of file diff --git a/extensions/typescript/src/features/documentHighlightProvider.ts b/extensions/typescript/src/features/documentHighlightProvider.ts index d91cb8fd90b..871629630dc 100644 --- a/extensions/typescript/src/features/documentHighlightProvider.ts +++ b/extensions/typescript/src/features/documentHighlightProvider.ts @@ -13,14 +13,20 @@ export default class TypeScriptDocumentHighlightProvider implements DocumentHigh public constructor( private client: ITypescriptServiceClient) { } - public provideDocumentHighlights(resource: TextDocument, position: Position, token: CancellationToken): Promise { + public async provideDocumentHighlights( + resource: TextDocument, + position: Position, + token: CancellationToken + ): Promise { const filepath = this.client.normalizePath(resource.uri); if (!filepath) { - return Promise.resolve([]); + return []; } + const args = vsPositionToTsFileLocation(filepath, position); - return this.client.execute('occurrences', args, token).then((response): DocumentHighlight[] => { - let data = response.body; + try { + const response = await this.client.execute('occurrences', args, token); + const data = response.body; if (data && data.length) { // Workaround for https://github.com/Microsoft/TypeScript/issues/12780 // Don't highlight string occurrences @@ -39,8 +45,8 @@ export default class TypeScriptDocumentHighlightProvider implements DocumentHigh item.isWriteAccess ? DocumentHighlightKind.Write : DocumentHighlightKind.Read)); } return []; - }, () => { + } catch { return []; - }); + } } } \ No newline at end of file From f8bac907b7d9d922d6f52ffec51b9eaa3fef9854 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 16 Oct 2017 14:44:32 -0700 Subject: [PATCH 154/394] Mark markdown yaml frontmatter as yaml embedded language Fixes #30873 --- extensions/markdown/package.json | 1 + extensions/markdown/syntaxes/markdown.tmLanguage | 2 ++ extensions/markdown/syntaxes/markdown.tmLanguage.base | 2 ++ 3 files changed, 5 insertions(+) diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json index 769c6091855..5cb34c4c662 100644 --- a/extensions/markdown/package.json +++ b/extensions/markdown/package.json @@ -46,6 +46,7 @@ "meta.embedded.block.html": "html", "source.js": "javascript", "source.css": "css", + "meta.embedded.block.frontmatter": "yaml", "meta.embedded.block.css": "css", "meta.embedded.block.ini": "ini", diff --git a/extensions/markdown/syntaxes/markdown.tmLanguage b/extensions/markdown/syntaxes/markdown.tmLanguage index 7d5448a80d2..5e7d26dea2b 100644 --- a/extensions/markdown/syntaxes/markdown.tmLanguage +++ b/extensions/markdown/syntaxes/markdown.tmLanguage @@ -3691,6 +3691,8 @@ frontMatter + contentName + meta.embedded.block.frontmatter begin \A-{3}\s*$ while diff --git a/extensions/markdown/syntaxes/markdown.tmLanguage.base b/extensions/markdown/syntaxes/markdown.tmLanguage.base index 6d0a8510217..d501f50a86f 100644 --- a/extensions/markdown/syntaxes/markdown.tmLanguage.base +++ b/extensions/markdown/syntaxes/markdown.tmLanguage.base @@ -1181,6 +1181,8 @@ frontMatter + contentName + meta.embedded.block.frontmatter begin \A-{3}\s*$ while From 3495b0b185acbe8188e821ccb3ae807274703a9c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 16 Oct 2017 15:49:25 -0700 Subject: [PATCH 155/394] node-debug2@1.18.3 --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index e424881eaab..beb618c5195 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -46,7 +46,7 @@ const nodeModules = ['electron', 'original-fs'] const builtInExtensions = [ { name: 'ms-vscode.node-debug', version: '1.18.1' }, - { name: 'ms-vscode.node-debug2', version: '1.18.1' } + { name: 'ms-vscode.node-debug2', version: '1.18.3' } ]; const excludedExtensions = [ From 5aff04bc9e57a6df22e6c026ad38bdaa377c44f2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 09:50:52 +0200 Subject: [PATCH 156/394] Capture current side editing behaviour --- .../test/common/commands/sideEditing.test.ts | 698 ++++++++++++++++++ 1 file changed, 698 insertions(+) diff --git a/src/vs/editor/test/common/commands/sideEditing.test.ts b/src/vs/editor/test/common/commands/sideEditing.test.ts index 08fe4e0c5e7..a5e2100692c 100644 --- a/src/vs/editor/test/common/commands/sideEditing.test.ts +++ b/src/vs/editor/test/common/commands/sideEditing.test.ts @@ -12,6 +12,10 @@ import { Selection } from 'vs/editor/common/core/selection'; import { IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon'; import { ILineEdit, ModelLine, LineMarker, MarkersTracker } from 'vs/editor/common/model/modelLine'; import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; +import { Model } from 'vs/editor/common/model/model'; +import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration'; +import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl'; +import { Cursor } from 'vs/editor/common/controller/cursor'; const NO_TAB_SIZE = 0; @@ -204,5 +208,699 @@ suite('Editor Side Editing - collapsed selection', () => { [new Selection(1, 1, 1, 1), new Selection(1, 3, 1, 3)] ); }); +}); +suite('SideEditing', () => { + + const LINES = [ + 'My First Line', + 'My Second Line', + 'Third Line' + ]; + + function _runTest(selection: Selection, editRange: Range, editText: string, editForceMoveMarkers: boolean, expected: Selection, msg: string): void { + const model = Model.createFromString(LINES.join('\n')); + const config = new TestConfiguration(null); + const viewModel = new ViewModel(0, config, model, null); + const cursor = new Cursor(config, model, viewModel); + + cursor.setSelections('tests', [selection]); + model.applyEdits([{ range: editRange, text: editText, forceMoveMarkers: editForceMoveMarkers, identifier: null }]); + const actual = cursor.getSelection(); + assert.deepEqual(actual.toString(), expected.toString(), msg); + + cursor.dispose(); + viewModel.dispose(); + config.dispose(); + model.dispose(); + } + + function runTest(selection: Range, editRange: Range, editText: string, expected: Selection[][]): void { + const sel1 = new Selection(selection.startLineNumber, selection.startColumn, selection.endLineNumber, selection.endColumn); + _runTest(sel1, editRange, editText, false, expected[0][0], '0-0-regular-no-force'); + _runTest(sel1, editRange, editText, true, expected[1][0], '1-0-regular-force'); + + // RTL selection + const sel2 = new Selection(selection.endLineNumber, selection.endColumn, selection.startLineNumber, selection.startColumn); + _runTest(sel2, editRange, editText, false, expected[0][1], '0-1-inverse-no-force'); + _runTest(sel2, editRange, editText, true, expected[1][1], '1-1-inverse-force'); + } + + suite('insert', () => { + suite('collapsed sel', () => { + test('before', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 3), 'xx', + [ + [new Selection(1, 6, 1, 6), new Selection(1, 6, 1, 6)], + [new Selection(1, 6, 1, 6), new Selection(1, 6, 1, 6)], + ] + ); + }); + test('equal', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 4), 'xx', + [ + [new Selection(1, 4, 1, 6), new Selection(1, 4, 1, 6)], + [new Selection(1, 6, 1, 6), new Selection(1, 6, 1, 6)], + ] + ); + }); + test('after', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 5), 'xx', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('before', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 3), 'xx', + [ + [new Selection(1, 6, 1, 11), new Selection(1, 11, 1, 6)], + [new Selection(1, 6, 1, 11), new Selection(1, 11, 1, 6)], + ] + ); + }); + test('start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 4), 'xx', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 6, 1, 11), new Selection(1, 11, 1, 6)], + ] + ); + }); + test('inside', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 5), 'xx', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + ] + ); + }); + test('end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 9), 'xx', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + ] + ); + }); + test('after', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 10), 'xx', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + }); + }); + + suite('delete', () => { + suite('collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 1, 1, 3), '', + [ + [new Selection(1, 2, 1, 2), new Selection(1, 2, 1, 2)], + [new Selection(1, 2, 1, 2), new Selection(1, 2, 1, 2)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 2, 1, 4), '', + [ + [new Selection(1, 2, 1, 2), new Selection(1, 2, 1, 2)], + [new Selection(1, 2, 1, 2), new Selection(1, 2, 1, 2)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 5), '', + [ + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + ] + ); + }); + test('edit.start >= range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 6), '', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 7), '', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 1, 1, 3), '', + [ + [new Selection(1, 2, 1, 7), new Selection(1, 7, 1, 2)], + [new Selection(1, 2, 1, 7), new Selection(1, 7, 1, 2)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 2, 1, 4), '', + [ + [new Selection(1, 2, 1, 7), new Selection(1, 7, 1, 2)], + [new Selection(1, 2, 1, 7), new Selection(1, 7, 1, 2)], + ] + ); + }); + test('edit.start < range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 5), '', + [ + [new Selection(1, 3, 1, 7), new Selection(1, 7, 1, 3)], + [new Selection(1, 3, 1, 7), new Selection(1, 7, 1, 3)], + ] + ); + }); + + test('edit.start < range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 9), '', + [ + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + ] + ); + }); + + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 10), '', + [ + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + ] + ); + }); + + test('edit.start == range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 6), '', + [ + [new Selection(1, 4, 1, 7), new Selection(1, 7, 1, 4)], + [new Selection(1, 4, 1, 7), new Selection(1, 7, 1, 4)], + ] + ); + }); + + test('edit.start == range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 9), '', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + + test('edit.start == range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 10), '', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + + test('edit.start > range.start && edit.start < range.end && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 7), '', + [ + [new Selection(1, 4, 1, 7), new Selection(1, 7, 1, 4)], + [new Selection(1, 4, 1, 7), new Selection(1, 7, 1, 4)], + ] + ); + }); + + test('edit.start > range.start && edit.start < range.end && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 9), '', + [ + [new Selection(1, 4, 1, 5), new Selection(1, 5, 1, 4)], + [new Selection(1, 4, 1, 5), new Selection(1, 5, 1, 4)], + ] + ); + }); + + test('edit.start > range.start && edit.start < range.end && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 10), '', + [ + [new Selection(1, 4, 1, 5), new Selection(1, 5, 1, 4)], + [new Selection(1, 4, 1, 5), new Selection(1, 5, 1, 4)], + ] + ); + }); + + test('edit.start == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 11), '', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 11), '', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + }); + }); + + suite('replace short', () => { + suite('collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 1, 1, 3), 'c', + [ + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 2, 1, 4), 'c', + [ + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + [new Selection(1, 3, 1, 3), new Selection(1, 3, 1, 3)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 5), 'c', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + test('edit.start >= range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 6), 'c', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 5, 1, 5), new Selection(1, 5, 1, 5)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 7), 'c', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 1, 1, 3), 'c', + [ + [new Selection(1, 3, 1, 8), new Selection(1, 8, 1, 3)], + [new Selection(1, 3, 1, 8), new Selection(1, 8, 1, 3)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 2, 1, 4), 'c', + [ + [new Selection(1, 3, 1, 8), new Selection(1, 8, 1, 3)], + [new Selection(1, 3, 1, 8), new Selection(1, 8, 1, 3)], + ] + ); + }); + test('edit.start < range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 5), 'c', + [ + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + ] + ); + }); + test('edit.start < range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 9), 'c', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 10), 'c', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + test('edit.start == range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 6), 'c', + [ + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + [new Selection(1, 5, 1, 8), new Selection(1, 8, 1, 5)], + ] + ); + }); + test('edit.start == range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 9), 'c', + [ + [new Selection(1, 4, 1, 5), new Selection(1, 5, 1, 4)], + [new Selection(1, 5, 1, 5), new Selection(1, 5, 1, 5)], + ] + ); + }); + test('edit.start == range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 10), 'c', + [ + [new Selection(1, 4, 1, 5), new Selection(1, 5, 1, 4)], + [new Selection(1, 5, 1, 5), new Selection(1, 5, 1, 5)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 7), 'c', + [ + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 9), 'c', + [ + [new Selection(1, 4, 1, 6), new Selection(1, 6, 1, 4)], + [new Selection(1, 4, 1, 6), new Selection(1, 6, 1, 4)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 10), 'c', + [ + [new Selection(1, 4, 1, 6), new Selection(1, 6, 1, 4)], + [new Selection(1, 4, 1, 6), new Selection(1, 6, 1, 4)], + ] + ); + }); + test('edit.start == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 11), 'c', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 10), new Selection(1, 10, 1, 4)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 11), 'c', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + }); + }); + + suite('replace long', () => { + suite('collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 1, 1, 3), 'cccc', + [ + [new Selection(1, 6, 1, 6), new Selection(1, 6, 1, 6)], + [new Selection(1, 6, 1, 6), new Selection(1, 6, 1, 6)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 2, 1, 4), 'cccc', + [ + [new Selection(1, 4, 1, 6), new Selection(1, 4, 1, 6)], + [new Selection(1, 6, 1, 6), new Selection(1, 6, 1, 6)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 3, 1, 5), 'cccc', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 7, 1, 7), new Selection(1, 7, 1, 7)], + ] + ); + }); + test('edit.start >= range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 4, 1, 6), 'cccc', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 8, 1, 8), new Selection(1, 8, 1, 8)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 4), + new Range(1, 5, 1, 7), 'cccc', + [ + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + [new Selection(1, 4, 1, 4), new Selection(1, 4, 1, 4)], + ] + ); + }); + }); + suite('non-collapsed dec', () => { + test('edit.end < range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 1, 1, 3), 'cccc', + [ + [new Selection(1, 6, 1, 11), new Selection(1, 11, 1, 6)], + [new Selection(1, 6, 1, 11), new Selection(1, 11, 1, 6)], + ] + ); + }); + test('edit.end <= range.start', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 2, 1, 4), 'cccc', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 6, 1, 11), new Selection(1, 11, 1, 6)], + ] + ); + }); + test('edit.start < range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 5), 'cccc', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 7, 1, 11), new Selection(1, 11, 1, 7)], + ] + ); + }); + test('edit.start < range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 9), 'cccc', + [ + [new Selection(1, 4, 1, 7), new Selection(1, 7, 1, 4)], + [new Selection(1, 7, 1, 7), new Selection(1, 7, 1, 7)], + ] + ); + }); + test('edit.start < range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 3, 1, 10), 'cccc', + [ + [new Selection(1, 4, 1, 7), new Selection(1, 7, 1, 4)], + [new Selection(1, 7, 1, 7), new Selection(1, 7, 1, 7)], + ] + ); + }); + test('edit.start == range.start && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 6), 'cccc', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 8, 1, 11), new Selection(1, 11, 1, 8)], + ] + ); + }); + test('edit.start == range.start && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 9), 'cccc', + [ + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + [new Selection(1, 8, 1, 8), new Selection(1, 8, 1, 8)], + ] + ); + }); + test('edit.start == range.start && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 4, 1, 10), 'cccc', + [ + [new Selection(1, 4, 1, 8), new Selection(1, 8, 1, 4)], + [new Selection(1, 8, 1, 8), new Selection(1, 8, 1, 8)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end < range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 7), 'cccc', + [ + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + [new Selection(1, 4, 1, 11), new Selection(1, 11, 1, 4)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 9), 'cccc', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + test('edit.start > range.start && edit.start < range.end && edit.end > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 5, 1, 10), 'cccc', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + test('edit.start == range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 9, 1, 11), 'cccc', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 13), new Selection(1, 13, 1, 4)], + ] + ); + }); + test('edit.start > range.end', () => { + runTest( + new Range(1, 4, 1, 9), + new Range(1, 10, 1, 11), 'cccc', + [ + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + [new Selection(1, 4, 1, 9), new Selection(1, 9, 1, 4)], + ] + ); + }); + }); + }); }); \ No newline at end of file From 7d3ee8ab43c6656adc27a0292c93660c4e9bb04f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 Oct 2017 10:18:59 +0200 Subject: [PATCH 157/394] telemetry - delay fileGet until model is loaded to properly resolve mimetype --- .../textfile/common/textFileEditorModel.ts | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 90b96f490d5..8076fc12f2a 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -364,16 +364,25 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } private loadWithContent(content: IRawTextContent | IContent, backup?: URI): TPromise { - diag('load() - resolved content', this.resource, new Date()); + return this.doLoadWithContent(content, backup).then(model => { - /* __GDPR__ - "fileGet" : { - "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); + // We log the fileGet telemetry event after the model has been loaded to ensure a good mimetype + + /* __GDPR__ + "fileGet" : { + "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); + + return model; + }); + } + + private doLoadWithContent(content: IRawTextContent | IContent, backup?: URI): TPromise { + diag('load() - resolved content', this.resource, new Date()); // Update our resolved disk stat model const resolvedStat: IFileStat = { From b0a7b57d46a2dc1bafeb256006f71897ca9cfcb2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 17 Oct 2017 10:46:33 +0200 Subject: [PATCH 158/394] Rename IConfigurationService onDidUpdateConfiguration to onDidChangeConfiguration --- src/vs/code/electron-main/menus.ts | 2 +- src/vs/code/electron-main/window.ts | 2 +- src/vs/editor/common/services/modelServiceImpl.ts | 2 +- .../editor/common/services/resourceConfiguration.ts | 3 ++- .../common/services/resourceConfigurationImpl.ts | 8 ++++---- src/vs/editor/standalone/browser/simpleServices.ts | 12 ++++++------ .../platform/configuration/common/configuration.ts | 2 +- .../configuration/node/configurationService.ts | 6 +++--- .../test/common/testConfigurationService.ts | 2 +- .../platform/contextkey/browser/contextKeyService.ts | 2 +- src/vs/platform/request/node/requestService.ts | 2 +- src/vs/platform/telemetry/common/telemetryService.ts | 2 +- src/vs/platform/telemetry/common/telemetryUtils.ts | 2 +- .../test/electron-browser/telemetryService.test.ts | 2 +- .../api/electron-browser/mainThreadConfiguration.ts | 2 +- src/vs/workbench/browser/labels.ts | 2 +- src/vs/workbench/browser/parts/editor/editorPart.ts | 2 +- src/vs/workbench/browser/parts/editor/textEditor.ts | 2 +- .../browser/parts/quickopen/quickOpenController.ts | 2 +- .../workbench/browser/parts/titlebar/titlebarPart.ts | 2 +- src/vs/workbench/common/editor/editorStacksModel.ts | 2 +- .../workbench/common/editor/untitledEditorModel.ts | 2 +- src/vs/workbench/common/resources.ts | 2 +- src/vs/workbench/electron-browser/window.ts | 2 +- src/vs/workbench/electron-browser/workbench.ts | 2 +- .../parts/backup/common/backupModelTracker.ts | 2 +- .../parts/debug/browser/debugActionItems.ts | 2 +- .../parts/debug/browser/debugActionsWidget.ts | 2 +- .../electron-browser/debugConfigurationManager.ts | 2 +- .../parts/extensions/browser/extensionsActions.ts | 2 +- .../extensions/electron-browser/extensionsViewlet.ts | 2 +- .../extensions/node/extensionsWorkbenchService.ts | 2 +- .../workbench/parts/files/browser/explorerViewlet.ts | 2 +- .../parts/files/browser/views/explorerView.ts | 2 +- .../parts/files/browser/views/explorerViewer.ts | 4 ++-- .../parts/files/browser/views/openEditorsView.ts | 2 +- .../parts/files/common/editors/fileEditorTracker.ts | 2 +- .../parts/markers/browser/markersFileDecorations.ts | 2 +- .../workbench/parts/markers/browser/markersPanel.ts | 2 +- .../preferences/browser/preferencesRenderers.ts | 2 +- .../preferences/common/preferencesContribution.ts | 2 +- .../parts/quickopen/browser/commandsHandler.ts | 4 ++-- .../electron-browser/relauncher.contribution.ts | 2 +- .../parts/scm/electron-browser/scmFileDecorations.ts | 2 +- .../parts/search/browser/openAnythingHandler.ts | 2 +- .../tasks/electron-browser/task.contribution.ts | 2 +- .../parts/terminal/common/terminalService.ts | 2 +- .../parts/terminal/electron-browser/terminalPanel.ts | 2 +- .../electron-browser/terminalConfigHelper.test.ts | 2 +- .../unsupportedWorkspaceSettings.contribution.ts | 2 +- .../parts/watermark/electron-browser/watermark.ts | 2 +- .../walkThrough/electron-browser/walkThroughPart.ts | 4 ++-- .../configuration/node/configurationService.ts | 10 +++++----- .../test/node/configurationService.test.ts | 10 +++++----- .../test/node/configurationResolverService.test.ts | 2 +- .../services/files/electron-browser/fileService.ts | 2 +- .../files/node/watcher/nsfw/watcherService.ts | 2 +- .../keybinding/electron-browser/keybindingService.ts | 2 +- .../services/mode/common/workbenchModeService.ts | 2 +- .../services/textfile/common/textFileService.ts | 2 +- .../themes/electron-browser/workbenchThemeService.ts | 2 +- src/vs/workbench/test/workbenchTestServices.ts | 2 +- 62 files changed, 84 insertions(+), 83 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 327dcba23b3..68af45f2186 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -136,7 +136,7 @@ export class CodeMenu { }); // Update when auto save config changes - this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), true /* update menu if changed */)); + this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), true /* update menu if changed */)); // Listen to update service this.updateService.onStateChange(() => this.updateMenu()); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 50570fd57b9..e1999859678 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -409,7 +409,7 @@ export class CodeWindow implements ICodeWindow { } // Handle configuration changes - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated())); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated())); // Handle Workspace events this.toDispose.push(this.workspaceService.onUntitledWorkspaceDeleted(e => this.onUntitledWorkspaceDeleted(e))); diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index fe046a165d5..1fbc491f271 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -224,7 +224,7 @@ export class ModelServiceImpl implements IModelService { this._markerServiceSubscription = this._markerService.onMarkerChanged(this._handleMarkerChange, this); } - this._configurationServiceSubscription = this._configurationService.onDidUpdateConfiguration(e => this._updateModelOptions()); + this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions()); this._updateModelOptions(); } diff --git a/src/vs/editor/common/services/resourceConfiguration.ts b/src/vs/editor/common/services/resourceConfiguration.ts index 2a959539e9b..e65c4a12104 100644 --- a/src/vs/editor/common/services/resourceConfiguration.ts +++ b/src/vs/editor/common/services/resourceConfiguration.ts @@ -7,6 +7,7 @@ import Event from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IPosition } from 'vs/editor/common/core/position'; +import { IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; export const ITextResourceConfigurationService = createDecorator('textResourceConfigurationService'); @@ -17,7 +18,7 @@ export interface ITextResourceConfigurationService { /** * Event that fires when the configuration changes. */ - onDidUpdateConfiguration: Event; + onDidChangeConfiguration: Event; /** * Fetches the appropriate section of the for the given resource with appropriate overrides (e.g. language). diff --git a/src/vs/editor/common/services/resourceConfigurationImpl.ts b/src/vs/editor/common/services/resourceConfigurationImpl.ts index 453395b6488..6124db46a06 100644 --- a/src/vs/editor/common/services/resourceConfigurationImpl.ts +++ b/src/vs/editor/common/services/resourceConfigurationImpl.ts @@ -6,7 +6,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -16,8 +16,8 @@ export class TextResourceConfigurationService extends Disposable implements ITex public _serviceBrand: any; - private readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); - public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private readonly _onDidChangeConfiguration: Emitter = this._register(new Emitter()); + public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; constructor( @IConfigurationService private configurationService: IConfigurationService, @@ -25,7 +25,7 @@ export class TextResourceConfigurationService extends Disposable implements ITex @IModeService private modeService: IModeService, ) { super(); - this._register(this.configurationService.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire())); + this._register(this.configurationService.onDidChangeConfiguration(e => this._onDidChangeConfiguration.fire(e))); } getConfiguration(resource: URI, section?: string): T diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index abc268c123e..88a323b05be 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -445,8 +445,8 @@ export class SimpleConfigurationService implements IConfigurationService { _serviceBrand: any; - private _onDidUpdateConfiguration = new Emitter(); - public onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _onDidChangeConfiguration = new Emitter(); + public onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; private _configuration: Configuration; @@ -503,12 +503,12 @@ export class SimpleResourceConfigurationService implements ITextResourceConfigur _serviceBrand: any; - public readonly onDidUpdateConfiguration: Event; - private readonly _onDidUpdateConfigurationEmitter = new Emitter(); + public readonly onDidChangeConfiguration: Event; + private readonly _onDidChangeConfigurationEmitter = new Emitter(); constructor(private configurationService: SimpleConfigurationService) { - this.configurationService.onDidUpdateConfiguration(() => { - this._onDidUpdateConfigurationEmitter.fire(); + this.configurationService.onDidChangeConfiguration((e) => { + this._onDidChangeConfigurationEmitter.fire(e); }); } diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index fd78d7e71a1..5f5145c0ed3 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -48,7 +48,7 @@ export interface IConfigurationChangeEvent { export interface IConfigurationService { _serviceBrand: any; - onDidUpdateConfiguration: Event; + onDidChangeConfiguration: Event; getConfigurationData(): IConfigurationData; diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 6b1d5954fa5..9fb8cfc6fa6 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -24,8 +24,8 @@ export class ConfigurationService extends Disposable implements IConfigurationSe private _configuration: Configuration; private userConfigModelWatcher: ConfigWatcher; - private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); - readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _onDidChangeConfiguration: Emitter = this._register(new Emitter()); + readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; constructor( @IEnvironmentService environmentService: IEnvironmentService @@ -128,7 +128,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe } private trigger(keys: string[], source: ConfigurationTarget): void { - this._onDidUpdateConfiguration.fire(new ConfigurationChangeEvent().change(keys).telemetryData(source, this.getTargetConfiguration(source))); + this._onDidChangeConfiguration.fire(new ConfigurationChangeEvent().change(keys).telemetryData(source, this.getTargetConfiguration(source))); } private getTargetConfiguration(target: ConfigurationTarget): any { diff --git a/src/vs/platform/configuration/test/common/testConfigurationService.ts b/src/vs/platform/configuration/test/common/testConfigurationService.ts index 52363535b85..dcb88e2eb1d 100644 --- a/src/vs/platform/configuration/test/common/testConfigurationService.ts +++ b/src/vs/platform/configuration/test/common/testConfigurationService.ts @@ -52,7 +52,7 @@ export class TestConfigurationService extends EventEmitter implements IConfigura return TPromise.as(null); } - public onDidUpdateConfiguration() { + public onDidChangeConfiguration() { return { dispose() { } }; } diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index df96f3c0c0d..39d1f8cc654 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -58,7 +58,7 @@ class ConfigAwareContextValuesContainer extends Context { super(id, null); this._emitter = emitter; - this._subscription = configurationService.onDidUpdateConfiguration(e => this._updateConfigurationContext(configurationService.getConfiguration())); + this._subscription = configurationService.onDidChangeConfiguration(e => this._updateConfigurationContext(configurationService.getConfiguration())); this._updateConfigurationContext(configurationService.getConfiguration()); } diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts index de5f75fbbd6..a6e58846724 100644 --- a/src/vs/platform/request/node/requestService.ts +++ b/src/vs/platform/request/node/requestService.ts @@ -29,7 +29,7 @@ export class RequestService implements IRequestService { @IConfigurationService configurationService: IConfigurationService ) { this.configure(configurationService.getConfiguration()); - configurationService.onDidUpdateConfiguration(() => this.configure(configurationService.getConfiguration()), this, this.disposables); + configurationService.onDidChangeConfiguration(() => this.configure(configurationService.getConfiguration()), this, this.disposables); } private configure(config: IHTTPConfiguration) { diff --git a/src/vs/platform/telemetry/common/telemetryService.ts b/src/vs/platform/telemetry/common/telemetryService.ts index 0ebdb46ff38..45c89aa945a 100644 --- a/src/vs/platform/telemetry/common/telemetryService.ts +++ b/src/vs/platform/telemetry/common/telemetryService.ts @@ -64,7 +64,7 @@ export class TelemetryService implements ITelemetryService { if (this._configurationService) { this._updateUserOptIn(); - this._configurationService.onDidUpdateConfiguration(this._updateUserOptIn, this, this._disposables); + this._configurationService.onDidChangeConfiguration(this._updateUserOptIn, this, this._disposables); /* __GDPR__ "optInStatus" : { "optIn" : { "classification": "SystemMetaData", "purpose": "BusinessInsight" } diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 9ef38db2fa9..4f177bbb2e2 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -185,7 +185,7 @@ const configurationValueWhitelist = [ ]; export function configurationTelemetry(telemetryService: ITelemetryService, configurationService: IConfigurationService): IDisposable { - return configurationService.onDidUpdateConfiguration(event => { + return configurationService.onDidChangeConfiguration(event => { if (event.source !== ConfigurationTarget.DEFAULT) { /* __GDPR__ "updateConfiguration" : { diff --git a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts index d97577a72b3..69d2f789bb6 100644 --- a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts @@ -697,7 +697,7 @@ suite('TelemetryService', () => { }; }, keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; }, - onDidUpdateConfiguration: emitter.event, + onDidChangeConfiguration: emitter.event, reloadConfiguration() { return null; }, getConfigurationData() { return null; } }); diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 79d793d416c..a8b5cf06253 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -27,7 +27,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { ) { const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); - this._configurationListener = configurationService.onDidUpdateConfiguration(() => { + this._configurationListener = configurationService.onDidChangeConfiguration(() => { proxy.$acceptConfigurationChanged(configurationService.getConfigurationData()); }); } diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index ec6920eed22..5c0a40f1752 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -65,7 +65,7 @@ export class ResourceLabel extends IconLabel { private registerListeners(): void { this.extensionService.onReady().then(() => this.render(true /* clear cache */)); // update when extensions are loaded with potentially new languages - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => this.render(true /* clear cache */))); // update when file.associations change + this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.render(true /* clear cache */))); // update when file.associations change this.toDispose.push(this.modelService.onModelModeChanged(e => this.onModelModeChanged(e))); // react to model mode changes this.toDispose.push(this.decorationsService.onDidChangeDecorations(this.onFileDecorationsChanges, this)); // react to file decoration changes this.toDispose.push(this.themeService.onThemeChange(() => this.render(false))); diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 3b01b41686a..0899f3bd851 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -205,7 +205,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.toUnbind.push(this.stacks.onEditorClosed(event => this.onEditorClosed(event))); this.toUnbind.push(this.stacks.onGroupOpened(event => this.onEditorGroupOpenedOrClosed())); this.toUnbind.push(this.stacks.onGroupClosed(event => this.onEditorGroupOpenedOrClosed())); - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); } private onEditorGroupOpenedOrClosed(): void { diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index b70eced071c..13522be113f 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -66,7 +66,7 @@ export abstract class BaseTextEditor extends BaseEditor { ) { super(id, telemetryService, themeService); - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getConfiguration(this.getResource())))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getConfiguration(this.getResource())))); } protected get instantiationService(): IInstantiationService { diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 08681245fcd..3a666cfbc1c 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -137,7 +137,7 @@ export class QuickOpenController extends Component implements IQuickOpenService } private registerListeners(): void { - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.updateConfiguration(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration(this.configurationService.getConfiguration()))); this.toUnbind.push(this.partService.onTitleBarVisibilityChange(() => this.positionQuickOpenWidget())); this.toUnbind.push(browser.onDidChangeZoomLevel(() => this.positionQuickOpenWidget())); } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index bfba7464b3d..62741f2adfc 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -99,7 +99,7 @@ export class TitlebarPart extends Part implements ITitleService { private registerListeners(): void { this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.BLUR, () => this.onBlur())); this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.FOCUS, () => this.onFocus())); - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.onConfigurationChanged(true))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.onConfigurationChanged(true))); this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.setTitle(this.getWindowTitle()))); this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.setTitle(this.getWindowTitle()))); diff --git a/src/vs/workbench/common/editor/editorStacksModel.ts b/src/vs/workbench/common/editor/editorStacksModel.ts index 26d0dca609d..148a01d2c41 100644 --- a/src/vs/workbench/common/editor/editorStacksModel.ts +++ b/src/vs/workbench/common/editor/editorStacksModel.ts @@ -110,7 +110,7 @@ export class EditorGroup implements IEditorGroup { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); } private onConfigurationUpdated(config: IWorkbenchEditorConfiguration): void { diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 5442ba80ab6..278e1bdcad8 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -94,7 +94,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin private registerListeners(): void { // Config Changes - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange())); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange())); } private onConfigurationChange(): void { diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index ec82d07b99b..9ffaef6c14f 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -95,7 +95,7 @@ export class ResourceGlobMatcher { } private registerListeners(): void { - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.updateExcludes(true))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.updateExcludes(true))); this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateExcludes(true))); } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index e1dfbbe2a03..5049e7db79e 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -240,7 +240,7 @@ export class ElectronWindow extends Themable { }); // Configuration changes - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onDidUpdateConfiguration(e))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onDidUpdateConfiguration(e))); // Context menu support in input/textarea window.document.addEventListener('contextmenu', e => this.onContextMenu(e)); diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 8f5e5fbe60d..89a41c79fb2 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -986,7 +986,7 @@ export class Workbench implements IPartService { this.toDispose.push(this.quickOpen.onHide(() => (this.messageService).resume())); // resume messages once quick open is closed again // Configuration changes - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => this.onDidUpdateConfiguration())); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration())); // Fullscreen changes this.toDispose.push(browser.onDidChangeFullscreen(() => this.onFullscreenChanged())); diff --git a/src/vs/workbench/parts/backup/common/backupModelTracker.ts b/src/vs/workbench/parts/backup/common/backupModelTracker.ts index 787897cd389..4b1408847d2 100644 --- a/src/vs/workbench/parts/backup/common/backupModelTracker.ts +++ b/src/vs/workbench/parts/backup/common/backupModelTracker.ts @@ -50,7 +50,7 @@ export class BackupModelTracker implements IWorkbenchContribution { this.toDispose.push(this.untitledEditorService.onDidDisposeModel((e) => this.discardBackup(e))); // Listen to config changes - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); } private onConfigurationChange(configuration: IFilesConfiguration): void { diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 9467e227330..81af57279a2 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -54,7 +54,7 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('launch')) { this.updateOptions(); } diff --git a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts index 5818d30bd3b..3c68f376e9c 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts @@ -93,7 +93,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi private registerListeners(): void { this.toUnbind.push(this.debugService.onDidChangeState(state => this.update(state))); - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.update(this.debugService.state))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.update(this.debugService.state))); this.toUnbind.push(this.actionBar.actionRunner.addListener(EventType.RUN, (e: any) => { // check for error if (e.error && !errors.isPromiseCanceledError(e.error)) { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index d303e2417ff..78cecbd98bf 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -323,7 +323,7 @@ export class ConfigurationManager implements IConfigurationManager { this.initLaunches(); this.selectConfiguration(); })); - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => { + this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => { this.selectConfiguration(); })); diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index 1217632d2ab..e32066bcf7a 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -709,7 +709,7 @@ export class ToggleAutoUpdateAction extends Action { ) { super(id, label, '', true); this.updateEnablement(); - configurationService.onDidUpdateConfiguration(() => this.updateEnablement()); + configurationService.onDidChangeConfiguration(() => this.updateEnablement()); } private updateEnablement(): void { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts index ccbee9dd3a1..6a9c5ce9481 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts @@ -111,7 +111,7 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens this.disposables.push(viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables)); this.isAutoUpdateEnabled = this.extensionsWorkbenchService.isAutoUpdateEnabled; - this.configurationService.onDidUpdateConfiguration(() => { + this.configurationService.onDidChangeConfiguration(() => { const isAutoUpdateEnabled = this.extensionsWorkbenchService.isAutoUpdateEnabled; if (this.isAutoUpdateEnabled !== isAutoUpdateEnabled) { this.isAutoUpdateEnabled = isAutoUpdateEnabled; diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index b55058ebf56..7808d2d4c4c 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -347,7 +347,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { .on(this.onOpenExtensionUrl, this, this.disposables); this._isAutoUpdateEnabled = this.configurationService.getConfiguration(ConfigurationKey).autoUpdate; - this.configurationService.onDidUpdateConfiguration(() => { + this.configurationService.onDidChangeConfiguration(() => { const isAutoUpdateEnabled = this.configurationService.getConfiguration(ConfigurationKey).autoUpdate; if (this._isAutoUpdateEnabled !== isAutoUpdateEnabled) { this._isAutoUpdateEnabled = isAutoUpdateEnabled; diff --git a/src/vs/workbench/parts/files/browser/explorerViewlet.ts b/src/vs/workbench/parts/files/browser/explorerViewlet.ts index 340a269b289..8855798cefa 100644 --- a/src/vs/workbench/parts/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/browser/explorerViewlet.ts @@ -62,7 +62,7 @@ export class ExplorerViewlet extends PersistentViewsViewlet { this.registerViews(); this.onConfigurationUpdated(); - this._register(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated())); + this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated())); this._register(this.contextService.onDidChangeWorkspaceName(e => this.updateTitleArea())); this._register(this.contextService.onDidChangeWorkbenchState(() => this.registerViews())); this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.registerViews())); diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index f522ebcea6d..b831fcb8ac4 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -204,7 +204,7 @@ export class ExplorerView extends ViewsViewletPanel { this.disposables.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); // Also handle configuration updates - this.disposables.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), e))); + this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), e))); }); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index a095ecd2a5a..0328d3ef7ea 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -568,7 +568,7 @@ export class FileSorter implements ISorter { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); } private onConfigurationUpdated(configuration: IFilesConfiguration): void { @@ -769,7 +769,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); } private onConfigurationUpdated(config: IFilesConfiguration): void { diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts index 51b5ab51ba9..541fd1adb78 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts @@ -183,7 +183,7 @@ export class OpenEditorsView extends ViewsViewletPanel { this.disposables.push(this.model.onModelChanged(e => this.onEditorStacksModelChanged(e))); // Also handle configuration updates - this.disposables.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); // Handle dirty counter this.disposables.push(this.untitledEditorService.onDidChangeDirty(e => this.updateDirtyIndicator())); diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts index c07ed76b795..3209fbc2a2e 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts @@ -75,7 +75,7 @@ export class FileEditorTracker implements IWorkbenchContribution { this.lifecycleService.onShutdown(this.dispose, this); // Configuration - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); } private onConfigurationUpdated(configuration: IWorkbenchEditorConfiguration): void { diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts index e9a44a611ac..d9a6ce584da 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts @@ -64,7 +64,7 @@ class MarkersFileDecorations implements IWorkbenchContribution { ) { // this._disposables = [ - this._configurationService.onDidUpdateConfiguration(this._updateEnablement, this), + this._configurationService.onDidChangeConfiguration(this._updateEnablement, this), ]; this._updateEnablement(); } diff --git a/src/vs/workbench/parts/markers/browser/markersPanel.ts b/src/vs/workbench/parts/markers/browser/markersPanel.ts index a4060b88693..13305518c4e 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanel.ts @@ -253,7 +253,7 @@ export class MarkersPanel extends Panel { } private createListeners(): void { - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationsUpdated(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationsUpdated(this.configurationService.getConfiguration()))); this.toUnbind.push(this.markerService.onMarkerChanged(this.onMarkerChanged, this)); this.toUnbind.push(this.editorGroupService.onEditorsChanged(this.onEditorsChanged, this)); this.toUnbind.push(this.tree.addListener('selection', () => this.onSelected())); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 02c4e1a85c6..151446902f8 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -950,7 +950,7 @@ class UnsupportedWorkspaceSettingsRenderer extends Disposable { @IMarkerService private markerService: IMarkerService ) { super(); - this._register(this.configurationService.onDidUpdateConfiguration(() => this.render())); + this._register(this.configurationService.onDidChangeConfiguration(() => this.render())); } private getMarkerMessage(settingKey: string): string { diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index 2f91e713b0d..db5b54b3fb7 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -38,7 +38,7 @@ export class PreferencesContribution implements IWorkbenchContribution { @IWorkspaceContextService private workspaceService: IWorkspaceContextService, @IConfigurationService private configurationService: IConfigurationService ) { - this.settingsListener = this.configurationService.onDidUpdateConfiguration(() => this.handleSettingsEditorOverride()); + this.settingsListener = this.configurationService.onDidChangeConfiguration(() => this.handleSettingsEditorOverride()); this.handleSettingsEditorOverride(); this.start(); diff --git a/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts b/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts index f5e99434096..8b5d93e1438 100644 --- a/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts @@ -95,7 +95,7 @@ class CommandsHistory { } private registerListeners(): void { - this.configurationService.onDidUpdateConfiguration(e => this.updateConfiguration()); + this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration()); once(this.lifecycleService.onShutdown)(reason => this.save()); } @@ -404,7 +404,7 @@ export class CommandsHandler extends QuickOpenHandler { this.commandsHistory = this.instantiationService.createInstance(CommandsHistory); - this.configurationService.onDidUpdateConfiguration(e => this.updateConfiguration()); + this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration()); this.updateConfiguration(); } diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index 854fbca08ae..988464d7332 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -58,7 +58,7 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration(), true))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration(), true))); this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => setTimeout(() => this.handleWorkbenchState()))); } diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index 02616fb2a13..e69496fafdb 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -90,7 +90,7 @@ export class FileDecorations implements IWorkbenchContribution { @IConfigurationService private _configurationService: IConfigurationService, @ISCMService private _scmService: ISCMService, ) { - this._configListener = this._configurationService.onDidUpdateConfiguration(e => e.affectsConfiguration('scm.fileDecorations.enabled') && this._update()); + this._configListener = this._configurationService.onDidChangeConfiguration(e => e.affectsConfiguration('scm.fileDecorations.enabled') && this._update()); this._update(); } diff --git a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts index 16acf16b142..7e9faa28fd4 100644 --- a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts +++ b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts @@ -148,7 +148,7 @@ export class OpenAnythingHandler extends QuickOpenHandler { } private registerListeners(): void { - this.configurationService.onDidUpdateConfiguration(e => this.updateHandlers(this.configurationService.getConfiguration())); + this.configurationService.onDidChangeConfiguration(e => this.updateHandlers(this.configurationService.getConfiguration())); } private updateHandlers(configuration: IWorkbenchSearchConfiguration): void { diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 3ccba8cd491..14c8cddf519 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -620,7 +620,7 @@ class TaskService extends EventEmitter implements ITaskService { this._taskSystemListeners = []; this._outputChannel = this.outputService.getChannel(TaskService.OutputChannelId); this._providers = new Map(); - this.configurationService.onDidUpdateConfiguration(() => { + this.configurationService.onDidChangeConfiguration(() => { if (!this._taskSystem && !this._workspaceTasksPromise) { return; } diff --git a/src/vs/workbench/parts/terminal/common/terminalService.ts b/src/vs/workbench/parts/terminal/common/terminalService.ts index 5ccb2a29e65..44815065a04 100644 --- a/src/vs/workbench/parts/terminal/common/terminalService.ts +++ b/src/vs/workbench/parts/terminal/common/terminalService.ts @@ -59,7 +59,7 @@ export abstract class TerminalService implements ITerminalService { this._onInstanceTitleChanged = new Emitter(); this._onInstancesChanged = new Emitter(); - this._configurationService.onDidUpdateConfiguration(() => this.updateConfig()); + this._configurationService.onDidChangeConfiguration(() => this.updateConfig()); lifecycleService.onWillShutdown(event => event.veto(this._onWillShutdown())); this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService); this._findWidgetVisible = KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE.bindTo(this._contextKeyService); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 2ec3fb4ed98..d382d1f2aa5 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -74,7 +74,7 @@ export class TerminalPanel extends Panel { this._terminalService.setContainers(this.getContainer().getHTMLElement(), this._terminalContainer); this._register(this.themeService.onThemeChange(theme => this._updateTheme(theme))); - this._register(this._configurationService.onDidUpdateConfiguration(() => this._updateFont())); + this._register(this._configurationService.onDidChangeConfiguration(() => this._updateFont())); this._updateFont(); this._updateTheme(); diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts index d38ab62eea9..2fb9993bf0a 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -23,7 +23,7 @@ class MockConfigurationService implements IConfigurationService { public getValue(key: string, overrides?: IConfigurationOverrides): T { return getConfigurationValue(this.getConfiguration(), key); } public updateValue(): TPromise { return null; } public getConfigurationData(): any { return null; } - public onDidUpdateConfiguration() { return { dispose() { } }; } + public onDidChangeConfiguration() { return { dispose() { } }; } public reloadConfiguration() { return null; } } diff --git a/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts b/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts index 21dbeb9472c..a008c9c954f 100644 --- a/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts +++ b/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts @@ -35,7 +35,7 @@ class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution @IStorageService private storageService: IStorageService ) { lifecycleService.onShutdown(this.dispose, this); - this.toDispose.push(this.workspaceConfigurationService.onDidUpdateConfiguration(e => this.checkWorkspaceSettings())); + this.toDispose.push(this.workspaceConfigurationService.onDidChangeConfiguration(e => this.checkWorkspaceSettings())); } getId(): string { diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index ec6aa876b65..8acbac70b41 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -126,7 +126,7 @@ export class WatermarkContribution implements IWorkbenchContribution { this.create(); } }); - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => { + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(WORKBENCH_TIPS_ENABLED_KEY)) { const enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); if (enabled !== this.enabled) { diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts index 173483768ba..8c3e14e3123 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts @@ -401,7 +401,7 @@ export class WalkThroughPart extends BaseEditor { } })); - this.contentDisposables.push(this.configurationService.onDidUpdateConfiguration(() => { + this.contentDisposables.push(this.configurationService.onDidChangeConfiguration(() => { if (snippet.textEditorModel) { editor.updateOptions(this.getEditorOptions(snippet.textEditorModel.getModeId())); } @@ -452,7 +452,7 @@ export class WalkThroughPart extends BaseEditor { }); this.updateSizeClasses(); this.multiCursorModifier(); - this.contentDisposables.push(this.configurationService.onDidUpdateConfiguration(() => this.multiCursorModifier())); + this.contentDisposables.push(this.configurationService.onDidChangeConfiguration(() => this.multiCursorModifier())); if (input.onReady) { input.onReady(innerContent); } diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index d83c8b0d642..262151b6a7b 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -61,8 +61,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private workspaceConfiguration: WorkspaceConfiguration; private cachedFolderConfigs: StrictResourceMap; - protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); - public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + protected readonly _onDidChangeConfiguration: Emitter = this._register(new Emitter()); + public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; protected readonly _onDidChangeWorkspaceFolders: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceFolders.event; @@ -82,7 +82,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat this._register(this.workspaceConfiguration.onDidUpdateConfiguration(() => this.onWorkspaceConfigurationChanged())); this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService)); - this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); + this._register(this.baseConfigurationService.onDidChangeConfiguration(e => this.onBaseConfigurationChanged(e))); this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(e => this.registerConfigurationSchemas())); } @@ -328,7 +328,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // TODO Sandy: compare with old values?? const keys = this._configuration.keys(); - this._onDidUpdateConfiguration.fire(new AllKeysConfigurationChangeEvent([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE))); + this._onDidChangeConfiguration.fire(new AllKeysConfigurationChangeEvent([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE))); }); } @@ -520,7 +520,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private triggerConfigurationChange(configurationEvent: ConfigurationChangeEvent, target: ConfigurationTarget): void { if (configurationEvent.affectedKeys.length) { configurationEvent.telemetryData(target, this.getTargetConfiguration(target)); - this._onDidUpdateConfiguration.fire(new WorkspaceConfigurationChangeEvent(configurationEvent, this.workspace)); + this._onDidChangeConfiguration.fire(new WorkspaceConfigurationChangeEvent(configurationEvent, this.workspace)); } } diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index 5c6763edb10..211e1f66128 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -196,7 +196,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); return service.initialize(workspaceDir).then(() => { - service.onDidUpdateConfiguration(event => { + service.onDidChangeConfiguration(event => { const config = service.getConfiguration<{ testworkbench: { editor: { tabs: boolean } } }>(); assert.equal(config.testworkbench.editor.tabs, false); @@ -279,7 +279,7 @@ suite('WorkspaceConfigurationService - Node', () => { test('workspace change triggers event', (done: () => void) => { createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { return createService(workspaceDir, globalSettingsFile).then(service => { - service.onDidUpdateConfiguration(event => { + service.onDidChangeConfiguration(event => { const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean } } }>(); assert.equal(config.testworkbench.editor.icons, true); assert.equal(service.getConfiguration().testworkbench.editor.icons, true); @@ -305,7 +305,7 @@ suite('WorkspaceConfigurationService - Node', () => { fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": true }'); const target = sinon.stub(); - service.onDidUpdateConfiguration(event => target()); + service.onDidChangeConfiguration(event => target()); fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": false }'); @@ -327,7 +327,7 @@ suite('WorkspaceConfigurationService - Node', () => { service.reloadWorkspaceConfiguration().done(() => { const target = sinon.stub(); - service.onDidUpdateConfiguration(event => target()); + service.onDidChangeConfiguration(event => target()); service.reloadWorkspaceConfiguration().done(() => { assert.ok(!target.called); @@ -344,7 +344,7 @@ suite('WorkspaceConfigurationService - Node', () => { createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { return createService(workspaceDir, globalSettingsFile).then(service => { const target = sinon.stub(); - service.onDidUpdateConfiguration(event => target()); + service.onDidChangeConfiguration(event => target()); service.reloadUserConfiguration().done(() => { assert.ok(!target.called); service.dispose(); diff --git a/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts index 2360f632988..fce774139c1 100644 --- a/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts @@ -354,7 +354,7 @@ class MockConfigurationService implements IConfigurationService { public getValue(key: string): any { return getConfigurationValue(this.getConfiguration(), key); } public updateValue(): TPromise { return null; } public getConfigurationData(): any { return null; } - public onDidUpdateConfiguration() { return { dispose() { } }; } + public onDidChangeConfiguration() { return { dispose() { } }; } public reloadConfiguration() { return null; } } diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index d2c61424a26..270f2367a64 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -119,7 +119,7 @@ export class FileService implements IFileService { this.toUnbind.push(this.raw.onAfterOperation(e => this._onAfterOperation.fire(e))); // Config changes - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); // Root changes this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); diff --git a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts index 05a68b0cb7a..6c54ae8d675 100644 --- a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts @@ -83,7 +83,7 @@ export class FileWatcher { // Start watching this.updateFolders(); this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateFolders())); - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => this.updateFolders())); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.updateFolders())); return () => this.dispose(); } diff --git a/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts index 9634a27da63..562e8972512 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts @@ -268,7 +268,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { super(contextKeyService, commandService, telemetryService, messageService, statusBarService); let dispatchConfig = getDispatchConfig(configurationService); - configurationService.onDidUpdateConfiguration((e) => { + configurationService.onDidChangeConfiguration((e) => { let newDispatchConfig = getDispatchConfig(configurationService); if (dispatchConfig === newDispatchConfig) { return; diff --git a/src/vs/workbench/services/mode/common/workbenchModeService.ts b/src/vs/workbench/services/mode/common/workbenchModeService.ts index 7b59087af60..abd67ba5a18 100644 --- a/src/vs/workbench/services/mode/common/workbenchModeService.ts +++ b/src/vs/workbench/services/mode/common/workbenchModeService.ts @@ -123,7 +123,7 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { }); - this._configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this._configurationService.getConfiguration())); + this._configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this._configurationService.getConfiguration())); this.onDidCreateMode((mode) => { this._extensionService.activateByEvent(`onLanguage:${mode.getId()}`).done(null, onUnexpectedError); diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 5dfbcde38a9..27a19245296 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -124,7 +124,7 @@ export abstract class TextFileService implements ITextFileService { this.lifecycleService.onShutdown(this.dispose, this); // Configuration changes - this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); } private beforeShutdown(reason: ShutdownReason): boolean | TPromise { diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 702a85b0baf..572299fd514 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -235,7 +235,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } private installConfigurationListener() { - this.configurationService.onDidUpdateConfiguration(e => { + this.configurationService.onDidChangeConfiguration(e => { let colorThemeSetting = this.configurationService.getValue(COLOR_THEME_SETTING); if (colorThemeSetting !== this.currentColorTheme.settingsId) { this.colorThemeStore.findThemeDataBySettingsId(colorThemeSetting, null).then(theme => { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index b07ab0b7f95..8bfdf7f0f46 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -1211,7 +1211,7 @@ export class TestTextResourceConfigurationService implements ITextResourceConfig constructor(private configurationService = new TestConfigurationService()) { } - public onDidUpdateConfiguration() { + public onDidChangeConfiguration() { return { dispose() { } }; } From 572c7ba2b4650b8626a65b3cccb7f5bfc65b31e2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 Oct 2017 11:15:46 +0200 Subject: [PATCH 159/394] deco - expose decorations as proposed api --- src/vs/vscode.proposed.d.ts | 22 +++++++ .../extensionHost.contribution.ts | 1 + .../electron-browser/mainThreadDecorations.ts | 64 +++++++++++++++++++ src/vs/workbench/api/node/extHost.api.impl.ts | 5 ++ src/vs/workbench/api/node/extHost.protocol.ts | 15 +++++ .../workbench/api/node/extHostDecorations.ts | 47 ++++++++++++++ .../markers/browser/markersFileDecorations.ts | 1 + .../electron-browser/scmFileDecorations.ts | 3 +- .../decorations/browser/decorations.ts | 1 + .../decorations/browser/decorationsService.ts | 13 +++- .../test/browser/decorationsService.test.ts | 39 +++++++++++ 11 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 src/vs/workbench/api/electron-browser/mainThreadDecorations.ts create mode 100644 src/vs/workbench/api/node/extHostDecorations.ts diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 0c5dba2a3e5..e8485b673fc 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -168,4 +168,26 @@ declare module 'vscode' { */ export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable; } + + //#region decorations + + //todo@joh -> make class + export interface DecorationData { + priority?: number; + title?: string; + abbreviation?: string; + color?: ThemeColor; + opacity?: number; + } + + export interface DecorationProvider { + onDidChangeDecorations: Event; + provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; + } + + export namespace window { + export function registerDecorationProvider(provider: DecorationProvider, label: string): Disposable; + } + + //#endregion } diff --git a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts index be065d33308..2940cda2e51 100644 --- a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts @@ -19,6 +19,7 @@ import './mainThreadCommands'; import './mainThreadConfiguration'; import './mainThreadCredentials'; import './mainThreadDebugService'; +import './mainThreadDecorations'; import './mainThreadDiagnostics'; import './mainThreadDialogs'; import './mainThreadDocumentContentProviders'; diff --git a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts new file mode 100644 index 00000000000..1dd8523ff44 --- /dev/null +++ b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts @@ -0,0 +1,64 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import URI from 'vs/base/common/uri'; +import { Emitter } from 'vs/base/common/event'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { ExtHostContext, MainContext, IExtHostContext, MainThreadDecorationsShape, ExtHostDecorationsShape } from '../node/extHost.protocol'; +import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; + +@extHostNamedCustomer(MainContext.MainThreadDecorations) +export class MainThreadDecorations implements MainThreadDecorationsShape { + + private readonly _provider = new Map, IDisposable]>(); + private readonly _proxy: ExtHostDecorationsShape; + + constructor( + context: IExtHostContext, + @IDecorationsService private readonly _decorationsService: IDecorationsService + ) { + this._proxy = context.get(ExtHostContext.ExtHostDecorations); + } + + dispose() { + this._provider.forEach(value => dispose(value)); + this._provider.clear(); + } + + $registerDecorationProvider(handle: number, label: string): void { + let emitter = new Emitter(); + let registration = this._decorationsService.registerDecorationsProvider({ + label, + onDidChange: emitter.event, + provideDecorations: (uri) => { + return this._proxy.$providerDecorations(handle, uri).then(data => { + const [weight, title, letter, opacity, themeColor] = data; + return { + weight: weight || 0, + title, + letter, + opacity, + color: themeColor && themeColor.id + }; + }); + } + }); + this._provider.set(handle, [emitter, registration]); + } + + $onDidChange(handle: number, resources: URI[]): void { + const [emitter] = this._provider.get(handle); + emitter.fire(resources); + } + + $unregisterDecorationProvider(handle: number): void { + if (this._provider.has(handle)) { + dispose(this._provider.get(handle)); + this._provider.delete(handle); + } + } +} diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 32af7291dfc..73c966c463e 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -55,6 +55,7 @@ import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadServi import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs'; import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem'; import { FileChangeType, FileType } from 'vs/platform/files/common/files'; +import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations'; export interface IExtensionApiFactory { (extension: IExtensionDescription): typeof vscode; @@ -83,6 +84,7 @@ export function createApiFactory( // Addressable instances const extHostHeapService = threadService.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService()); + const extHostDecorations = threadService.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(threadService)); const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService)); const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors)); const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors)); @@ -376,6 +378,9 @@ export function createApiFactory( sampleFunction: proposedApiFunction(extension, () => { return extHostMessageService.showMessage(extension, Severity.Info, 'Hello Proposed Api!', {}, []); }), + registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider, label: string) => { + return extHostDecorations.registerDecorationProvider(provider, label); + }) }; // namespace: workspace diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index d07165fce5a..eee71c3f13d 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -135,6 +135,12 @@ export interface MainThreadDiaglogsShape extends IDisposable { $showSaveDialog(options: MainThreadDialogSaveOptions): TPromise; } +export interface MainThreadDecorationsShape extends IDisposable { + $registerDecorationProvider(handle: number, label: string): void; + $unregisterDecorationProvider(handle: number): void; + $onDidChange(handle: number, resources: URI[]): void; +} + export interface MainThreadDocumentContentProvidersShape extends IDisposable { $registerTextContentProvider(handle: number, scheme: string): void; $unregisterTextContentProvider(handle: number): void; @@ -596,6 +602,13 @@ export interface ExtHostDebugServiceShape { $acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void; } + +export type DecorationData = [number, string, string, number, ThemeColor]; + +export interface ExtHostDecorationsShape { + $providerDecorations(handle: number, uri: URI): TPromise; +} + export interface ExtHostCredentialsShape { } @@ -609,6 +622,7 @@ export const MainContext = { MainThreadCommands: createMainId('MainThreadCommands'), MainThreadConfiguration: createMainId('MainThreadConfiguration'), MainThreadDebugService: createMainId('MainThreadDebugService'), + MainThreadDecorations: createMainId('MainThreadDecorations'), MainThreadDiagnostics: createMainId('MainThreadDiagnostics'), MainThreadDialogs: createMainId('MainThreadDiaglogs'), MainThreadDocuments: createMainId('MainThreadDocuments'), @@ -640,6 +654,7 @@ export const ExtHostContext = { ExtHostConfiguration: createExtId('ExtHostConfiguration'), ExtHostDiagnostics: createExtId('ExtHostDiagnostics'), ExtHostDebugService: createExtId('ExtHostDebugService'), + ExtHostDecorations: createExtId('ExtHostDecorations'), ExtHostDocumentsAndEditors: createExtId('ExtHostDocumentsAndEditors'), ExtHostDocuments: createExtId('ExtHostDocuments'), ExtHostDocumentContentProviders: createExtId('ExtHostDocumentContentProviders'), diff --git a/src/vs/workbench/api/node/extHostDecorations.ts b/src/vs/workbench/api/node/extHostDecorations.ts new file mode 100644 index 00000000000..05b93b96f33 --- /dev/null +++ b/src/vs/workbench/api/node/extHostDecorations.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as vscode from 'vscode'; +import URI from 'vs/base/common/uri'; +import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData } from 'vs/workbench/api/node/extHost.protocol'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Disposable } from 'vs/workbench/api/node/extHostTypes'; +import { asWinJsPromise } from 'vs/base/common/async'; + +export class ExtHostDecorations implements ExtHostDecorationsShape { + + private static _handlePool = 0; + + private readonly _provider = new Map(); + private readonly _proxy: MainThreadDecorationsShape; + + constructor(mainContext: IMainContext) { + this._proxy = mainContext.get(MainContext.MainThreadDecorations); + } + + registerDecorationProvider(provider: vscode.DecorationProvider, label: string): vscode.Disposable { + const handle = ExtHostDecorations._handlePool++; + this._provider.set(handle, provider); + this._proxy.$registerDecorationProvider(handle, label); + + const listener = provider.onDidChangeDecorations(e => { + this._proxy.$onDidChange(handle, Array.isArray(e) ? e : [e]); + }); + + return new Disposable(() => { + listener.dispose(); + this._proxy.$unregisterDecorationProvider(handle); + this._provider.delete(handle); + }); + } + + $providerDecorations(handle: number, uri: URI): TPromise { + const provider = this._provider.get(handle); + return asWinJsPromise(token => provider.provideDecoration(uri, token)).then(data => { + return [data.priority, data.title, data.abbreviation, data.opacity, data.color]; + }); + } +} diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts index d9a6ce584da..9dd0ce444fb 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts @@ -44,6 +44,7 @@ class MarkersDecorationsProvider implements IDecorationsProvider { return { weight: 100 * first.severity, + bubble: true, title: markers.length === 1 ? localize('tooltip.1', "1 problem in this file") : localize('tooltip.N', "{0} problems in this file", markers.length), letter: markers.length.toString(), color: first.severity === Severity.Error ? editorErrorForeground : editorWarningForeground, diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts index e69496fafdb..23e0d15fdae 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts @@ -65,7 +65,8 @@ class SCMDecorationsProvider implements IDecorationsProvider { return undefined; } return { - weight: 100 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0), + bubble: true, + weight: 255 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0), title: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label), color: resource.decorations.color, letter: resource.decorations.tooltip.charAt(0) diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 25401fd795a..6a5b7993205 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -18,6 +18,7 @@ export interface IDecorationData { readonly opacity?: number; readonly letter?: string; readonly title?: string; + readonly bubble?: boolean; } export interface IDecoration { diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 9792da756f4..ddbf12c6133 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -347,6 +347,12 @@ export class FileDecorationsService implements IDecorationsService { this._onDidChangeDecorationsDelayed ); const remove = this._data.push(wrapper); + + this._onDidChangeDecorations.fire({ + // everything might have changed + affectsResource() { return true; } + }); + return { dispose: () => { // fire event that says 'yes' for any resource @@ -363,9 +369,10 @@ export class FileDecorationsService implements IDecorationsService { let onlyChildren = true; for (let iter = this._data.iterator(), next = iter.next(); !next.done; next = iter.next()) { next.value.getOrRetrieve(uri, includeChildren, (deco, isChild) => { - // top = FileDecorationsService._pickBest(top, candidate); - data.push(deco); - onlyChildren = onlyChildren && isChild; + if (!isChild || deco.bubble) { + data.push(deco); + onlyChildren = onlyChildren && isChild; + } }); } diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index 21708a3b55d..721051fb31a 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -103,4 +103,43 @@ suite('DecorationsService', function () { reg.dispose(); assert.equal(didSeeEvent, true); }); + + test('No default bubbling', function () { + + let reg = service.registerDecorationsProvider({ + label: 'Test', + onDidChange: Event.None, + provideDecorations(uri: URI) { + return uri.path.match(/\.txt/) + ? { title: '.txt' } + : undefined; + } + }); + + let childUri = URI.parse('file:///some/path/some/file.txt'); + + let deco = service.getDecoration(childUri, false); + assert.equal(deco.title, '.txt'); + + deco = service.getDecoration(childUri.with({ path: 'some/path/' }), true); + assert.equal(deco, undefined); + reg.dispose(); + + // bubble + reg = service.registerDecorationsProvider({ + label: 'Test', + onDidChange: Event.None, + provideDecorations(uri: URI) { + return uri.path.match(/\.txt/) + ? { title: '.txt.bubble', bubble: true } + : undefined; + } + }); + + deco = service.getDecoration(childUri, false); + assert.equal(deco.title, '.txt.bubble'); + + deco = service.getDecoration(childUri.with({ path: 'some/path/' }), true); + assert.equal(deco.title, '.txt.bubble'); + }); }); From 506eea19ef5d6038995dd7bf4fc5bd7a685257ca Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 Oct 2017 11:27:14 +0200 Subject: [PATCH 160/394] fix explorer exploding --- src/vs/workbench/parts/files/browser/views/explorerView.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index b831fcb8ac4..2c2d45cb9c6 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -275,8 +275,8 @@ export class ExplorerView extends ViewsViewletPanel { || event.affectsConfiguration('explorer.decorations.badges'); } - // Refresh viewer as needed - if (needsRefresh) { + // Refresh viewer as needed if this originates from a config event + if (event && needsRefresh) { this.doRefresh().done(null, errors.onUnexpectedError); } } From 015901f14b5268c9874753cd7695f408b55052e9 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 17 Oct 2017 11:27:52 +0200 Subject: [PATCH 161/394] return threadId as the context for actions in the callstack view fixes #36394 --- src/vs/workbench/parts/debug/electron-browser/debugViewer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index 521ebfd16d0..bc97bf770ba 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -282,6 +282,9 @@ export class CallStackController extends BaseDebugController { return element.source.uri.toString(); } + if (element instanceof Thread) { + return element.threadId; + } } // user clicked / pressed on 'Load More Stack Frames', get those stack frames and refresh the tree. From 400afdbd4428fb3a2e0201bd4e631edda79a51f5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 11:33:27 +0200 Subject: [PATCH 162/394] Reduce reliance on _addMarker for cursor tracking --- src/vs/editor/common/controller/oneCursor.ts | 51 ++++++++++++--- src/vs/editor/common/editorCommon.ts | 10 +++ src/vs/editor/common/model/textModel.ts | 2 + .../common/model/textModelWithDecorations.ts | 63 ++++++++++++++++--- 4 files changed, 109 insertions(+), 17 deletions(-) diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index ae9c990ec4a..8e96e9130b8 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -8,6 +8,8 @@ import { SingleCursorState, CursorContext, CursorState } from 'vs/editor/common/ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection, SelectionDirection } from 'vs/editor/common/core/selection'; +import { TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; +import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; export class OneCursor { @@ -17,7 +19,19 @@ export class OneCursor { private _selStartMarker: string; private _selEndMarker: string; + private _selTrackedRange: string; + constructor(context: CursorContext) { + this.modelState = null; + this.viewState = null; + + if (USE_NEW_DECORATIONS) { + this._selTrackedRange = null; + } else { + this._selStartMarker = null; + this._selEndMarker = null; + } + this._setState( context, new SingleCursorState(new Range(1, 1, 1, 1), 0, new Position(1, 1), 0), @@ -26,8 +40,12 @@ export class OneCursor { } public dispose(context: CursorContext): void { - context.model._removeMarker(this._selStartMarker); - context.model._removeMarker(this._selEndMarker); + if (USE_NEW_DECORATIONS) { + this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, null, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + } else { + context.model._removeMarker(this._selStartMarker); + context.model._removeMarker(this._selEndMarker); + } } public asCursorState(): CursorState { @@ -35,14 +53,23 @@ export class OneCursor { } public readSelectionFromMarkers(context: CursorContext): Selection { - const start = context.model._getMarker(this._selStartMarker); - const end = context.model._getMarker(this._selEndMarker); + if (USE_NEW_DECORATIONS) { + const range = context.model._getTrackedRange(this._selTrackedRange); + if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { + return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); + } - if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { - return new Selection(start.lineNumber, start.column, end.lineNumber, end.column); + return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn); + } else { + const start = context.model._getMarker(this._selStartMarker); + const end = context.model._getMarker(this._selEndMarker); + + if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { + return new Selection(start.lineNumber, start.column, end.lineNumber, end.column); + } + + return new Selection(end.lineNumber, end.column, start.lineNumber, start.column); } - - return new Selection(end.lineNumber, end.column, start.lineNumber, start.column); } public ensureValidState(context: CursorContext): void { @@ -100,8 +127,12 @@ export class OneCursor { this.modelState = modelState; this.viewState = viewState; - this._selStartMarker = this._ensureMarker(context, this._selStartMarker, this.modelState.selection.startLineNumber, this.modelState.selection.startColumn, true); - this._selEndMarker = this._ensureMarker(context, this._selEndMarker, this.modelState.selection.endLineNumber, this.modelState.selection.endColumn, false); + if (USE_NEW_DECORATIONS) { + this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + } else { + this._selStartMarker = this._ensureMarker(context, this._selStartMarker, this.modelState.selection.startLineNumber, this.modelState.selection.startColumn, true); + this._selEndMarker = this._ensureMarker(context, this._selEndMarker, this.modelState.selection.endLineNumber, this.modelState.selection.endColumn, false); + } } private _ensureMarker(context: CursorContext, markerId: string, lineNumber: number, column: number, stickToPreviousCharacter: boolean): string { diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 837485b70a9..6fb2a079656 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -1041,6 +1041,16 @@ export interface ITextModelWithDecorations { * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). */ getOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + + /** + * @internal + */ + _getTrackedRange(id: string): Range; + + /** + * @internal + */ + _deltaTrackedRange(id: string, newRange: Range, newStickiness: TrackedRangeStickiness): string; } /** diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 4af332e8f14..493af0fb037 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -8,6 +8,7 @@ import { OrderGuaranteeEventEmitter, BulkListenerCallback } from 'vs/base/common import * as strings from 'vs/base/common/strings'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range, IRange } from 'vs/editor/common/core/range'; +import { Selection } from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { ModelLine, IModelLine, MinimalModelLine } from 'vs/editor/common/model/modelLine'; import { guessIndentation } from 'vs/editor/common/model/indentationGuesser'; @@ -670,6 +671,7 @@ export class TextModel implements editorCommon.ITextModel { && initialEndLineNumber === endLineNumber && initialEndColumn === endColumn && range instanceof Range + && !(range instanceof Selection) ) { return range; } diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index b4289f3aedd..fc0b8921c38 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -228,7 +228,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed let changeAccessor: editorCommon.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: editorCommon.IModelDecorationOptions): string => { if (USE_NEW_DECORATIONS) { - return this._deltaDecorationsImpl2(decorationsTracker, ownerId, [], [{ range: range, options: options }])[0]; + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + return this._deltaDecorationsImpl2(ownerId, [], [{ range: range, options: options }])[0]; } return this._addDecorationImpl(decorationsTracker, ownerId, this.validateRange(range), _normalizeOptions(options)); }, @@ -248,14 +250,18 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed }, removeDecoration: (id: string): void => { if (USE_NEW_DECORATIONS) { - this._deltaDecorationsImpl2(decorationsTracker, ownerId, [id], []); + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + this._deltaDecorationsImpl2(ownerId, [id], []); return; } this._removeDecorationImpl(decorationsTracker, id); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { if (USE_NEW_DECORATIONS) { - return this._deltaDecorationsImpl2(decorationsTracker, ownerId, oldDecorations, newDecorations); + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + return this._deltaDecorationsImpl2(ownerId, oldDecorations, newDecorations); } return this._deltaDecorationsImpl(decorationsTracker, ownerId, oldDecorations, this._normalizeDeltaDecorations(newDecorations)); } @@ -284,6 +290,41 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed }, ownerId); } + _getTrackedRange(id: string): Range { + return this.getDecorationRange(id); + } + + _deltaTrackedRange(id: string, newRange: Range, newStickiness: editorCommon.TrackedRangeStickiness): string { + const node = (id ? this._treeDecorations[id] : null); + + if (!node) { + if (!newRange) { + // node doesn't exist, the request is to delete => nothing to do + return null; + } + // node doesn't exist, the request is to set => add the tracked range + return this._deltaDecorationsImpl2(0, [], [{ range: newRange, options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0]; + } + + if (!newRange) { + // node exists, the request is to delete => delete node + this._tree.delete(node); + delete this._treeDecorations[node.id]; + return null; + } + + // node exists, the request is to set => change the tracked range and its options + const range = this._validateRangeRelaxedNoAllocations(newRange); + this._ensureLineStarts(); + const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; + this._tree.delete(node); + node.reset(this.getVersionId(), startOffset, endOffset, range); + node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]); + this._tree.insert(node); + return node.id; + } + public removeAllDecorationsWithOwnerId(ownerId: number): void { if (USE_NEW_DECORATIONS) { const nodes = this._tree.collectNodesFromOwner(ownerId); @@ -798,6 +839,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed if (!node) { return; } + this._ensureLineStarts(); const range = this._validateRangeRelaxedNoAllocations(_range); const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; @@ -981,7 +1023,7 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return result; } - private _deltaDecorationsImpl2(decorationsTracker: DecorationsTracker, ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { + private _deltaDecorationsImpl2(ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { this._ensureLineStarts(); const versionId = this.getVersionId(); @@ -1040,9 +1082,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } } - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - return result; } } @@ -1158,6 +1197,16 @@ export class ModelDecorationOptions implements editorCommon.IModelDecorationOpti } ModelDecorationOptions.EMPTY = ModelDecorationOptions.register({}); +/** + * The order carefully matches the values of the enum. + */ +const TRACKED_RANGE_OPTIONS = [ + ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges }), + ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }), + ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore }), + ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter }), +]; + class ModelDeltaDecoration implements editorCommon.IModelDeltaDecoration { _modelDeltaDecorationBrand: void; From a93953101ea49b2559f303c69f26c0d762cb31de Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 12:12:16 +0200 Subject: [PATCH 163/394] Further reduce reliance on _addMarker for editing commands selection tracking --- src/vs/editor/common/controller/cursor.ts | 113 ++++++++++++++++------ 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 65bc4059e5c..a6227965aa7 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -20,6 +20,7 @@ import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import Event, { Emitter } from 'vs/base/common/event'; +import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; function containsLineMappingChanged(events: viewEvents.ViewEvent[]): boolean { for (let i = 0, len = events.length; i < len; i++) { @@ -557,6 +558,8 @@ interface IExecContext { readonly selectionsBefore: Selection[]; readonly selectionStartMarkers: string[]; readonly positionMarkers: string[]; + readonly trackedRanges: string[]; + readonly trackedRangesDirection: SelectionDirection[]; } interface ICommandData { @@ -577,14 +580,22 @@ class CommandExecutor { model: model, selectionsBefore: selectionsBefore, selectionStartMarkers: [], - positionMarkers: [] + positionMarkers: [], + trackedRanges: [], + trackedRangesDirection: [] }; const result = this._innerExecuteCommands(ctx, commands); - for (let i = 0; i < ctx.selectionStartMarkers.length; i++) { - ctx.model._removeMarker(ctx.selectionStartMarkers[i]); - ctx.model._removeMarker(ctx.positionMarkers[i]); + if (USE_NEW_DECORATIONS) { + for (let i = 0, len = ctx.trackedRanges.length; i < len; i++) { + ctx.model._deltaTrackedRange(ctx.trackedRanges[i], null, editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + } + } else { + for (let i = 0; i < ctx.selectionStartMarkers.length; i++) { + ctx.model._removeMarker(ctx.selectionStartMarkers[i]); + ctx.model._removeMarker(ctx.positionMarkers[i]); + } } return result; @@ -661,9 +672,17 @@ class CommandExecutor { getTrackedSelection: (id: string) => { const idx = parseInt(id, 10); - const selectionStartMarker = ctx.model._getMarker(ctx.selectionStartMarkers[idx]); - const positionMarker = ctx.model._getMarker(ctx.positionMarkers[idx]); - return new Selection(selectionStartMarker.lineNumber, selectionStartMarker.column, positionMarker.lineNumber, positionMarker.column); + if (USE_NEW_DECORATIONS) { + const range = ctx.model._getTrackedRange(ctx.trackedRanges[idx]); + if (ctx.trackedRangesDirection[idx] === SelectionDirection.LTR) { + return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); + } + return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn); + } else { + const selectionStartMarker = ctx.model._getMarker(ctx.selectionStartMarkers[idx]); + const positionMarker = ctx.model._getMarker(ctx.positionMarkers[idx]); + return new Selection(selectionStartMarker.lineNumber, selectionStartMarker.column, positionMarker.lineNumber, positionMarker.column); + } } }); } else { @@ -750,38 +769,68 @@ class CommandExecutor { }; const trackSelection = (selection: Selection, trackPreviousOnEmpty?: boolean) => { - let selectionMarkerStickToPreviousCharacter: boolean; - let positionMarkerStickToPreviousCharacter: boolean; - - if (selection.isEmpty()) { - // Try to lock it with surrounding text - if (typeof trackPreviousOnEmpty === 'boolean') { - selectionMarkerStickToPreviousCharacter = trackPreviousOnEmpty; - positionMarkerStickToPreviousCharacter = trackPreviousOnEmpty; + if (USE_NEW_DECORATIONS) { + let stickiness: editorCommon.TrackedRangeStickiness; + if (selection.isEmpty()) { + if (typeof trackPreviousOnEmpty === 'boolean') { + if (trackPreviousOnEmpty) { + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore; + } else { + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter; + } + } else { + // Try to lock it with surrounding text + const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber); + if (selection.startColumn === maxLineColumn) { + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore; + } else { + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter; + } + } } else { - const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber); - if (selection.startColumn === maxLineColumn) { - selectionMarkerStickToPreviousCharacter = true; + stickiness = editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges; + } + + const l = ctx.trackedRanges.length; + const id = ctx.model._deltaTrackedRange(null, selection, stickiness); + ctx.trackedRanges[l] = id; + ctx.trackedRangesDirection[l] = selection.getDirection(); + return l.toString(); + + } else { + let selectionMarkerStickToPreviousCharacter: boolean; + let positionMarkerStickToPreviousCharacter: boolean; + + if (selection.isEmpty()) { + // Try to lock it with surrounding text + if (typeof trackPreviousOnEmpty === 'boolean') { + selectionMarkerStickToPreviousCharacter = trackPreviousOnEmpty; + positionMarkerStickToPreviousCharacter = trackPreviousOnEmpty; + } else { + const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber); + if (selection.startColumn === maxLineColumn) { + selectionMarkerStickToPreviousCharacter = true; + positionMarkerStickToPreviousCharacter = true; + } else { + selectionMarkerStickToPreviousCharacter = false; + positionMarkerStickToPreviousCharacter = false; + } + } + } else { + if (selection.getDirection() === SelectionDirection.LTR) { + selectionMarkerStickToPreviousCharacter = false; positionMarkerStickToPreviousCharacter = true; } else { - selectionMarkerStickToPreviousCharacter = false; + selectionMarkerStickToPreviousCharacter = true; positionMarkerStickToPreviousCharacter = false; } } - } else { - if (selection.getDirection() === SelectionDirection.LTR) { - selectionMarkerStickToPreviousCharacter = false; - positionMarkerStickToPreviousCharacter = true; - } else { - selectionMarkerStickToPreviousCharacter = true; - positionMarkerStickToPreviousCharacter = false; - } - } - const l = ctx.selectionStartMarkers.length; - ctx.selectionStartMarkers[l] = ctx.model._addMarker(0, selection.selectionStartLineNumber, selection.selectionStartColumn, selectionMarkerStickToPreviousCharacter); - ctx.positionMarkers[l] = ctx.model._addMarker(0, selection.positionLineNumber, selection.positionColumn, positionMarkerStickToPreviousCharacter); - return l.toString(); + const l = ctx.selectionStartMarkers.length; + ctx.selectionStartMarkers[l] = ctx.model._addMarker(0, selection.selectionStartLineNumber, selection.selectionStartColumn, selectionMarkerStickToPreviousCharacter); + ctx.positionMarkers[l] = ctx.model._addMarker(0, selection.positionLineNumber, selection.positionColumn, positionMarkerStickToPreviousCharacter); + return l.toString(); + } }; const editOperationBuilder: editorCommon.IEditOperationBuilder = { From 7b9e4aebffa5a5f9b2048199051002f7a9aad891 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 12:13:17 +0200 Subject: [PATCH 164/394] Flip the switch --- src/vs/editor/common/model/textModelWithDecorations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index fc0b8921c38..d912eb39530 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -19,7 +19,7 @@ import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; -export const USE_NEW_DECORATIONS = false; +export const USE_NEW_DECORATIONS = true; export const ClassName = { EditorInfoDecoration: 'infosquiggly', From 40f61d0b902c5f5b0933514a8afea7f25b381840 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 12:24:56 +0200 Subject: [PATCH 165/394] Remove old decorations implementation --- src/vs/editor/common/controller/cursor.ts | 102 +-- src/vs/editor/common/controller/oneCursor.ts | 55 +- src/vs/editor/common/model/textModel.ts | 1 + .../common/model/textModelWithDecorations.ts | 591 ++---------------- .../test/browser/snippetSession.test.ts | 13 +- .../common/model/modelDecorations.test.ts | 13 +- 6 files changed, 81 insertions(+), 694 deletions(-) diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index a6227965aa7..91ea1e17dcb 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -20,7 +20,6 @@ import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import Event, { Emitter } from 'vs/base/common/event'; -import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; function containsLineMappingChanged(events: viewEvents.ViewEvent[]): boolean { for (let i = 0, len = events.length; i < len; i++) { @@ -556,8 +555,6 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { interface IExecContext { readonly model: editorCommon.IModel; readonly selectionsBefore: Selection[]; - readonly selectionStartMarkers: string[]; - readonly positionMarkers: string[]; readonly trackedRanges: string[]; readonly trackedRangesDirection: SelectionDirection[]; } @@ -579,23 +576,14 @@ class CommandExecutor { const ctx: IExecContext = { model: model, selectionsBefore: selectionsBefore, - selectionStartMarkers: [], - positionMarkers: [], trackedRanges: [], trackedRangesDirection: [] }; const result = this._innerExecuteCommands(ctx, commands); - if (USE_NEW_DECORATIONS) { - for (let i = 0, len = ctx.trackedRanges.length; i < len; i++) { - ctx.model._deltaTrackedRange(ctx.trackedRanges[i], null, editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); - } - } else { - for (let i = 0; i < ctx.selectionStartMarkers.length; i++) { - ctx.model._removeMarker(ctx.selectionStartMarkers[i]); - ctx.model._removeMarker(ctx.positionMarkers[i]); - } + for (let i = 0, len = ctx.trackedRanges.length; i < len; i++) { + ctx.model._deltaTrackedRange(ctx.trackedRanges[i], null, editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } return result; @@ -672,17 +660,11 @@ class CommandExecutor { getTrackedSelection: (id: string) => { const idx = parseInt(id, 10); - if (USE_NEW_DECORATIONS) { - const range = ctx.model._getTrackedRange(ctx.trackedRanges[idx]); - if (ctx.trackedRangesDirection[idx] === SelectionDirection.LTR) { - return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); - } - return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn); - } else { - const selectionStartMarker = ctx.model._getMarker(ctx.selectionStartMarkers[idx]); - const positionMarker = ctx.model._getMarker(ctx.positionMarkers[idx]); - return new Selection(selectionStartMarker.lineNumber, selectionStartMarker.column, positionMarker.lineNumber, positionMarker.column); + const range = ctx.model._getTrackedRange(ctx.trackedRanges[idx]); + if (ctx.trackedRangesDirection[idx] === SelectionDirection.LTR) { + return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); } + return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn); } }); } else { @@ -769,68 +751,32 @@ class CommandExecutor { }; const trackSelection = (selection: Selection, trackPreviousOnEmpty?: boolean) => { - if (USE_NEW_DECORATIONS) { - let stickiness: editorCommon.TrackedRangeStickiness; - if (selection.isEmpty()) { - if (typeof trackPreviousOnEmpty === 'boolean') { - if (trackPreviousOnEmpty) { - stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore; - } else { - stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter; - } + let stickiness: editorCommon.TrackedRangeStickiness; + if (selection.isEmpty()) { + if (typeof trackPreviousOnEmpty === 'boolean') { + if (trackPreviousOnEmpty) { + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore; } else { - // Try to lock it with surrounding text - const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber); - if (selection.startColumn === maxLineColumn) { - stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore; - } else { - stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter; - } + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter; } } else { - stickiness = editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges; - } - - const l = ctx.trackedRanges.length; - const id = ctx.model._deltaTrackedRange(null, selection, stickiness); - ctx.trackedRanges[l] = id; - ctx.trackedRangesDirection[l] = selection.getDirection(); - return l.toString(); - - } else { - let selectionMarkerStickToPreviousCharacter: boolean; - let positionMarkerStickToPreviousCharacter: boolean; - - if (selection.isEmpty()) { // Try to lock it with surrounding text - if (typeof trackPreviousOnEmpty === 'boolean') { - selectionMarkerStickToPreviousCharacter = trackPreviousOnEmpty; - positionMarkerStickToPreviousCharacter = trackPreviousOnEmpty; + const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber); + if (selection.startColumn === maxLineColumn) { + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore; } else { - const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber); - if (selection.startColumn === maxLineColumn) { - selectionMarkerStickToPreviousCharacter = true; - positionMarkerStickToPreviousCharacter = true; - } else { - selectionMarkerStickToPreviousCharacter = false; - positionMarkerStickToPreviousCharacter = false; - } - } - } else { - if (selection.getDirection() === SelectionDirection.LTR) { - selectionMarkerStickToPreviousCharacter = false; - positionMarkerStickToPreviousCharacter = true; - } else { - selectionMarkerStickToPreviousCharacter = true; - positionMarkerStickToPreviousCharacter = false; + stickiness = editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter; } } - - const l = ctx.selectionStartMarkers.length; - ctx.selectionStartMarkers[l] = ctx.model._addMarker(0, selection.selectionStartLineNumber, selection.selectionStartColumn, selectionMarkerStickToPreviousCharacter); - ctx.positionMarkers[l] = ctx.model._addMarker(0, selection.positionLineNumber, selection.positionColumn, positionMarkerStickToPreviousCharacter); - return l.toString(); + } else { + stickiness = editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges; } + + const l = ctx.trackedRanges.length; + const id = ctx.model._deltaTrackedRange(null, selection, stickiness); + ctx.trackedRanges[l] = id; + ctx.trackedRangesDirection[l] = selection.getDirection(); + return l.toString(); }; const editOperationBuilder: editorCommon.IEditOperationBuilder = { diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 8e96e9130b8..f4be4b16a78 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -9,28 +9,19 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection, SelectionDirection } from 'vs/editor/common/core/selection'; import { TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; -import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; export class OneCursor { public modelState: SingleCursorState; public viewState: SingleCursorState; - private _selStartMarker: string; - private _selEndMarker: string; - private _selTrackedRange: string; constructor(context: CursorContext) { this.modelState = null; this.viewState = null; - if (USE_NEW_DECORATIONS) { - this._selTrackedRange = null; - } else { - this._selStartMarker = null; - this._selEndMarker = null; - } + this._selTrackedRange = null; this._setState( context, @@ -40,12 +31,7 @@ export class OneCursor { } public dispose(context: CursorContext): void { - if (USE_NEW_DECORATIONS) { - this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, null, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); - } else { - context.model._removeMarker(this._selStartMarker); - context.model._removeMarker(this._selEndMarker); - } + this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, null, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } public asCursorState(): CursorState { @@ -53,23 +39,11 @@ export class OneCursor { } public readSelectionFromMarkers(context: CursorContext): Selection { - if (USE_NEW_DECORATIONS) { - const range = context.model._getTrackedRange(this._selTrackedRange); - if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { - return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); - } - - return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn); - } else { - const start = context.model._getMarker(this._selStartMarker); - const end = context.model._getMarker(this._selEndMarker); - - if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { - return new Selection(start.lineNumber, start.column, end.lineNumber, end.column); - } - - return new Selection(end.lineNumber, end.column, start.lineNumber, start.column); + const range = context.model._getTrackedRange(this._selTrackedRange); + if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { + return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); } + return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn); } public ensureValidState(context: CursorContext): void { @@ -127,21 +101,6 @@ export class OneCursor { this.modelState = modelState; this.viewState = viewState; - if (USE_NEW_DECORATIONS) { - this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); - } else { - this._selStartMarker = this._ensureMarker(context, this._selStartMarker, this.modelState.selection.startLineNumber, this.modelState.selection.startColumn, true); - this._selEndMarker = this._ensureMarker(context, this._selEndMarker, this.modelState.selection.endLineNumber, this.modelState.selection.endColumn, false); - } - } - - private _ensureMarker(context: CursorContext, markerId: string, lineNumber: number, column: number, stickToPreviousCharacter: boolean): string { - if (!markerId) { - return context.model._addMarker(0, lineNumber, column, stickToPreviousCharacter); - } else { - context.model._changeMarker(markerId, lineNumber, column); - context.model._changeMarkerStickiness(markerId, stickToPreviousCharacter); - return markerId; - } + this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } } diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 493af0fb037..e932ce350c3 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -527,6 +527,7 @@ export class TextModel implements editorCommon.ITextModel { } public setEOL(eol: editorCommon.EndOfLineSequence): void { + // TODO@interval!!! this._assertNotDisposed(); const newEOL = (eol === editorCommon.EndOfLineSequence.CRLF ? '\r\n' : '\n'); if (this._EOL === newEOL) { diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index d912eb39530..5e651d60c5e 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -12,15 +12,13 @@ import { Range, IRange } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { MarkersTracker, LineMarker } from 'vs/editor/common/model/modelLine'; import { Position } from 'vs/editor/common/core/position'; -import { INewMarker, TextModelWithMarkers } from 'vs/editor/common/model/textModelWithMarkers'; +import { TextModelWithMarkers } from 'vs/editor/common/model/textModelWithMarkers'; import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; -export const USE_NEW_DECORATIONS = true; - export const ClassName = { EditorInfoDecoration: 'infosquiggly', EditorWarningDecoration: 'warningsquiggly', @@ -188,25 +186,8 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._treeDecorations = Object.create(null); } - private static _shouldStartMarkerSticksToPreviousCharacter(stickiness: editorCommon.TrackedRangeStickiness): boolean { - if (stickiness === editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges || stickiness === editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore) { - return true; - } - return false; - } - - private static _shouldEndMarkerSticksToPreviousCharacter(stickiness: editorCommon.TrackedRangeStickiness): boolean { - if (stickiness === editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges || stickiness === editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore) { - return true; - } - return false; - } - _getTrackedRangesCount(): number { - if (USE_NEW_DECORATIONS) { - return this._tree.count(); - } - return Object.keys(this._decorations).length; + return this._tree.count(); } // --- END TrackedRanges @@ -227,43 +208,25 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _changeDecorations(decorationsTracker: DecorationsTracker, ownerId: number, callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T): T { let changeAccessor: editorCommon.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: editorCommon.IModelDecorationOptions): string => { - if (USE_NEW_DECORATIONS) { - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - return this._deltaDecorationsImpl2(ownerId, [], [{ range: range, options: options }])[0]; - } - return this._addDecorationImpl(decorationsTracker, ownerId, this.validateRange(range), _normalizeOptions(options)); + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + return this._deltaDecorationsImpl2(ownerId, [], [{ range: range, options: options }])[0]; }, changeDecoration: (id: string, newRange: IRange): void => { - if (USE_NEW_DECORATIONS) { - this._changeDecorationImpl2(decorationsTracker, id, newRange); - return; - } - this._changeDecorationImpl(decorationsTracker, id, this.validateRange(newRange)); + this._changeDecorationImpl2(decorationsTracker, id, newRange); }, changeDecorationOptions: (id: string, options: editorCommon.IModelDecorationOptions) => { - if (USE_NEW_DECORATIONS) { - this._changeDecorationOptionsImpl2(decorationsTracker, id, _normalizeOptions(options)); - return; - } - this._changeDecorationOptionsImpl(decorationsTracker, id, _normalizeOptions(options)); + this._changeDecorationOptionsImpl2(decorationsTracker, id, _normalizeOptions(options)); }, removeDecoration: (id: string): void => { - if (USE_NEW_DECORATIONS) { - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - this._deltaDecorationsImpl2(ownerId, [id], []); - return; - } - this._removeDecorationImpl(decorationsTracker, id); + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + this._deltaDecorationsImpl2(ownerId, [id], []); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { - if (USE_NEW_DECORATIONS) { - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - return this._deltaDecorationsImpl2(ownerId, oldDecorations, newDecorations); - } - return this._deltaDecorationsImpl(decorationsTracker, ownerId, oldDecorations, this._normalizeDeltaDecorations(newDecorations)); + decorationsTracker.markDidAddDecorations(); + decorationsTracker.markDidRemoveDecorations(); + return this._deltaDecorationsImpl2(ownerId, oldDecorations, newDecorations); } }; let result: T = null; @@ -326,44 +289,21 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } public removeAllDecorationsWithOwnerId(ownerId: number): void { - if (USE_NEW_DECORATIONS) { - const nodes = this._tree.collectNodesFromOwner(ownerId); - for (let i = 0, len = nodes.length; i < len; i++) { - const node = nodes[i]; + const nodes = this._tree.collectNodesFromOwner(ownerId); + for (let i = 0, len = nodes.length; i < len; i++) { + const node = nodes[i]; - this._tree.delete(node); - delete this._treeDecorations[node.id]; - } - return; + this._tree.delete(node); + delete this._treeDecorations[node.id]; } - let toRemove: string[] = []; - - for (let decorationId in this._decorations) { - // No `hasOwnProperty` call due to using Object.create(null) - - let decoration = this._decorations[decorationId]; - - if (decoration.ownerId === ownerId) { - toRemove.push(decoration.id); - } - } - - this._removeDecorationsImpl(null, toRemove); } public getDecorationOptions(decorationId: string): editorCommon.IModelDecorationOptions { - if (USE_NEW_DECORATIONS) { - const node = this._treeDecorations[decorationId]; - if (!node) { - return null; - } - return node.options; - } - let decoration = this._decorations[decorationId]; - if (!decoration) { + const node = this._treeDecorations[decorationId]; + if (!node) { return null; } - return decoration.options; + return node.options; } private _getRangeAt(start: number, end: number): Range { @@ -379,26 +319,19 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } public getDecorationRange(decorationId: string): Range { - if (USE_NEW_DECORATIONS) { - const node = this._treeDecorations[decorationId]; - if (!node) { - return null; - } - const versionId = this.getVersionId(); - if (node.cachedVersionId !== versionId) { - this._tree.resolveNode(node, versionId); - } - if (node.range === null) { - this._ensureLineStarts(); - node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); - } - return node.range; - } - let decoration = this._decorations[decorationId]; - if (!decoration) { + const node = this._treeDecorations[decorationId]; + if (!node) { return null; } - return decoration.range; + const versionId = this.getVersionId(); + if (node.cachedVersionId !== versionId) { + this._tree.resolveNode(node, versionId); + } + if (node.range === null) { + this._ensureLineStarts(); + node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); + } + return node.range; } public getLineDecorations(lineNumber: number, ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { @@ -409,50 +342,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return this.getLinesDecorations(lineNumber, lineNumber, ownerId, filterOutValidation); } - /** - * Fetch only multi-line decorations that intersect with the given line number range - */ - private _getMultiLineDecorations(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): InternalDecoration[] { - const filterStartLineNumber = filterRange.startLineNumber; - const filterStartColumn = filterRange.startColumn; - const filterEndLineNumber = filterRange.endLineNumber; - const filterEndColumn = filterRange.endColumn; - - let result: InternalDecoration[] = [], resultLen = 0; - - for (let decorationId in this._multiLineDecorationsMap) { - // No `hasOwnProperty` call due to using Object.create(null) - let decoration = this._multiLineDecorationsMap[decorationId]; - - if (filterOwnerId && decoration.ownerId && decoration.ownerId !== filterOwnerId) { - continue; - } - - if (filterOutValidation && decoration.isForValidation) { - continue; - } - - let range = decoration.range; - - if (range.startLineNumber > filterEndLineNumber) { - continue; - } - if (range.startLineNumber === filterEndLineNumber && range.startColumn > filterEndColumn) { - continue; - } - if (range.endLineNumber < filterStartLineNumber) { - continue; - } - if (range.endLineNumber === filterStartLineNumber && range.endColumn < filterStartColumn) { - continue; - } - - result[resultLen++] = decoration; - } - - return result; - } - private _ensureNodesHaveRanges(nodes: IntervalNode[]): IntervalNode[] { this._ensureLineStarts(); @@ -465,82 +354,16 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed return nodes; } - private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): IntervalNode[] | InternalDecoration[] { - if (USE_NEW_DECORATIONS) { - this._ensureLineStarts(); + private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): IntervalNode[] { + this._ensureLineStarts(); - const startOffset = this._lineStarts.getAccumulatedValue(filterRange.startLineNumber - 2) + filterRange.startColumn - 1; - const endOffset = this._lineStarts.getAccumulatedValue(filterRange.endLineNumber - 2) + filterRange.endColumn - 1; + const startOffset = this._lineStarts.getAccumulatedValue(filterRange.startLineNumber - 2) + filterRange.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(filterRange.endLineNumber - 2) + filterRange.endColumn - 1; - const versionId = this.getVersionId(); - const result = this._tree.intervalSearch(startOffset, endOffset, filterOwnerId, filterOutValidation, versionId); + const versionId = this.getVersionId(); + const result = this._tree.intervalSearch(startOffset, endOffset, filterOwnerId, filterOutValidation, versionId); - return this._ensureNodesHaveRanges(result); - } - - const filterStartLineNumber = filterRange.startLineNumber; - const filterStartColumn = filterRange.startColumn; - const filterEndLineNumber = filterRange.endLineNumber; - const filterEndColumn = filterRange.endColumn; - - let result = this._getMultiLineDecorations(filterRange, filterOwnerId, filterOutValidation); - let resultLen = result.length; - let resultMap: { [decorationId: string]: boolean; } = {}; - - for (let i = 0, len = resultLen; i < len; i++) { - resultMap[result[i].id] = true; - } - - for (let lineNumber = filterStartLineNumber; lineNumber <= filterEndLineNumber; lineNumber++) { - let lineMarkers = this._lines[lineNumber - 1].getMarkers(); - if (lineMarkers === null) { - continue; - } - for (let i = 0, len = lineMarkers.length; i < len; i++) { - let lineMarker = lineMarkers[i]; - let internalDecorationId = lineMarker.internalDecorationId; - - if (internalDecorationId === 0) { - // marker does not belong to any decoration - continue; - } - - let decoration = this._internalDecorations[internalDecorationId]; - - if (resultMap.hasOwnProperty(decoration.id)) { - // decoration already in result - continue; - } - - if (filterOwnerId && decoration.ownerId && decoration.ownerId !== filterOwnerId) { - continue; - } - - if (filterOutValidation && decoration.isForValidation) { - continue; - } - - let range = decoration.range; - - if (range.startLineNumber > filterEndLineNumber) { - continue; - } - if (range.startLineNumber === filterEndLineNumber && range.startColumn > filterEndColumn) { - continue; - } - if (range.endLineNumber < filterStartLineNumber) { - continue; - } - if (range.endLineNumber === filterStartLineNumber && range.endColumn < filterStartColumn) { - continue; - } - - result[resultLen++] = decoration; - resultMap[decoration.id] = true; - } - } - - return result; + return this._ensureNodesHaveRanges(result); } public getLinesDecorations(_startLineNumber: number, _endLineNumber: number, ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { @@ -557,59 +380,15 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } public getOverviewRulerDecorations(ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { - if (USE_NEW_DECORATIONS) { - const versionId = this.getVersionId(); - const result = this._tree.search(ownerId, filterOutValidation, true, versionId); - return this._ensureNodesHaveRanges(result); - } - let result: InternalDecoration[] = [], resultLen = 0; - - for (let decorationId in this._decorations) { - // No `hasOwnProperty` call due to using Object.create(null) - let decoration = this._decorations[decorationId]; - - if (ownerId && decoration.ownerId && decoration.ownerId !== ownerId) { - continue; - } - - if (filterOutValidation && decoration.isForValidation) { - continue; - } - - if (!decoration.options.overviewRuler.color) { - continue; - } - - result[resultLen++] = decoration; - } - - return result; + const versionId = this.getVersionId(); + const result = this._tree.search(ownerId, filterOutValidation, true, versionId); + return this._ensureNodesHaveRanges(result); } public getAllDecorations(ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { - if (USE_NEW_DECORATIONS) { - const versionId = this.getVersionId(); - const result = this._tree.search(ownerId, filterOutValidation, false, versionId); - return this._ensureNodesHaveRanges(result); - } - let result: InternalDecoration[] = [], resultLen = 0; - - for (let decorationId in this._decorations) { - // No `hasOwnProperty` call due to using Object.create(null) - let decoration = this._decorations[decorationId]; - - if (ownerId && decoration.ownerId && decoration.ownerId !== ownerId) { - continue; - } - - if (filterOutValidation && decoration.isForValidation) { - continue; - } - - result[resultLen++] = decoration; - } - - return result; + const versionId = this.getVersionId(); + const result = this._tree.search(ownerId, filterOutValidation, false, versionId); + return this._ensureNodesHaveRanges(result); } protected _acquireMarkersTracker(): MarkersTracker { @@ -711,129 +490,10 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed } } - private _normalizeDeltaDecorations(deltaDecorations: editorCommon.IModelDeltaDecoration[]): ModelDeltaDecoration[] { - let result: ModelDeltaDecoration[] = []; - for (let i = 0, len = deltaDecorations.length; i < len; i++) { - let deltaDecoration = deltaDecorations[i]; - result.push(new ModelDeltaDecoration(i, this.validateRange(deltaDecoration.range), _normalizeOptions(deltaDecoration.options))); - } - return result; - } - private _externalDecorationId(internalId: number): string { return `${this._instanceId};${internalId}`; } - private _addDecorationImpl(decorationsTracker: DecorationsTracker, ownerId: number, _range: Range, options: ModelDecorationOptions): string { - let range = this.validateRange(_range); - - let internalDecorationId = (++this._lastDecorationId); - let decorationId = this._externalDecorationId(internalDecorationId); - - let markers = this._addMarkers([ - { - internalDecorationId: internalDecorationId, - position: new Position(range.startLineNumber, range.startColumn), - stickToPreviousCharacter: TextModelWithDecorations._shouldStartMarkerSticksToPreviousCharacter(options.stickiness) - }, - { - internalDecorationId: internalDecorationId, - position: new Position(range.endLineNumber, range.endColumn), - stickToPreviousCharacter: TextModelWithDecorations._shouldEndMarkerSticksToPreviousCharacter(options.stickiness) - } - ]); - - let decoration = new InternalDecoration(decorationId, internalDecorationId, ownerId, range, markers[0], markers[1], options); - this._decorations[decorationId] = decoration; - this._internalDecorations[internalDecorationId] = decoration; - if (range.startLineNumber !== range.endLineNumber) { - this._multiLineDecorationsMap[decorationId] = decoration; - } - - decorationsTracker.markDidAddDecorations(); - - return decorationId; - } - - private _addDecorationsImpl(decorationsTracker: DecorationsTracker, ownerId: number, newDecorations: ModelDeltaDecoration[]): string[] { - let internalDecorationIds: number[] = []; - let decorationIds: string[] = []; - let newMarkers: INewMarker[] = []; - - for (let i = 0, len = newDecorations.length; i < len; i++) { - let newDecoration = newDecorations[i]; - let range = newDecoration.range; - let stickiness = newDecoration.options.stickiness; - - let internalDecorationId = (++this._lastDecorationId); - let decorationId = this._externalDecorationId(internalDecorationId); - - internalDecorationIds[i] = internalDecorationId; - decorationIds[i] = decorationId; - - newMarkers[2 * i] = { - internalDecorationId: internalDecorationId, - position: new Position(range.startLineNumber, range.startColumn), - stickToPreviousCharacter: TextModelWithDecorations._shouldStartMarkerSticksToPreviousCharacter(stickiness) - }; - - newMarkers[2 * i + 1] = { - internalDecorationId: internalDecorationId, - position: new Position(range.endLineNumber, range.endColumn), - stickToPreviousCharacter: TextModelWithDecorations._shouldEndMarkerSticksToPreviousCharacter(stickiness) - }; - } - - let markerIds = this._addMarkers(newMarkers); - - for (let i = 0, len = newDecorations.length; i < len; i++) { - let newDecoration = newDecorations[i]; - let range = newDecoration.range; - let internalDecorationId = internalDecorationIds[i]; - let decorationId = decorationIds[i]; - let startMarker = markerIds[2 * i]; - let endMarker = markerIds[2 * i + 1]; - - let decoration = new InternalDecoration(decorationId, internalDecorationId, ownerId, range, startMarker, endMarker, newDecoration.options); - this._decorations[decorationId] = decoration; - this._internalDecorations[internalDecorationId] = decoration; - if (range.startLineNumber !== range.endLineNumber) { - this._multiLineDecorationsMap[decorationId] = decoration; - } - - decorationsTracker.markDidAddDecorations(); - } - - return decorationIds; - } - - private _changeDecorationImpl(decorationsTracker: DecorationsTracker, decorationId: string, newRange: Range): void { - let decoration = this._decorations[decorationId]; - if (!decoration) { - return; - } - - let startMarker = decoration.startMarker; - if (newRange.startLineNumber !== startMarker.position.lineNumber) { - // move marker between lines - this._lines[startMarker.position.lineNumber - 1].removeMarker(startMarker); - this._lines[newRange.startLineNumber - 1].addMarker(startMarker); - } - startMarker.setPosition(new Position(newRange.startLineNumber, newRange.startColumn)); - - let endMarker = decoration.endMarker; - if (newRange.endLineNumber !== endMarker.position.lineNumber) { - // move marker between lines - this._lines[endMarker.position.lineNumber - 1].removeMarker(endMarker); - this._lines[newRange.endLineNumber - 1].addMarker(endMarker); - } - endMarker.setPosition(new Position(newRange.endLineNumber, newRange.endColumn)); - - decoration.setRange(this._multiLineDecorationsMap, newRange); - - decorationsTracker.markDidChangeDecorations(); - } - private _changeDecorationImpl2(decorationsTracker: DecorationsTracker, decorationId: string, _range: IRange): void { const node = this._treeDecorations[decorationId]; if (!node) { @@ -851,22 +511,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed decorationsTracker.markDidChangeDecorations(); } - private _changeDecorationOptionsImpl(decorationsTracker: DecorationsTracker, decorationId: string, options: ModelDecorationOptions): void { - let decoration = this._decorations[decorationId]; - if (!decoration) { - return; - } - - if (decoration.options.stickiness !== options.stickiness) { - decoration.startMarker.stickToPreviousCharacter = TextModelWithDecorations._shouldStartMarkerSticksToPreviousCharacter(options.stickiness); - decoration.endMarker.stickToPreviousCharacter = TextModelWithDecorations._shouldEndMarkerSticksToPreviousCharacter(options.stickiness); - } - - decoration.setOptions(options); - - decorationsTracker.markDidChangeDecorations(); - } - private _changeDecorationOptionsImpl2(decorationsTracker: DecorationsTracker, decorationId: string, options: ModelDecorationOptions): void { const node = this._treeDecorations[decorationId]; if (!node) { @@ -878,151 +522,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed decorationsTracker.markDidChangeDecorations(); } - private _removeDecorationImpl(decorationsTracker: DecorationsTracker, decorationId: string): void { - let decoration = this._decorations[decorationId]; - if (!decoration) { - return; - } - - this._removeMarkers([decoration.startMarker, decoration.endMarker]); - - delete this._multiLineDecorationsMap[decorationId]; - delete this._decorations[decorationId]; - delete this._internalDecorations[decoration.internalId]; - - if (decorationsTracker) { - decorationsTracker.markDidRemoveDecorations(); - } - } - - private _removeDecorationsImpl(decorationsTracker: DecorationsTracker, decorationIds: string[]): void { - let removeMarkers: LineMarker[] = [], removeMarkersLen = 0; - - for (let i = 0, len = decorationIds.length; i < len; i++) { - let decorationId = decorationIds[i]; - let decoration = this._decorations[decorationId]; - if (!decoration) { - continue; - } - - if (decorationsTracker) { - decorationsTracker.markDidRemoveDecorations(); - } - - removeMarkers[removeMarkersLen++] = decoration.startMarker; - removeMarkers[removeMarkersLen++] = decoration.endMarker; - delete this._multiLineDecorationsMap[decorationId]; - delete this._decorations[decorationId]; - delete this._internalDecorations[decoration.internalId]; - } - - if (removeMarkers.length > 0) { - this._removeMarkers(removeMarkers); - } - } - - private _resolveOldDecorations(oldDecorations: string[]): InternalDecoration[] { - let result: InternalDecoration[] = []; - for (let i = 0, len = oldDecorations.length; i < len; i++) { - let id = oldDecorations[i]; - let decoration = this._decorations[id]; - if (!decoration) { - continue; - } - - result.push(decoration); - } - return result; - } - - private _deltaDecorationsImpl(decorationsTracker: DecorationsTracker, ownerId: number, oldDecorationsIds: string[], newDecorations: ModelDeltaDecoration[]): string[] { - - if (oldDecorationsIds.length === 0) { - // Nothing to remove - return this._addDecorationsImpl(decorationsTracker, ownerId, newDecorations); - } - - if (newDecorations.length === 0) { - // Nothing to add - this._removeDecorationsImpl(decorationsTracker, oldDecorationsIds); - return []; - } - - let oldDecorations = this._resolveOldDecorations(oldDecorationsIds); - - oldDecorations.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range)); - newDecorations.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range)); - - let result: string[] = [], - oldDecorationsIndex = 0, - oldDecorationsLength = oldDecorations.length, - newDecorationsIndex = 0, - newDecorationsLength = newDecorations.length, - decorationsToAdd: ModelDeltaDecoration[] = [], - decorationsToRemove: string[] = []; - - while (oldDecorationsIndex < oldDecorationsLength && newDecorationsIndex < newDecorationsLength) { - let oldDecoration = oldDecorations[oldDecorationsIndex]; - let newDecoration = newDecorations[newDecorationsIndex]; - let comparison = Range.compareRangesUsingStarts(oldDecoration.range, newDecoration.range); - - if (comparison < 0) { - // `oldDecoration` is before `newDecoration` => remove `oldDecoration` - decorationsToRemove.push(oldDecoration.id); - oldDecorationsIndex++; - continue; - } - - if (comparison > 0) { - // `newDecoration` is before `oldDecoration` => add `newDecoration` - decorationsToAdd.push(newDecoration); - newDecorationsIndex++; - continue; - } - - // The ranges of `oldDecoration` and `newDecoration` are equal - - if (!oldDecoration.options.equals(newDecoration.options)) { - // The options do not match => remove `oldDecoration` - decorationsToRemove.push(oldDecoration.id); - oldDecorationsIndex++; - continue; - } - - // Bingo! We can reuse `oldDecoration` for `newDecoration` - result[newDecoration.index] = oldDecoration.id; - oldDecorationsIndex++; - newDecorationsIndex++; - } - - while (oldDecorationsIndex < oldDecorationsLength) { - // No more new decorations => remove decoration at `oldDecorationsIndex` - decorationsToRemove.push(oldDecorations[oldDecorationsIndex].id); - oldDecorationsIndex++; - } - - while (newDecorationsIndex < newDecorationsLength) { - // No more old decorations => add decoration at `newDecorationsIndex` - decorationsToAdd.push(newDecorations[newDecorationsIndex]); - newDecorationsIndex++; - } - - // Remove `decorationsToRemove` - if (decorationsToRemove.length > 0) { - this._removeDecorationsImpl(decorationsTracker, decorationsToRemove); - } - - // Add `decorationsToAdd` - if (decorationsToAdd.length > 0) { - let newIds = this._addDecorationsImpl(decorationsTracker, ownerId, decorationsToAdd); - for (let i = 0, len = decorationsToAdd.length; i < len; i++) { - result[decorationsToAdd[i].index] = newIds[i]; - } - } - - return result; - } - private _deltaDecorationsImpl2(ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { this._ensureLineStarts(); const versionId = this.getVersionId(); diff --git a/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts b/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts index d29f6908dc9..05d96ea0b30 100644 --- a/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts +++ b/src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts @@ -12,7 +12,6 @@ import { SnippetSession } from 'vs/editor/contrib/snippet/browser/snippetSession import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { mockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { Model } from 'vs/editor/common/model/model'; -import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; suite('SnippetSession', function () { @@ -235,17 +234,9 @@ suite('SnippetSession', function () { assertSelections(editor, new Selection(1, 10, 1, 10), new Selection(2, 14, 2, 14)); session.prev(); - if (USE_NEW_DECORATIONS) { - assertSelections(editor, new Selection(1, 7, 1, 10), new Selection(2, 11, 2, 14)); - } else { - assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11)); - } + assertSelections(editor, new Selection(1, 7, 1, 10), new Selection(2, 11, 2, 14)); session.prev(); - if (USE_NEW_DECORATIONS) { - assertSelections(editor, new Selection(1, 4, 1, 7), new Selection(2, 8, 2, 11)); - } else { - assertSelections(editor, new Selection(1, 4, 1, 4), new Selection(2, 8, 2, 8)); - } + assertSelections(editor, new Selection(1, 4, 1, 7), new Selection(2, 8, 2, 11)); session.prev(); assertSelections(editor, new Selection(1, 1, 1, 4), new Selection(2, 5, 2, 8)); }); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 8e808191925..54fd5d17424 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -10,7 +10,6 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; import { Model } from 'vs/editor/common/model/model'; -import { USE_NEW_DECORATIONS } from 'vs/editor/common/model/textModelWithDecorations'; // --------- utils @@ -1095,11 +1094,7 @@ suite('deltaDecorations', () => { assert.equal(initialIds.length, decorations.length, 'returns expected cnt of ids'); assert.equal(initialIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(initialIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); - if (!USE_NEW_DECORATIONS) { - assert.equal(2 * initialIds.length, model._getMarkersCount(), 'does not leak markers'); - } else { - assert.equal(0, model._getMarkersCount(), 'does not leak markers'); - } + assert.equal(0, model._getMarkersCount(), 'does not leak markers'); actualDecorations.sort((a, b) => strcmp(a.id, b.id)); decorations.sort((a, b) => strcmp(a.id, b.id)); assert.deepEqual(actualDecorations, decorations); @@ -1110,11 +1105,7 @@ suite('deltaDecorations', () => { assert.equal(newIds.length, newDecorations.length, 'returns expected cnt of ids'); assert.equal(newIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(newIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); - if (!USE_NEW_DECORATIONS) { - assert.equal(2 * newIds.length, model._getMarkersCount(), 'does not leak markers'); - } else { - assert.equal(0, model._getMarkersCount(), 'does not leak markers'); - } + assert.equal(0, model._getMarkersCount(), 'does not leak markers'); actualNewDecorations.sort((a, b) => strcmp(a.id, b.id)); newDecorations.sort((a, b) => strcmp(a.id, b.id)); assert.deepEqual(actualDecorations, decorations); From a0a5f18f7271c239b83523498ccf60680a00757a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 12:40:45 +0200 Subject: [PATCH 166/394] Remove TextModelWithMarkers --- src/vs/editor/common/editorCommon.ts | 30 +- .../editor/common/model/editableTextModel.ts | 25 -- src/vs/editor/common/model/model.ts | 2 +- .../common/model/textModelWithDecorations.ts | 113 +------- .../common/model/textModelWithMarkers.ts | 174 ------------ .../common/model/editableTextModel.test.ts | 257 +----------------- .../model/editableTextModelTestUtils.ts | 1 - .../common/model/modelDecorations.test.ts | 2 - src/vs/monaco.d.ts | 10 +- 9 files changed, 9 insertions(+), 605 deletions(-) delete mode 100644 src/vs/editor/common/model/textModelWithMarkers.ts diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 6fb2a079656..6b46304bbeb 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -915,32 +915,6 @@ export interface ITokenizedModel extends ITextModel { getLineIndentGuide(lineNumber: number): number; } -/** - * A model that can track markers. - */ -export interface ITextModelWithMarkers extends ITextModel { - /** - * @internal - */ - _addMarker(internalDecorationId: number, lineNumber: number, column: number, stickToPreviousCharacter: boolean): string; - /** - * @internal - */ - _changeMarker(id: string, newLineNumber: number, newColumn: number): void; - /** - * @internal - */ - _changeMarkerStickiness(id: string, newStickToPreviousCharacter: boolean): void; - /** - * @internal - */ - _getMarker(id: string): Position; - /** - * @internal - */ - _removeMarker(id: string): void; -} - /** * Describes the behavior of decorations when typing/editing near their edges. * Note: Please do not edit the values, as they very carefully match `DecorationRangeBehavior` @@ -1056,7 +1030,7 @@ export interface ITextModelWithDecorations { /** * An editable text model. */ -export interface IEditableTextModel extends ITextModelWithMarkers { +export interface IEditableTextModel extends ITextModel { /** * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs). @@ -1139,7 +1113,7 @@ export interface IEditableTextModel extends ITextModelWithMarkers { /** * A model. */ -export interface IModel extends IReadOnlyModel, IEditableTextModel, ITextModelWithMarkers, ITokenizedModel, ITextModelWithDecorations { +export interface IModel extends IReadOnlyModel, IEditableTextModel, ITokenizedModel, ITextModelWithDecorations { /** * @deprecated Please use `onDidChangeContent` instead. * An event emitted when the contents of the model have changed. diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index e8c617fc2c2..0880fc0824b 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -730,31 +730,6 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._resetIndentRanges(); } - public _assertLineNumbersOK(): void { - let foundMarkersCnt = 0; - for (let i = 0, len = this._lines.length; i < len; i++) { - let line = this._lines[i]; - let lineNumber = i + 1; - - let markers = line.getMarkers(); - if (markers !== null) { - for (let j = 0, lenJ = markers.length; j < lenJ; j++) { - foundMarkersCnt++; - let markerId = markers[j].id; - let marker = this._markerIdToMarker[markerId]; - if (marker.position.lineNumber !== lineNumber) { - throw new Error('Misplaced marker with id ' + markerId); - } - } - } - } - - let totalMarkersCnt = Object.keys(this._markerIdToMarker).length; - if (totalMarkersCnt !== foundMarkersCnt) { - throw new Error('There are misplaced markers!'); - } - } - private _undo(): Selection[] { this._isUndoing = true; let r = this._commandManager.undo(); diff --git a/src/vs/editor/common/model/model.ts b/src/vs/editor/common/model/model.ts index 1228592fe0f..2e1410fc830 100644 --- a/src/vs/editor/common/model/model.ts +++ b/src/vs/editor/common/model/model.ts @@ -16,7 +16,7 @@ import { IRawTextSource, RawTextSource } from 'vs/editor/common/model/textSource import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; // The hierarchy is: -// Model -> EditableTextModel -> TextModelWithDecorations -> TextModelWithTrackedRanges -> TextModelWithMarkers -> TextModelWithTokens -> TextModel +// Model -> EditableTextModel -> TextModelWithDecorations -> TextModelWithTokens -> TextModel var MODEL_ID = 0; diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 5e651d60c5e..de20a2b6aec 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -10,9 +10,8 @@ import * as strings from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; import { Range, IRange } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { MarkersTracker, LineMarker } from 'vs/editor/common/model/modelLine'; -import { Position } from 'vs/editor/common/core/position'; -import { TextModelWithMarkers } from 'vs/editor/common/model/textModelWithMarkers'; +import { MarkersTracker } from 'vs/editor/common/model/modelLine'; +import { TextModelWithTokens } from 'vs/editor/common/model/textModelWithTokens'; import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; @@ -52,57 +51,6 @@ class DecorationsTracker { } } -export class InternalDecoration implements editorCommon.IModelDecoration { - _internalDecorationBrand: void; - - public readonly id: string; - public readonly internalId: number; - public readonly ownerId: number; - public readonly startMarker: LineMarker; - public readonly endMarker: LineMarker; - public options: ModelDecorationOptions; - public isForValidation: boolean; - public range: Range; - - constructor(id: string, internalId: number, ownerId: number, range: Range, startMarker: LineMarker, endMarker: LineMarker, options: ModelDecorationOptions) { - this.id = id; - this.internalId = internalId; - this.ownerId = ownerId; - this.range = range; - this.startMarker = startMarker; - this.endMarker = endMarker; - this.setOptions(options); - } - - public setOptions(options: ModelDecorationOptions) { - this.options = options; - this.isForValidation = ( - this.options.className === ClassName.EditorErrorDecoration - || this.options.className === ClassName.EditorWarningDecoration - ); - } - - public setRange(multiLineDecorationsMap: { [key: string]: InternalDecoration; }, range: Range): void { - if (this.range.equalsRange(range)) { - return; - } - - let rangeWasMultiLine = (this.range.startLineNumber !== this.range.endLineNumber); - this.range = range; - let rangeIsMultiline = (this.range.startLineNumber !== this.range.endLineNumber); - - if (rangeWasMultiLine === rangeIsMultiline) { - return; - } - - if (rangeIsMultiline) { - multiLineDecorationsMap[this.id] = this; - } else { - delete multiLineDecorationsMap[this.id]; - } - } -} - let _INSTANCE_COUNT = 0; /** * Produces 'a'-'z', followed by 'A'-'Z'... followed by 'a'-'z', etc. @@ -120,7 +68,7 @@ function nextInstanceId(): string { return String.fromCharCode(CharCode.A + result - LETTERS_CNT); } -export class TextModelWithDecorations extends TextModelWithMarkers implements editorCommon.ITextModelWithDecorations { +export class TextModelWithDecorations extends TextModelWithTokens implements editorCommon.ITextModelWithDecorations { /** * Used to workaround broken clients that might attempt using a decoration id generated by a different model. @@ -138,10 +86,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed protected _tree: IntervalTree; private _treeDecorations: { [decorationId: string]: IntervalNode; }; - private _decorations: { [decorationId: string]: InternalDecoration; }; - private _internalDecorations: { [internalDecorationId: number]: InternalDecoration; }; - private _multiLineDecorationsMap: { [key: string]: InternalDecoration; }; - constructor(rawTextSource: IRawTextSource, creationOptions: editorCommon.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier) { super(rawTextSource, creationOptions, languageIdentifier); @@ -157,17 +101,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed this._tree = new IntervalTree(); this._treeDecorations = Object.create(null); - - this._decorations = Object.create(null); - this._internalDecorations = Object.create(null); - this._multiLineDecorationsMap = Object.create(null); } public dispose(): void { - this._decorations = null; - this._internalDecorations = null; - this._multiLineDecorationsMap = null; - this._tree = null; this._treeDecorations = null; @@ -178,10 +114,6 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed super._resetValue(newValue); // Destroy all my decorations - this._decorations = Object.create(null); - this._internalDecorations = Object.create(null); - this._multiLineDecorationsMap = Object.create(null); - this._tree = new IntervalTree(); this._treeDecorations = Object.create(null); } @@ -412,48 +344,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed * Handle changed markers (i.e. update decorations ranges) */ private _handleTrackedMarkers(markersTracker: MarkersTracker): void { - let changedInternalDecorationIds = markersTracker.getDecorationIds(); - if (changedInternalDecorationIds.length === 0) { - this.emitModelDecorationsChangedEvent(); - return; - } - - changedInternalDecorationIds.sort(); - - let previousInternalDecorationId: number = 0; - for (let i = 0, len = changedInternalDecorationIds.length; i < len; i++) { - let internalDecorationId = changedInternalDecorationIds[i]; - if (internalDecorationId === previousInternalDecorationId) { - continue; - } - previousInternalDecorationId = internalDecorationId; - - let decoration = this._internalDecorations[internalDecorationId]; - if (!decoration) { - // perhaps the decoration was removed in the meantime - continue; - } - - let startMarker = decoration.startMarker.position; - let endMarker = decoration.endMarker.position; - let range = TextModelWithDecorations._createRangeFromMarkers(startMarker, endMarker); - decoration.setRange(this._multiLineDecorationsMap, range); - } - this.emitModelDecorationsChangedEvent(); } - private static _createRangeFromMarkers(startPosition: Position, endPosition: Position): Range { - if (endPosition.isBefore(startPosition)) { - // This tracked range has turned in on itself (end marker before start marker) - // This can happen in extreme editing conditions where lots of text is removed and lots is added - - // Treat it as a collapsed range - return new Range(startPosition.lineNumber, startPosition.column, startPosition.lineNumber, startPosition.column); - } - return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column); - } - private _acquireDecorationsTracker(): DecorationsTracker { if (this._currentDecorationsTrackerCnt === 0) { this._currentDecorationsTracker = new DecorationsTracker(); diff --git a/src/vs/editor/common/model/textModelWithMarkers.ts b/src/vs/editor/common/model/textModelWithMarkers.ts deleted file mode 100644 index 6100bfc3999..00000000000 --- a/src/vs/editor/common/model/textModelWithMarkers.ts +++ /dev/null @@ -1,174 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { IdGenerator } from 'vs/base/common/idGenerator'; -import { Position } from 'vs/editor/common/core/position'; -import { ITextModelWithMarkers, ITextModelCreationOptions } from 'vs/editor/common/editorCommon'; -import { LineMarker } from 'vs/editor/common/model/modelLine'; -import { TextModelWithTokens } from 'vs/editor/common/model/textModelWithTokens'; -import { LanguageIdentifier } from 'vs/editor/common/modes'; -import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; - -export interface IMarkerIdToMarkerMap { - [key: string]: LineMarker; -} - -export interface INewMarker { - internalDecorationId: number; - position: Position; - stickToPreviousCharacter: boolean; -} - -var _INSTANCE_COUNT = 0; - -export class TextModelWithMarkers extends TextModelWithTokens implements ITextModelWithMarkers { - - private _markerIdGenerator: IdGenerator; - protected _markerIdToMarker: IMarkerIdToMarkerMap; - - constructor(rawTextSource: IRawTextSource, creationOptions: ITextModelCreationOptions, languageIdentifier: LanguageIdentifier) { - super(rawTextSource, creationOptions, languageIdentifier); - this._markerIdGenerator = new IdGenerator((++_INSTANCE_COUNT) + ';'); - this._markerIdToMarker = Object.create(null); - } - - public dispose(): void { - this._markerIdToMarker = null; - super.dispose(); - } - - protected _resetValue(newValue: ITextSource): void { - super._resetValue(newValue); - - // Destroy all my markers - this._markerIdToMarker = Object.create(null); - } - - _addMarker(internalDecorationId: number, lineNumber: number, column: number, stickToPreviousCharacter: boolean): string { - var pos = this.validatePosition(new Position(lineNumber, column)); - - var marker = new LineMarker(this._markerIdGenerator.nextId(), internalDecorationId, pos, stickToPreviousCharacter); - this._markerIdToMarker[marker.id] = marker; - - this._lines[pos.lineNumber - 1].addMarker(marker); - - return marker.id; - } - - protected _addMarkers(newMarkers: INewMarker[]): LineMarker[] { - if (newMarkers.length === 0) { - return []; - } - - let markers: LineMarker[] = []; - for (let i = 0, len = newMarkers.length; i < len; i++) { - let newMarker = newMarkers[i]; - - let marker = new LineMarker(this._markerIdGenerator.nextId(), newMarker.internalDecorationId, newMarker.position, newMarker.stickToPreviousCharacter); - this._markerIdToMarker[marker.id] = marker; - - markers[i] = marker; - } - - let sortedMarkers = markers.slice(0); - sortedMarkers.sort((a, b) => { - return a.position.lineNumber - b.position.lineNumber; - }); - - let currentLineNumber = 0; - let currentMarkers: LineMarker[] = [], currentMarkersLen = 0; - for (let i = 0, len = sortedMarkers.length; i < len; i++) { - let marker = sortedMarkers[i]; - - if (marker.position.lineNumber !== currentLineNumber) { - if (currentLineNumber !== 0) { - this._lines[currentLineNumber - 1].addMarkers(currentMarkers); - } - currentLineNumber = marker.position.lineNumber; - currentMarkers.length = 0; - currentMarkersLen = 0; - } - - currentMarkers[currentMarkersLen++] = marker; - } - this._lines[currentLineNumber - 1].addMarkers(currentMarkers); - - return markers; - } - - _changeMarker(id: string, lineNumber: number, column: number): void { - let marker = this._markerIdToMarker[id]; - if (!marker) { - return; - } - - let newPos = this.validatePosition(new Position(lineNumber, column)); - - if (newPos.lineNumber !== marker.position.lineNumber) { - // Move marker between lines - this._lines[marker.position.lineNumber - 1].removeMarker(marker); - this._lines[newPos.lineNumber - 1].addMarker(marker); - } - - marker.setPosition(newPos); - } - - _changeMarkerStickiness(id: string, newStickToPreviousCharacter: boolean): void { - let marker = this._markerIdToMarker[id]; - if (!marker) { - return; - } - - marker.stickToPreviousCharacter = newStickToPreviousCharacter; - } - - _getMarker(id: string): Position { - let marker = this._markerIdToMarker[id]; - if (!marker) { - return null; - } - - return marker.position; - } - - _getMarkersCount(): number { - return Object.keys(this._markerIdToMarker).length; - } - - _removeMarker(id: string): void { - let marker = this._markerIdToMarker[id]; - if (!marker) { - return; - } - - this._lines[marker.position.lineNumber - 1].removeMarker(marker); - delete this._markerIdToMarker[id]; - } - - protected _removeMarkers(markers: LineMarker[]): void { - markers.sort((a, b) => { - return a.position.lineNumber - b.position.lineNumber; - }); - - let currentLineNumber = 0; - let currentMarkers: { [markerId: string]: boolean; } = null; - for (let i = 0, len = markers.length; i < len; i++) { - let marker = markers[i]; - delete this._markerIdToMarker[marker.id]; - - if (marker.position.lineNumber !== currentLineNumber) { - if (currentLineNumber !== 0) { - this._lines[currentLineNumber - 1].removeMarkers(currentMarkers); - } - currentLineNumber = marker.position.lineNumber; - currentMarkers = Object.create(null); - } - - currentMarkers[marker.id] = true; - } - this._lines[currentLineNumber - 1].removeMarkers(currentMarkers); - } -} diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 266b6b67f05..d04e5269cad 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Range } from 'vs/editor/common/core/range'; -import { EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon'; +import { EndOfLineSequence, IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon'; import { EditableTextModel, IValidatedEditOperation } from 'vs/editor/common/model/editableTextModel'; import { MirrorModel } from 'vs/editor/common/model/mirrorModel'; import { assertSyncedModels, testApplyEditsWithSyncedModels } from 'vs/editor/test/common/model/editableTextModelTestUtils'; @@ -1569,7 +1569,6 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }); let assertMirrorModels = () => { - model._assertLineNumbersOK(); assert.equal(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK'); assert.equal(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK'); }; @@ -1581,257 +1580,3 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { mirrorModel2.dispose(); }); }); - -interface ILightWeightMarker { - id: string; - lineNumber: number; - column: number; - stickToPreviousCharacter: boolean; -} - -suite('EditorModel - EditableTextModel.applyEdits & markers', () => { - - function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, text: string[]): IIdentifiedSingleEditOperation { - return { - identifier: null, - range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), - text: text.join('\n'), - forceMoveMarkers: false - }; - } - - function marker(id: string, lineNumber: number, column: number, stickToPreviousCharacter: boolean): ILightWeightMarker { - return { - id: id, - lineNumber: lineNumber, - column: column, - stickToPreviousCharacter: stickToPreviousCharacter - }; - } - - function toMarkersMap(markers: ILightWeightMarker[]): { [markerId: string]: ILightWeightMarker } { - var result: { [markerId: string]: ILightWeightMarker } = {}; - markers.forEach(m => { - result[m.id] = m; - }); - return result; - } - - function testApplyEditsAndMarkers(text: string[], markers: ILightWeightMarker[], edits: IIdentifiedSingleEditOperation[], changedMarkers: string[], expectedText: string[], expectedMarkers: ILightWeightMarker[]): void { - var textStr = text.join('\n'); - var expectedTextStr = expectedText.join('\n'); - var markersMap = toMarkersMap(markers); - // var expectedMarkersMap = toMarkersMap(expectedMarkers); - var markerId2ModelMarkerId = Object.create(null); - - var model = EditableTextModel.createFromString(textStr); - model.setEOL(EndOfLineSequence.LF); - - // Add markers - markers.forEach((m) => { - let modelMarkerId = model._addMarker(0, m.lineNumber, m.column, m.stickToPreviousCharacter); - markerId2ModelMarkerId[m.id] = modelMarkerId; - }); - - // Apply edits & collect inverse edits - model.applyEdits(edits); - model._assertLineNumbersOK(); - - // Assert edits produced expected result - assert.deepEqual(model.getValue(EndOfLinePreference.LF), expectedTextStr); - - let actualChangedMarkers: string[] = []; - for (let i = 0, len = expectedMarkers.length; i < len; i++) { - let expectedMarker = expectedMarkers[i]; - let initialMarker = markersMap[expectedMarker.id]; - let expectedMarkerModelMarkerId = markerId2ModelMarkerId[expectedMarker.id]; - let actualMarker = model._getMarker(expectedMarkerModelMarkerId); - - if (actualMarker.lineNumber !== initialMarker.lineNumber || actualMarker.column !== initialMarker.column) { - actualChangedMarkers.push(initialMarker.id); - } - - assert.equal(actualMarker.lineNumber, expectedMarker.lineNumber, 'marker lineNumber of marker ' + expectedMarker.id); - assert.equal(actualMarker.column, expectedMarker.column, 'marker column of marker ' + expectedMarker.id); - } - - changedMarkers.sort(); - actualChangedMarkers.sort(); - assert.deepEqual(actualChangedMarkers, changedMarkers, 'changed markers'); - - model.dispose(); - } - - test('no markers changed', () => { - testApplyEditsAndMarkers( - [ - 'Hello world,', - 'this is a short text', - 'that is used in testing' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 2, 1, false), - marker('f', 2, 16, true), - marker('g', 2, 21, true), - marker('h', 3, 24, false) - ], - [ - editOp(1, 13, 1, 13, [' how are you?']) - ], - [], - [ - 'Hello world, how are you?', - 'this is a short text', - 'that is used in testing' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 2, 1, false), - marker('f', 2, 16, true), - marker('g', 2, 21, true), - marker('h', 3, 24, false) - ] - ); - }); - - test('first line changes', () => { - testApplyEditsAndMarkers( - [ - 'Hello world,', - 'this is a short text', - 'that is used in testing' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 2, 1, false), - marker('f', 2, 16, true), - marker('g', 2, 21, true), - marker('h', 3, 24, false) - ], - [ - editOp(1, 7, 1, 12, ['friends']) - ], - [], - [ - 'Hello friends,', - 'this is a short text', - 'that is used in testing' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 2, 1, false), - marker('f', 2, 16, true), - marker('g', 2, 21, true), - marker('h', 3, 24, false) - ] - ); - }); - - test('inserting lines', () => { - testApplyEditsAndMarkers( - [ - 'Hello world,', - 'this is a short text', - 'that is used in testing' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 2, 1, false), - marker('f', 2, 16, true), - marker('g', 2, 21, true), - marker('h', 3, 24, false) - ], - [ - editOp(1, 7, 1, 12, ['friends']), - editOp(1, 13, 1, 13, ['', 'this is an inserted line', 'and another one. By the way,']) - ], - ['e', 'f', 'g', 'h'], - [ - 'Hello friends,', - 'this is an inserted line', - 'and another one. By the way,', - 'this is a short text', - 'that is used in testing' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 4, 1, false), - marker('f', 4, 16, true), - marker('g', 4, 21, true), - marker('h', 5, 24, false) - ] - ); - }); - - test('replacing a lot', () => { - testApplyEditsAndMarkers( - [ - 'Hello world,', - 'this is a short text', - 'that is used in testing', - 'more lines...', - 'more lines...', - 'more lines...', - 'more lines...' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 2, 1, false), - marker('f', 2, 16, true), - marker('g', 2, 21, true), - marker('h', 3, 24, false), - marker('i', 5, 1, false), - marker('j', 6, 1, false), - marker('k', 7, 14, false), - ], - [ - editOp(1, 7, 1, 12, ['friends']), - editOp(1, 13, 1, 13, ['', 'this is an inserted line', 'and another one. By the way,', 'This is another line']), - editOp(2, 1, 7, 14, ['Some new text here']) - ], - ['e', 'f', 'g', 'h', 'i', 'j', 'k'], - [ - 'Hello friends,', - 'this is an inserted line', - 'and another one. By the way,', - 'This is another line', - 'Some new text here' - ], - [ - marker('a', 1, 1, true), - marker('b', 1, 1, false), - marker('c', 1, 7, false), - marker('d', 1, 12, true), - marker('e', 5, 1, false), - marker('f', 5, 16, true), - marker('g', 5, 19, true), - marker('h', 5, 19, false), - marker('i', 5, 19, false), - marker('j', 5, 19, false), - marker('k', 5, 19, false), - ] - ); - }); -}); diff --git a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts index a901d29fcd3..b0b18723062 100644 --- a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts +++ b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts @@ -105,7 +105,6 @@ export function assertSyncedModels(text: string, callback: (model: EditableTextM var assertMirrorModels = () => { assertLineMapping(model, 'model'); - model._assertLineNumbersOK(); assert.equal(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK'); assert.equal(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK'); }; diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 54fd5d17424..26b004d0a0c 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -1094,7 +1094,6 @@ suite('deltaDecorations', () => { assert.equal(initialIds.length, decorations.length, 'returns expected cnt of ids'); assert.equal(initialIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(initialIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); - assert.equal(0, model._getMarkersCount(), 'does not leak markers'); actualDecorations.sort((a, b) => strcmp(a.id, b.id)); decorations.sort((a, b) => strcmp(a.id, b.id)); assert.deepEqual(actualDecorations, decorations); @@ -1105,7 +1104,6 @@ suite('deltaDecorations', () => { assert.equal(newIds.length, newDecorations.length, 'returns expected cnt of ids'); assert.equal(newIds.length, model.getAllDecorations().length, 'does not leak decorations'); assert.equal(newIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges'); - assert.equal(0, model._getMarkersCount(), 'does not leak markers'); actualNewDecorations.sort((a, b) => strcmp(a.id, b.id)); newDecorations.sort((a, b) => strcmp(a.id, b.id)); assert.deepEqual(actualDecorations, decorations); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 4b4e91c9824..7874e3fd4fb 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1641,12 +1641,6 @@ declare module monaco.editor { getWordUntilPosition(position: IPosition): IWordAtPosition; } - /** - * A model that can track markers. - */ - export interface ITextModelWithMarkers extends ITextModel { - } - /** * Describes the behavior of decorations when typing/editing near their edges. * Note: Please do not edit the values, as they very carefully match `DecorationRangeBehavior` @@ -1728,7 +1722,7 @@ declare module monaco.editor { /** * An editable text model. */ - export interface IEditableTextModel extends ITextModelWithMarkers { + export interface IEditableTextModel extends ITextModel { /** * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs). */ @@ -1772,7 +1766,7 @@ declare module monaco.editor { /** * A model. */ - export interface IModel extends IReadOnlyModel, IEditableTextModel, ITextModelWithMarkers, ITokenizedModel, ITextModelWithDecorations { + export interface IModel extends IReadOnlyModel, IEditableTextModel, ITokenizedModel, ITextModelWithDecorations { /** * An event emitted when the contents of the model have changed. * @event From 41f0ff15d7327da30fdae73aa04ca570ce34fa0a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 Oct 2017 12:47:39 +0200 Subject: [PATCH 167/394] deco - move scm decorations to git extension --- extensions/git/src/decorationProvider.ts | 96 +++++++++++++ extensions/git/src/main.ts | 4 +- extensions/git/src/repository.ts | 32 +++-- src/vs/vscode.d.ts | 6 - src/vs/vscode.proposed.d.ts | 1 + .../electron-browser/mainThreadDecorations.ts | 6 +- .../api/electron-browser/mainThreadSCM.ts | 5 +- src/vs/workbench/api/node/extHost.protocol.ts | 5 +- .../workbench/api/node/extHostDecorations.ts | 2 +- src/vs/workbench/api/node/extHostSCM.ts | 3 +- .../scm/electron-browser/scm.contribution.ts | 19 --- .../electron-browser/scmFileDecorations.ts | 136 ------------------ src/vs/workbench/services/scm/common/scm.ts | 2 - 13 files changed, 128 insertions(+), 189 deletions(-) create mode 100644 extensions/git/src/decorationProvider.ts delete mode 100644 src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts new file mode 100644 index 00000000000..ed4bad8aef0 --- /dev/null +++ b/extensions/git/src/decorationProvider.ts @@ -0,0 +1,96 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { window, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider } from 'vscode'; +import { Repository, GitResourceGroup } from './repository'; +import { Model } from './model'; + +class GitDecorationProvider implements DecorationProvider { + + private readonly _onDidChangeDecorations = new EventEmitter(); + readonly onDidChangeDecorations: Event = this._onDidChangeDecorations.event; + + private disposables: Disposable[] = []; + private decorations = new Map(); + + constructor(private repository: Repository) { + this.disposables.push( + window.registerDecorationProvider(this, repository.root), + repository.onDidRunOperation(this.onDidRunOperation, this) + ); + } + + private onDidRunOperation(): void { + let newDecorations = new Map(); + this.collectDecorationData(this.repository.indexGroup, newDecorations); + this.collectDecorationData(this.repository.workingTreeGroup, newDecorations); + + let uris: Uri[] = []; + newDecorations.forEach((value, uriString) => { + if (this.decorations.has(uriString)) { + this.decorations.delete(uriString); + } else { + uris.push(Uri.parse(uriString)); + } + }); + this.decorations.forEach((value, uriString) => { + uris.push(Uri.parse(uriString)); + }); + this.decorations = newDecorations; + this._onDidChangeDecorations.fire(uris); + } + + private collectDecorationData(group: GitResourceGroup, bucket: Map): void { + group.resourceStates.forEach(r => { + if (r.resourceDecoration) { + bucket.set(r.original.toString(), r.resourceDecoration); + } + }); + } + + provideDecoration(uri: Uri): DecorationData | undefined { + return this.decorations.get(uri.toString()); + } + + dispose(): void { + this.disposables.forEach(d => d.dispose()); + } +} + + +export class GitDecorations { + + private disposables: Disposable[] = []; + private providers = new Map(); + + constructor(private model: Model) { + this.disposables.push( + model.onDidOpenRepository(this.onDidOpenRepository, this), + model.onDidCloseRepository(this.onDidCloseRepository, this) + ); + model.repositories.forEach(this.onDidOpenRepository, this); + } + + private onDidOpenRepository(repository: Repository): void { + const provider = new GitDecorationProvider(repository); + this.providers.set(repository, provider); + } + + private onDidCloseRepository(repository: Repository): void { + const provider = this.providers.get(repository); + if (provider) { + provider.dispose(); + this.providers.delete(repository); + } + } + + dispose(): void { + this.disposables.forEach(d => d.dispose()); + this.providers.forEach(value => value.dispose); + this.providers.clear(); + } +} diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index acc30eeb81d..b090495be71 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -12,6 +12,7 @@ import { findGit, Git, IGit } from './git'; import { Model } from './model'; import { CommandCenter } from './commands'; import { GitContentProvider } from './contentProvider'; +import { GitDecorations } from './decorationProvider'; import { Askpass } from './askpass'; import { toDisposable } from './util'; import TelemetryReporter from 'vscode-extension-telemetry'; @@ -54,6 +55,7 @@ async function init(context: ExtensionContext, disposables: Disposable[]): Promi disposables.push( new CommandCenter(git, model, outputChannel, telemetryReporter), new GitContentProvider(model), + new GitDecorations(model) ); await checkGitVersion(info); @@ -93,4 +95,4 @@ async function checkGitVersion(info: IGit): Promise { } else if (choice === neverShowAgain) { await config.update('ignoreLegacyWarning', true, true); } -} \ No newline at end of file +} diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 6c9f781c58f..319edc3a07e 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -5,7 +5,7 @@ 'use strict'; -import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor } from 'vscode'; +import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData } from 'vscode'; import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType } from './git'; import { anyEvent, filterEvent, eventToPromise, dispose, find } from './util'; import { memoize, throttle, debounce } from './decorators'; @@ -170,27 +170,29 @@ export class Resource implements SourceControlResourceState { // return this.resourceUri.fsPath.substr(0, workspaceRootPath.length) !== workspaceRootPath; } - private get color(): ThemeColor | undefined { - switch (this.type) { - case Status.INDEX_MODIFIED: - case Status.MODIFIED: - return new ThemeColor('git.color.modified'); - case Status.UNTRACKED: - return new ThemeColor('git.color.untracked'); - default: - return undefined; - } - } - get decorations(): SourceControlResourceDecorations { const light = { iconPath: this.getIconPath('light') }; const dark = { iconPath: this.getIconPath('dark') }; const tooltip = this.tooltip; const strikeThrough = this.strikeThrough; const faded = this.faded; - const color = this.color; - return { strikeThrough, faded, tooltip, light, dark, color }; + return { strikeThrough, faded, tooltip, light, dark }; + } + + get resourceDecoration(): DecorationData | undefined { + const title = this.tooltip; + switch (this.type) { + case Status.IGNORED: + return { priority: 3, title, opacity: 0.75 }; + case Status.UNTRACKED: + return { priority: 1, title, abbreviation: localize('untracked, short', "U"), bubble: true, color: new ThemeColor('git.color.untracked') }; + case Status.INDEX_MODIFIED: + case Status.MODIFIED: + return { priority: 2, title, abbreviation: localize('modified, short', "M"), bubble: true, color: new ThemeColor('git.color.modified') }; + default: + return undefined; + } } constructor( diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 891b0b2289f..09c84d07fc1 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5795,12 +5795,6 @@ declare module 'vscode' { */ readonly tooltip?: string; - /** - * A color for a specific - * [source control resource state](#SourceControlResourceState). - */ - readonly color?: ThemeColor; - /** * The light theme decorations. */ diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index e8485b673fc..d48b0f9020a 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -175,6 +175,7 @@ declare module 'vscode' { export interface DecorationData { priority?: number; title?: string; + bubble?: boolean; abbreviation?: string; color?: ThemeColor; opacity?: number; diff --git a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts index 1dd8523ff44..b2ae08b829c 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts @@ -36,9 +36,13 @@ export class MainThreadDecorations implements MainThreadDecorationsShape { onDidChange: emitter.event, provideDecorations: (uri) => { return this._proxy.$providerDecorations(handle, uri).then(data => { - const [weight, title, letter, opacity, themeColor] = data; + if (!data) { + return undefined; + } + const [weight, bubble, title, letter, opacity, themeColor] = data; return { weight: weight || 0, + bubble: bubble || false, title, letter, opacity, diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 69b253930b7..64253cfa2d4 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -182,7 +182,7 @@ class MainThreadSCMProvider implements ISCMProvider { for (const [start, deleteCount, rawResources] of groupSlices) { const resources = rawResources.map(rawResource => { - const [handle, sourceUri, icons, tooltip, strikeThrough, faded, color] = rawResource; + const [handle, sourceUri, icons, tooltip, strikeThrough, faded] = rawResource; const icon = icons[0]; const iconDark = icons[1] || icon; const decorations = { @@ -190,8 +190,7 @@ class MainThreadSCMProvider implements ISCMProvider { iconDark: iconDark && URI.parse(iconDark), tooltip, strikeThrough, - faded, - color: color && color.id + faded }; return new MainThreadSCMResource( diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index eee71c3f13d..5de663decdf 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -362,8 +362,7 @@ export type SCMRawResource = [ string[] /*icons: light, dark*/, string /*tooltip*/, boolean /*strike through*/, - boolean /*faded*/, - { id: string } /*ThemeColor*/ + boolean /*faded*/ ]; export type SCMRawResourceSplice = [ @@ -603,7 +602,7 @@ export interface ExtHostDebugServiceShape { } -export type DecorationData = [number, string, string, number, ThemeColor]; +export type DecorationData = [number, boolean, string, string, number, ThemeColor]; export interface ExtHostDecorationsShape { $providerDecorations(handle: number, uri: URI): TPromise; diff --git a/src/vs/workbench/api/node/extHostDecorations.ts b/src/vs/workbench/api/node/extHostDecorations.ts index 05b93b96f33..ad428987404 100644 --- a/src/vs/workbench/api/node/extHostDecorations.ts +++ b/src/vs/workbench/api/node/extHostDecorations.ts @@ -41,7 +41,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape { $providerDecorations(handle: number, uri: URI): TPromise { const provider = this._provider.get(handle); return asWinJsPromise(token => provider.provideDecoration(uri, token)).then(data => { - return [data.priority, data.title, data.abbreviation, data.opacity, data.color]; + return data && [data.priority, data.bubble, data.title, data.abbreviation, data.opacity, data.color]; }); } } diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 9fafcbf368d..310ea752f91 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -243,9 +243,8 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG const tooltip = (r.decorations && r.decorations.tooltip) || ''; const strikeThrough = r.decorations && !!r.decorations.strikeThrough; const faded = r.decorations && !!r.decorations.faded; - const color = r.decorations && r.decorations.color; - return [handle, sourceUri, icons, tooltip, strikeThrough, faded, color] as SCMRawResource; + return [handle, sourceUri, icons, tooltip, strikeThrough, faded] as SCMRawResource; }); handlesToDelete.push(...this._handlesSnapshot.splice(start, deleteCount, ...handles)); diff --git a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts index 9405fdb123c..b5465c83f69 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts @@ -17,9 +17,7 @@ import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { StatusUpdater, StatusBarController } from './scmActivity'; -import { FileDecorations } from './scmFileDecorations'; import { SCMViewlet } from 'vs/workbench/parts/scm/electron-browser/scmViewlet'; -import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; class OpenSCMViewletAction extends ToggleViewletAction { @@ -51,9 +49,6 @@ Registry.as(WorkbenchExtensions.Workbench) Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(StatusBarController); -Registry.as(WorkbenchExtensions.Workbench) - .registerWorkbenchContribution(FileDecorations); - // Register Action to Open Viewlet Registry.as(WorkbenchActionExtensions.WorkbenchActions).registerWorkbenchAction( new SyncActionDescriptor(OpenSCMViewletAction, VIEWLET_ID, localize('toggleSCMViewlet', "Show SCM"), { @@ -65,17 +60,3 @@ Registry.as(WorkbenchActionExtensions.WorkbenchActions 'View: Show SCM', localize('view', "View") ); - - -Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': 'scm', - 'order': 101, - 'type': 'object', - 'properties': { - 'scm.fileDecorations.enabled': { - 'description': localize('scm.fileDecorations.enabled', "Show source control status on files and folders"), - 'type': 'boolean', - 'default': true - } - } -}); diff --git a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts b/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts deleted file mode 100644 index 23e0d15fdae..00000000000 --- a/src/vs/workbench/parts/scm/electron-browser/scmFileDecorations.ts +++ /dev/null @@ -1,136 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IDecorationsService, IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; -import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; -import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource } from 'vs/workbench/services/scm/common/scm'; -import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { localize } from 'vs/nls'; - -class SCMDecorationsProvider implements IDecorationsProvider { - - private readonly _disposable: IDisposable; - private readonly _onDidChange = new Emitter(); - private _data = new Map(); - - readonly label: string; - readonly onDidChange: Event = this._onDidChange.event; - - constructor( - private readonly _provider: ISCMProvider, - private readonly _config: ISCMConfiguration - ) { - this.label = this._provider.label; - this._disposable = this._provider.onDidChangeResources(this._updateGroups, this); - this._updateGroups(); - } - - dispose(): void { - this._disposable.dispose(); - } - - private _updateGroups(): void { - const uris: URI[] = []; - const newData = new Map(); - for (const group of this._provider.resources) { - for (const resource of group.resourceCollection.resources) { - newData.set(resource.sourceUri.toString(), resource); - - if (!this._data.has(resource.sourceUri.toString())) { - uris.push(resource.sourceUri); // added - } - } - } - - this._data.forEach((value, key) => { - if (!newData.has(key)) { - uris.push(value.sourceUri); // removed - } - }); - - this._data = newData; - this._onDidChange.fire(uris); - } - - provideDecorations(uri: URI): IDecorationData { - const resource = this._data.get(uri.toString()); - if (!resource || !resource.decorations.color || !resource.decorations.tooltip) { - return undefined; - } - return { - bubble: true, - weight: 255 - resource.decorations.tooltip.charAt(0).toLowerCase().charCodeAt(0), - title: localize('tooltip', "{0}, {1}", resource.decorations.tooltip, this._provider.label), - color: resource.decorations.color, - letter: resource.decorations.tooltip.charAt(0) - }; - } -} - -interface ISCMConfiguration { - fileDecorations: { - enabled: boolean; - }; -} - -export class FileDecorations implements IWorkbenchContribution { - - private _providers = new Map(); - private _configListener: IDisposable; - private _repoListeners: IDisposable[]; - - constructor( - @IDecorationsService private _decorationsService: IDecorationsService, - @IConfigurationService private _configurationService: IConfigurationService, - @ISCMService private _scmService: ISCMService, - ) { - this._configListener = this._configurationService.onDidChangeConfiguration(e => e.affectsConfiguration('scm.fileDecorations.enabled') && this._update()); - this._update(); - } - - getId(): string { - throw new Error('smc.SCMFileDecorations'); - } - - dispose(): void { - this._providers.forEach(value => dispose(value)); - dispose(this._repoListeners); - dispose(this._configListener, this._configListener); - } - - private _update(): void { - const config = this._configurationService.getConfiguration('scm'); - if (config.fileDecorations.enabled) { - this._scmService.repositories.forEach(this._onDidAddRepository, this); - this._repoListeners = [ - this._scmService.onDidAddRepository(this._onDidAddRepository, this), - this._scmService.onDidRemoveRepository(this._onDidRemoveRepository, this) - ]; - } else { - this._repoListeners = dispose(this._repoListeners); - this._providers.forEach(value => dispose(value)); - this._providers.clear(); - } - } - - private _onDidAddRepository(repo: ISCMRepository): void { - const provider = new SCMDecorationsProvider(repo.provider, this._configurationService.getConfiguration('scm')); - const registration = this._decorationsService.registerDecorationsProvider(provider); - this._providers.set(repo, combinedDisposable([registration, provider])); - } - - private _onDidRemoveRepository(repo: ISCMRepository): void { - let listener = this._providers.get(repo); - if (listener) { - this._providers.delete(repo); - listener.dispose(); - } - } -} diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index e5dda8e6e2b..b659bfeedc4 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -11,7 +11,6 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import Event from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Command } from 'vs/editor/common/modes'; -import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; export interface IBaselineResourceProvider { getBaselineResource(resource: URI): TPromise; @@ -25,7 +24,6 @@ export interface ISCMResourceDecorations { tooltip?: string; strikeThrough?: boolean; faded?: boolean; - color?: ColorIdentifier; } export interface ISCMResourceSplice { From 828dd97c2dc6096c5289147fd4a0959ca7941dee Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 17 Oct 2017 14:39:54 +0200 Subject: [PATCH 168/394] fixes #36340 --- src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts | 6 +++++- .../parts/scm/electron-browser/dirtydiffDecorator.ts | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index 24acb8e2eba..da7e44b07dd 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -395,7 +395,11 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { // Reveal the line above or below the zone widget, to get the zone widget in the viewport const revealLineNumber = Math.min(this.editor.getModel().getLineCount(), Math.max(1, where.endLineNumber + 1)); - this.editor.revealLineInCenterIfOutsideViewport(revealLineNumber, ScrollType.Smooth); + this.revealLine(revealLineNumber); + } + + protected revealLine(lineNumber: number) { + this.editor.revealLine(lineNumber, ScrollType.Smooth); } protected setCssClass(className: string, classToReplace?: string): void { diff --git a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts index cdb0a5ab4a4..7096a5a7c00 100644 --- a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts @@ -315,6 +315,10 @@ class DirtyDiffWidget extends PeekViewWidget { secondaryHeadingColor: theme.getColor(peekViewTitleInfoForeground) }); } + + protected revealLine(lineNumber: number) { + this.editor.revealLineInCenterIfOutsideViewport(lineNumber, ScrollType.Smooth); + } } @editorAction From 2ce576d8a1c4c660e54f7dcc675811901e2a9ed2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 Oct 2017 15:38:36 +0200 Subject: [PATCH 169/394] fix tests --- .../extensions/test/electron-browser/extensionsActions.test.ts | 2 +- .../test/electron-browser/extensionsWorkbenchService.test.ts | 2 +- .../services/keybinding/test/node/keybindingEditing.test.ts | 1 + .../test/electron-browser/api/mainThreadConfiguration.test.ts | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts index 405be3a135f..17f180eedc1 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts @@ -53,7 +53,7 @@ suite('ExtensionsActions Test', () => { instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(IWorkspaceContextService, new TestContextService()); - instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, getConfiguration: () => ({}) }); + instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, onDidChangeConfiguration: () => { }, getConfiguration: () => ({}) }); instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index 3cfe083cd16..2fad5c275f0 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -56,7 +56,7 @@ suite('ExtensionsWorkbenchService Test', () => { instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); instantiationService.stub(IWorkspaceContextService, new TestContextService()); - instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, getConfiguration: () => ({}) }); + instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, onDidChangeConfiguration: () => { }, getConfiguration: () => ({}) }); instantiationService.stub(IExtensionManagementService, ExtensionManagementService); instantiationService.stub(IExtensionManagementService, 'onInstallExtension', installEvent.event); diff --git a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts index 9ee62bfdc44..6f003bde491 100644 --- a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts @@ -67,6 +67,7 @@ suite('Keybindings Editing', () => { instantiationService.stub(IConfigurationService, ConfigurationService); instantiationService.stub(IConfigurationService, 'getConfiguration', { 'eol': '\n' }); instantiationService.stub(IConfigurationService, 'onDidUpdateConfiguration', () => { }); + instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', () => { }); instantiationService.stub(IWorkspaceContextService, new TestContextService()); instantiationService.stub(ILifecycleService, new TestLifecycleService()); instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts index 5cd09140d48..b91637eeeae 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts @@ -50,6 +50,7 @@ suite('MainThreadConfiguration', function () { instantiationService = new TestInstantiationService(); instantiationService.stub(IConfigurationService, WorkspaceService); instantiationService.stub(IConfigurationService, 'onDidUpdateConfiguration', sinon.mock()); + instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', sinon.mock()); instantiationService.stub(IConfigurationService, 'updateValue', target); }); From d882decfcbf6eac5da54826daaf686cb676b9a0e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 16:02:04 +0200 Subject: [PATCH 170/394] Delete LineMarker and associated code --- .../editor/common/model/editableTextModel.ts | 63 +- src/vs/editor/common/model/modelLine.ts | 419 +------- .../common/model/textModelWithDecorations.ts | 93 +- .../test/common/commands/sideEditing.test.ts | 20 - .../test/common/model/model.line.test.ts | 910 +----------------- 5 files changed, 125 insertions(+), 1380 deletions(-) diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index 0880fc0824b..ca0508e2ad1 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -7,12 +7,11 @@ import { Range, IRange } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { EditStack } from 'vs/editor/common/model/editStack'; -import { ILineEdit, LineMarker, MarkersTracker, IModelLine } from 'vs/editor/common/model/modelLine'; +import { ILineEdit, IModelLine } from 'vs/editor/common/model/modelLine'; import { TextModelWithDecorations, ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import * as strings from 'vs/base/common/strings'; import * as arrays from 'vs/base/common/arrays'; import { Selection } from 'vs/editor/common/core/selection'; -import { Position } from 'vs/editor/common/core/position'; import { IDisposable } from 'vs/base/common/lifecycle'; import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource, RawTextSource } from 'vs/editor/common/model/textSource'; @@ -277,15 +276,15 @@ export class EditableTextModel extends TextModelWithDecorations implements edito public applyEdits(rawOperations: editorCommon.IIdentifiedSingleEditOperation[]): editorCommon.IIdentifiedSingleEditOperation[] { try { this._eventEmitter.beginDeferredEmit(); - let markersTracker = this._acquireMarkersTracker(); - return this._applyEdits(markersTracker, rawOperations); + this._acquireMarkersTracker(); + return this._applyEdits(rawOperations); } finally { this._releaseMarkersTracker(); this._eventEmitter.endDeferredEmit(); } } - private _applyEdits(markersTracker: MarkersTracker, rawOperations: editorCommon.IIdentifiedSingleEditOperation[]): editorCommon.IIdentifiedSingleEditOperation[] { + private _applyEdits(rawOperations: editorCommon.IIdentifiedSingleEditOperation[]): editorCommon.IIdentifiedSingleEditOperation[] { if (rawOperations.length === 0) { return []; } @@ -383,7 +382,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._mightContainRTL = mightContainRTL; this._mightContainNonBasicASCII = mightContainNonBasicASCII; - this._doApplyEdits(markersTracker, operations); + this._doApplyEdits(operations); this._trimAutoWhitespaceLines = null; if (this._options.trimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { @@ -470,7 +469,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito return result; } - private _doApplyEdits(markersTracker: MarkersTracker, operations: IValidatedEditOperation[]): void { + private _doApplyEdits(operations: IValidatedEditOperation[]): void { const tabSize = this._options.tabSize; @@ -508,7 +507,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } this._invalidateLine(currentLineNumber - 1); - this._lines[currentLineNumber - 1].applyEdits(markersTracker, lineEditsQueue.slice(currentLineNumberStart, i), tabSize); + this._lines[currentLineNumber - 1].applyEdits(lineEditsQueue.slice(currentLineNumberStart, i), tabSize); if (this._lineStarts) { // update prefix sum this._lineStarts.changeValue(currentLineNumber - 1, this._lines[currentLineNumber - 1].text.length + this._EOL.length); @@ -522,7 +521,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } this._invalidateLine(currentLineNumber - 1); - this._lines[currentLineNumber - 1].applyEdits(markersTracker, lineEditsQueue.slice(currentLineNumberStart, lineEditsQueue.length), tabSize); + this._lines[currentLineNumber - 1].applyEdits(lineEditsQueue.slice(currentLineNumberStart, lineEditsQueue.length), tabSize); if (this._lineStarts) { // update prefix sum this._lineStarts.changeValue(currentLineNumber - 1, this._lines[currentLineNumber - 1].text.length + this._EOL.length); @@ -534,10 +533,6 @@ export class EditableTextModel extends TextModelWithDecorations implements edito lineEditsQueue = []; }; - let minTouchedLineNumber = operations[operations.length - 1].range.startLineNumber; - let maxTouchedLineNumber = operations[0].range.endLineNumber + 1; - let totalLinesCountDelta = 0; - for (let i = 0, len = operations.length; i < len; i++) { const op = operations[i]; @@ -561,8 +556,6 @@ export class EditableTextModel extends TextModelWithDecorations implements edito const insertingLinesCnt = (op.lines ? op.lines.length - 1 : 0); const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt); - totalLinesCountDelta += (insertingLinesCnt - deletingLinesCnt); - // Iterating descending to overlap with previous op // in case there are common lines being edited in both for (let j = editingLinesCnt; j >= 0; j--) { @@ -572,8 +565,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito lineNumber: editLineNumber, startColumn: (editLineNumber === startLineNumber ? startColumn : 1), endColumn: (editLineNumber === endLineNumber ? endColumn : this.getLineMaxColumn(editLineNumber)), - text: (op.lines ? op.lines[j] : ''), - forceMoveMarkers: op.forceMoveMarkers + text: (op.lines ? op.lines[j] : '') }); } @@ -584,23 +576,12 @@ export class EditableTextModel extends TextModelWithDecorations implements edito flushLineEdits(); const spliceStartLineNumber = startLineNumber + editingLinesCnt; - const spliceStartColumn = this.getLineMaxColumn(spliceStartLineNumber); - const endLineRemains = this._lines[endLineNumber - 1].split(markersTracker, endColumn, false, tabSize); + const endLineRemains = this._lines[endLineNumber - 1].split(endColumn, tabSize); this._invalidateLine(spliceStartLineNumber - 1); const spliceCnt = endLineNumber - spliceStartLineNumber; - // Collect all these markers - let markersOnDeletedLines: LineMarker[] = []; - for (let j = 0; j < spliceCnt; j++) { - const deleteLineIndex = spliceStartLineNumber + j; - const deleteLineMarkers = this._lines[deleteLineIndex].getMarkers(); - if (deleteLineMarkers) { - markersOnDeletedLines = markersOnDeletedLines.concat(deleteLineMarkers); - } - } - this._lines.splice(spliceStartLineNumber, spliceCnt); if (this._lineStarts) { // update prefix sum @@ -608,19 +589,12 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } // Reconstruct first line - this._lines[spliceStartLineNumber - 1].append(markersTracker, spliceStartLineNumber, endLineRemains, tabSize); + this._lines[spliceStartLineNumber - 1].append(endLineRemains, tabSize); if (this._lineStarts) { // update prefix sum this._lineStarts.changeValue(spliceStartLineNumber - 1, this._lines[spliceStartLineNumber - 1].text.length + this._EOL.length); } - // Update deleted markers - const deletedMarkersPosition = new Position(spliceStartLineNumber, spliceStartColumn); - for (let j = 0, lenJ = markersOnDeletedLines.length; j < lenJ; j++) { - markersOnDeletedLines[j].updatePosition(markersTracker, deletedMarkersPosition); - } - - this._lines[spliceStartLineNumber - 1].addMarkers(markersOnDeletedLines); rawContentChanges.push( new textModelEvents.ModelRawLineChanged(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1].text) ); @@ -643,7 +617,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } // Split last line - let leftoverLine = this._lines[spliceLineNumber - 1].split(markersTracker, spliceColumn, op.forceMoveMarkers, tabSize); + let leftoverLine = this._lines[spliceLineNumber - 1].split(spliceColumn, tabSize); if (this._lineStarts) { // update prefix sum this._lineStarts.changeValue(spliceLineNumber - 1, this._lines[spliceLineNumber - 1].text.length + this._EOL.length); @@ -670,7 +644,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } // Last line - this._lines[startLineNumber + insertingLinesCnt - 1].append(markersTracker, startLineNumber + insertingLinesCnt, leftoverLine, tabSize); + this._lines[startLineNumber + insertingLinesCnt - 1].append(leftoverLine, tabSize); if (this._lineStarts) { // update prefix sum this._lineStarts.changeValue(startLineNumber + insertingLinesCnt - 1, this._lines[startLineNumber + insertingLinesCnt - 1].text.length + this._EOL.length); @@ -695,16 +669,6 @@ export class EditableTextModel extends TextModelWithDecorations implements edito flushLineEdits(); - maxTouchedLineNumber = Math.max(1, Math.min(this.getLineCount(), maxTouchedLineNumber + totalLinesCountDelta)); - if (totalLinesCountDelta !== 0) { - // must update line numbers all the way to the bottom - maxTouchedLineNumber = this.getLineCount(); - } - - for (let lineNumber = minTouchedLineNumber; lineNumber <= maxTouchedLineNumber; lineNumber++) { - this._lines[lineNumber - 1].updateLineNumber(markersTracker, lineNumber); - } - if (rawContentChanges.length !== 0 || contentChanges.length !== 0) { this._increaseVersionId(); @@ -726,7 +690,6 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._eventEmitter.emit(textModelEvents.TextModelEventType.ModelContentChanged, e); } - // this._assertLineNumbersOK(); this._resetIndentRanges(); } diff --git a/src/vs/editor/common/model/modelLine.ts b/src/vs/editor/common/model/modelLine.ts index e71219bd689..b811f40a73f 100644 --- a/src/vs/editor/common/model/modelLine.ts +++ b/src/vs/editor/common/model/modelLine.ts @@ -7,94 +7,12 @@ import { IState, FontStyle, StandardTokenType, MetadataConsts, ColorId, LanguageId } from 'vs/editor/common/modes'; import { CharCode } from 'vs/base/common/charCode'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; -import { Position } from 'vs/editor/common/core/position'; import { Constants } from 'vs/editor/common/core/uint'; export interface ILineEdit { startColumn: number; endColumn: number; text: string; - forceMoveMarkers: boolean; -} - -export class LineMarker { - _lineMarkerBrand: void; - - public readonly id: string; - public readonly internalDecorationId: number; - - public stickToPreviousCharacter: boolean; - public position: Position; - - constructor(id: string, internalDecorationId: number, position: Position, stickToPreviousCharacter: boolean) { - this.id = id; - this.internalDecorationId = internalDecorationId; - this.position = position; - this.stickToPreviousCharacter = stickToPreviousCharacter; - } - - public toString(): string { - return '{\'' + this.id + '\';' + this.position.toString() + ',' + this.stickToPreviousCharacter + '}'; - } - - public updateLineNumber(markersTracker: MarkersTracker, lineNumber: number): void { - if (this.position.lineNumber === lineNumber) { - return; - } - markersTracker.addChangedMarker(this); - this.position = new Position(lineNumber, this.position.column); - } - - public updateColumn(markersTracker: MarkersTracker, column: number): void { - if (this.position.column === column) { - return; - } - markersTracker.addChangedMarker(this); - this.position = new Position(this.position.lineNumber, column); - } - - public updatePosition(markersTracker: MarkersTracker, position: Position): void { - if (this.position.lineNumber === position.lineNumber && this.position.column === position.column) { - return; - } - markersTracker.addChangedMarker(this); - this.position = position; - } - - public setPosition(position: Position) { - this.position = position; - } - - - public static compareMarkers(a: LineMarker, b: LineMarker): number { - if (a.position.column === b.position.column) { - return (a.stickToPreviousCharacter ? 0 : 1) - (b.stickToPreviousCharacter ? 0 : 1); - } - return a.position.column - b.position.column; - } -} - -export class MarkersTracker { - _changedDecorationsBrand: void; - - private _changedDecorations: number[]; - private _changedDecorationsLen: number; - - constructor() { - this._changedDecorations = []; - this._changedDecorationsLen = 0; - } - - public addChangedMarker(marker: LineMarker): void { - let internalDecorationId = marker.internalDecorationId; - if (internalDecorationId !== 0) { - this._changedDecorations[this._changedDecorationsLen++] = internalDecorationId; - } - } - - public getDecorationIds(): number[] { - return this._changedDecorations; - } } export interface ITokensAdjuster { @@ -102,27 +20,10 @@ export interface ITokensAdjuster { finish(delta: number, lineTextLength: number): void; } -interface IMarkersAdjuster { - adjustDelta(toColumn: number, delta: number, minimumAllowedColumn: number, moveSemantics: MarkerMoveSemantics): void; - adjustSet(toColumn: number, newColumn: number, moveSemantics: MarkerMoveSemantics): void; - finish(delta: number, lineTextLength: number): void; -} - var NO_OP_TOKENS_ADJUSTER: ITokensAdjuster = { adjust: () => { }, finish: () => { } }; -var NO_OP_MARKERS_ADJUSTER: IMarkersAdjuster = { - adjustDelta: () => { }, - adjustSet: () => { }, - finish: () => { } -}; - -const enum MarkerMoveSemantics { - MarkerDefined = 0, - ForceMove = 1, - ForceStay = 2 -} /** * Returns: @@ -156,13 +57,6 @@ function computePlusOneIndentLevel(line: string, tabSize: number): number { export interface IModelLine { readonly text: string; - // --- markers - addMarker(marker: LineMarker): void; - addMarkers(markers: LineMarker[]): void; - removeMarker(marker: LineMarker): void; - removeMarkers(deleteMarkers: { [markerId: string]: boolean; }): void; - getMarkers(): LineMarker[]; - // --- tokenization resetTokenizationState(): void; isInvalid(): boolean; @@ -177,20 +71,14 @@ export interface IModelLine { getIndentLevel(): number; // --- editing - updateLineNumber(markersTracker: MarkersTracker, newLineNumber: number): void; - applyEdits(markersTracker: MarkersTracker, edits: ILineEdit[], tabSize: number): number; - append(markersTracker: MarkersTracker, myLineNumber: number, other: IModelLine, tabSize: number): void; - split(markersTracker: MarkersTracker, splitColumn: number, forceMoveMarkers: boolean, tabSize: number): IModelLine; + applyEdits(edits: ILineEdit[], tabSize: number): number; + append(other: IModelLine, tabSize: number): void; + split(splitColumn: number, tabSize: number): IModelLine; } export abstract class AbstractModelLine { - private _markers: LineMarker[]; - - constructor(initializeMarkers: boolean) { - if (initializeMarkers) { - this._markers = null; - } + constructor() { } /// @@ -202,121 +90,18 @@ export abstract class AbstractModelLine { /// - // private _printMarkers(): string { - // if (!this._markers) { - // return '[]'; - // } - // if (this._markers.length === 0) { - // return '[]'; - // } - - // var markers = this._markers; - - // var printMarker = (m:LineMarker) => { - // if (m.stickToPreviousCharacter) { - // return '|' + m.position.column; - // } - // return m.position.column + '|'; - // }; - // return '[' + markers.map(printMarker).join(', ') + ']'; - // } - - private _createMarkersAdjuster(markersTracker: MarkersTracker): IMarkersAdjuster { - if (!this._markers) { - return NO_OP_MARKERS_ADJUSTER; - } - if (this._markers.length === 0) { - return NO_OP_MARKERS_ADJUSTER; - } - - this._markers.sort(LineMarker.compareMarkers); - - var markers = this._markers; - var markersLength = markers.length; - var markersIndex = 0; - var marker = markers[markersIndex]; - - // console.log('------------- INITIAL MARKERS: ' + this._printMarkers()); - - let adjustMarkerBeforeColumn = (toColumn: number, moveSemantics: MarkerMoveSemantics) => { - if (marker.position.column < toColumn) { - return true; - } - if (marker.position.column > toColumn) { - return false; - } - if (moveSemantics === MarkerMoveSemantics.ForceMove) { - return false; - } - if (moveSemantics === MarkerMoveSemantics.ForceStay) { - return true; - } - return marker.stickToPreviousCharacter; - }; - - let adjustDelta = (toColumn: number, delta: number, minimumAllowedColumn: number, moveSemantics: MarkerMoveSemantics) => { - // console.log('------------------------------'); - // console.log('adjustDelta called: toColumn: ' + toColumn + ', delta: ' + delta + ', minimumAllowedColumn: ' + minimumAllowedColumn + ', moveSemantics: ' + MarkerMoveSemantics[moveSemantics]); - // console.log('BEFORE::: markersIndex: ' + markersIndex + ' : ' + this._printMarkers()); - - while (markersIndex < markersLength && adjustMarkerBeforeColumn(toColumn, moveSemantics)) { - if (delta !== 0) { - let newColumn = Math.max(minimumAllowedColumn, marker.position.column + delta); - marker.updateColumn(markersTracker, newColumn); - } - - markersIndex++; - if (markersIndex < markersLength) { - marker = markers[markersIndex]; - } - } - - // console.log('AFTER::: markersIndex: ' + markersIndex + ' : ' + this._printMarkers()); - }; - - let adjustSet = (toColumn: number, newColumn: number, moveSemantics: MarkerMoveSemantics) => { - // console.log('------------------------------'); - // console.log('adjustSet called: toColumn: ' + toColumn + ', newColumn: ' + newColumn + ', moveSemantics: ' + MarkerMoveSemantics[moveSemantics]); - // console.log('BEFORE::: markersIndex: ' + markersIndex + ' : ' + this._printMarkers()); - - while (markersIndex < markersLength && adjustMarkerBeforeColumn(toColumn, moveSemantics)) { - marker.updateColumn(markersTracker, newColumn); - - markersIndex++; - if (markersIndex < markersLength) { - marker = markers[markersIndex]; - } - } - - // console.log('AFTER::: markersIndex: ' + markersIndex + ' : ' + this._printMarkers()); - }; - - let finish = (delta: number, lineTextLength: number) => { - adjustDelta(Constants.MAX_SAFE_SMALL_INTEGER, delta, 1, MarkerMoveSemantics.MarkerDefined); - - // console.log('------------- FINAL MARKERS: ' + this._printMarkers()); - }; - - return { - adjustDelta: adjustDelta, - adjustSet: adjustSet, - finish: finish - }; - } - - public applyEdits(markersTracker: MarkersTracker, edits: ILineEdit[], tabSize: number): number { + public applyEdits(edits: ILineEdit[], tabSize: number): number { let deltaColumn = 0; let resultText = this.text; let tokensAdjuster = this._createTokensAdjuster(); - let markersAdjuster = this._createMarkersAdjuster(markersTracker); for (let i = 0, len = edits.length; i < len; i++) { let edit = edits[i]; // console.log(); // console.log('============================='); - // console.log('EDIT #' + i + ' [ ' + edit.startColumn + ' -> ' + edit.endColumn + ' ] : <<<' + edit.text + '>>>, forceMoveMarkers: ' + edit.forceMoveMarkers); + // console.log('EDIT #' + i + ' [ ' + edit.startColumn + ' -> ' + edit.endColumn + ' ] : <<<' + edit.text + '>>>'); // console.log('deltaColumn: ' + deltaColumn); let startColumn = deltaColumn + edit.startColumn; @@ -324,35 +109,28 @@ export abstract class AbstractModelLine { let deletingCnt = endColumn - startColumn; let insertingCnt = edit.text.length; - // Adjust tokens & markers before this edit - // console.log('Adjust tokens & markers before this edit'); + // Adjust tokens before this edit + // console.log('Adjust tokens before this edit'); tokensAdjuster.adjust(edit.startColumn - 1, deltaColumn, 1); - markersAdjuster.adjustDelta(edit.startColumn, deltaColumn, 1, edit.forceMoveMarkers ? MarkerMoveSemantics.ForceMove : (deletingCnt > 0 ? MarkerMoveSemantics.ForceStay : MarkerMoveSemantics.MarkerDefined)); - // Adjust tokens & markers for the common part of this edit + // Adjust tokens for the common part of this edit let commonLength = Math.min(deletingCnt, insertingCnt); if (commonLength > 0) { - // console.log('Adjust tokens & markers for the common part of this edit'); + // console.log('Adjust tokens for the common part of this edit'); tokensAdjuster.adjust(edit.startColumn - 1 + commonLength, deltaColumn, startColumn); - - if (!edit.forceMoveMarkers) { - markersAdjuster.adjustDelta(edit.startColumn + commonLength, deltaColumn, startColumn, edit.forceMoveMarkers ? MarkerMoveSemantics.ForceMove : (deletingCnt > insertingCnt ? MarkerMoveSemantics.ForceStay : MarkerMoveSemantics.MarkerDefined)); - } } // Perform the edit & update `deltaColumn` resultText = resultText.substring(0, startColumn - 1) + edit.text + resultText.substring(endColumn - 1); deltaColumn += insertingCnt - deletingCnt; - // Adjust tokens & markers inside this edit - // console.log('Adjust tokens & markers inside this edit'); + // Adjust tokens inside this edit + // console.log('Adjust tokens inside this edit'); tokensAdjuster.adjust(edit.endColumn, deltaColumn, startColumn); - markersAdjuster.adjustSet(edit.endColumn, startColumn + insertingCnt, edit.forceMoveMarkers ? MarkerMoveSemantics.ForceMove : MarkerMoveSemantics.MarkerDefined); } - // Wrap up tokens & markers; adjust remaining if needed + // Wrap up tokens; adjust remaining if needed tokensAdjuster.finish(deltaColumn, resultText.length); - markersAdjuster.finish(deltaColumn, resultText.length); // Save the resulting text this._setText(resultText, tabSize); @@ -360,157 +138,16 @@ export abstract class AbstractModelLine { return deltaColumn; } - public split(markersTracker: MarkersTracker, splitColumn: number, forceMoveMarkers: boolean, tabSize: number): IModelLine { - // console.log('--> split @ ' + splitColumn + '::: ' + this._printMarkers()); - var myText = this.text.substring(0, splitColumn - 1); - var otherText = this.text.substring(splitColumn - 1); - - var otherMarkers: LineMarker[] = null; - - if (this._markers) { - this._markers.sort(LineMarker.compareMarkers); - for (let i = 0, len = this._markers.length; i < len; i++) { - let marker = this._markers[i]; - - if ( - marker.position.column > splitColumn - || ( - marker.position.column === splitColumn - && ( - forceMoveMarkers - || !marker.stickToPreviousCharacter - ) - ) - ) { - let myMarkers = this._markers.slice(0, i); - otherMarkers = this._markers.slice(i); - this._markers = myMarkers; - break; - } - } - - if (otherMarkers) { - for (let i = 0, len = otherMarkers.length; i < len; i++) { - let marker = otherMarkers[i]; - - marker.updateColumn(markersTracker, marker.position.column - (splitColumn - 1)); - } - } - } + public split(splitColumn: number, tabSize: number): IModelLine { + const myText = this.text.substring(0, splitColumn - 1); + const otherText = this.text.substring(splitColumn - 1); this._setText(myText, tabSize); - - var otherLine = this._createModelLine(otherText, tabSize); - if (otherMarkers) { - otherLine.addMarkers(otherMarkers); - } - return otherLine; + return this._createModelLine(otherText, tabSize); } - public append(markersTracker: MarkersTracker, myLineNumber: number, other: IModelLine, tabSize: number): void { - // console.log('--> append: THIS :: ' + this._printMarkers()); - // console.log('--> append: OTHER :: ' + this._printMarkers()); - let thisTextLength = this.text.length; + public append(other: IModelLine, tabSize: number): void { this._setText(this.text + other.text, tabSize); - - if (other instanceof AbstractModelLine) { - if (other._markers) { - // Other has markers - let otherMarkers = other._markers; - - // Adjust other markers - for (let i = 0, len = otherMarkers.length; i < len; i++) { - let marker = otherMarkers[i]; - - marker.updatePosition(markersTracker, new Position(myLineNumber, marker.position.column + thisTextLength)); - } - - this.addMarkers(otherMarkers); - } - } - } - - public addMarker(marker: LineMarker): void { - if (!this._markers) { - this._markers = [marker]; - } else { - this._markers.push(marker); - } - } - - public addMarkers(markers: LineMarker[]): void { - if (markers.length === 0) { - return; - } - - if (!this._markers) { - this._markers = markers.slice(0); - } else { - this._markers = this._markers.concat(markers); - } - } - - public removeMarker(marker: LineMarker): void { - if (!this._markers) { - return; - } - - let index = this._indexOfMarkerId(marker.id); - if (index < 0) { - return; - } - - if (this._markers.length === 1) { - // was last marker on line - this._markers = null; - } else { - this._markers.splice(index, 1); - } - } - - public removeMarkers(deleteMarkers: { [markerId: string]: boolean; }): void { - if (!this._markers) { - return; - } - for (let i = 0, len = this._markers.length; i < len; i++) { - let marker = this._markers[i]; - - if (deleteMarkers[marker.id]) { - this._markers.splice(i, 1); - len--; - i--; - } - } - if (this._markers.length === 0) { - this._markers = null; - } - } - - public getMarkers(): LineMarker[] { - if (!this._markers) { - return null; - } - return this._markers; - } - - public updateLineNumber(markersTracker: MarkersTracker, newLineNumber: number): void { - if (this._markers) { - let markers = this._markers; - for (let i = 0, len = markers.length; i < len; i++) { - let marker = markers[i]; - marker.updateLineNumber(markersTracker, newLineNumber); - } - } - } - - private _indexOfMarkerId(markerId: string): number { - let markers = this._markers; - for (let i = 0, len = markers.length; i < len; i++) { - if (markers[i].id === markerId) { - return i; - } - } - return undefined; } } @@ -559,7 +196,7 @@ export class ModelLine extends AbstractModelLine implements IModelLine { private _lineTokens: ArrayBuffer; constructor(text: string, tabSize: number) { - super(true); + super(); this._metadata = 0; this._setText(text, tabSize); this._state = null; @@ -570,8 +207,8 @@ export class ModelLine extends AbstractModelLine implements IModelLine { return new ModelLine(text, tabSize); } - public split(markersTracker: MarkersTracker, splitColumn: number, forceMoveMarkers: boolean, tabSize: number): IModelLine { - let result = super.split(markersTracker, splitColumn, forceMoveMarkers, tabSize); + public split(splitColumn: number, tabSize: number): IModelLine { + let result = super.split(splitColumn, tabSize); // Mark overflowing tokens for deletion & delete marked tokens this._deleteMarkedTokens(this._markOverflowingTokensForDeletion(0, this.text.length)); @@ -579,10 +216,10 @@ export class ModelLine extends AbstractModelLine implements IModelLine { return result; } - public append(markersTracker: MarkersTracker, myLineNumber: number, other: IModelLine, tabSize: number): void { + public append(other: IModelLine, tabSize: number): void { let thisTextLength = this.text.length; - super.append(markersTracker, myLineNumber, other, tabSize); + super.append(other, tabSize); if (other instanceof ModelLine) { let otherRawTokens = other._lineTokens; @@ -828,7 +465,7 @@ export class MinimalModelLine extends AbstractModelLine implements IModelLine { } constructor(text: string, tabSize: number) { - super(false); + super(); this._setText(text, tabSize); } @@ -836,12 +473,12 @@ export class MinimalModelLine extends AbstractModelLine implements IModelLine { return new MinimalModelLine(text, tabSize); } - public split(markersTracker: MarkersTracker, splitColumn: number, forceMoveMarkers: boolean, tabSize: number): IModelLine { - return super.split(markersTracker, splitColumn, forceMoveMarkers, tabSize); + public split(splitColumn: number, tabSize: number): IModelLine { + return super.split(splitColumn, tabSize); } - public append(markersTracker: MarkersTracker, myLineNumber: number, other: IModelLine, tabSize: number): void { - super.append(markersTracker, myLineNumber, other, tabSize); + public append(other: IModelLine, tabSize: number): void { + super.append(other, tabSize); } // --- BEGIN STATE diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index de20a2b6aec..40e9add2c52 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -10,7 +10,6 @@ import * as strings from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; import { Range, IRange } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { MarkersTracker } from 'vs/editor/common/model/modelLine'; import { TextModelWithTokens } from 'vs/editor/common/model/textModelWithTokens'; import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; @@ -80,7 +79,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi private _currentDecorationsTracker: DecorationsTracker; private _currentDecorationsTrackerCnt: number; - private _currentMarkersTracker: MarkersTracker; private _currentMarkersTrackerCnt: number; protected _tree: IntervalTree; @@ -96,7 +94,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._currentDecorationsTracker = null; this._currentDecorationsTrackerCnt = 0; - this._currentMarkersTracker = null; this._currentMarkersTrackerCnt = 0; this._tree = new IntervalTree(); @@ -124,6 +121,35 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi // --- END TrackedRanges + private _acquireDecorationsTracker(): DecorationsTracker { + if (this._currentDecorationsTrackerCnt === 0) { + this._currentDecorationsTracker = new DecorationsTracker(); + } + this._currentDecorationsTrackerCnt++; + return this._currentDecorationsTracker; + } + + private _releaseDecorationsTracker(): void { + this._currentDecorationsTrackerCnt--; + if (this._currentDecorationsTrackerCnt === 0) { + let decorationsTracker = this._currentDecorationsTracker; + this._currentDecorationsTracker = null; + this._handleTrackedDecorations(decorationsTracker); + } + } + + private _handleTrackedDecorations(decorationsTracker: DecorationsTracker): void { + if ( + !decorationsTracker.didAddDecorations + && !decorationsTracker.didChangeDecorations + && !decorationsTracker.didRemoveDecorations + ) { + return; + } + + this.emitModelDecorationsChangedEvent(); + } + public changeDecorations(callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T { this._assertNotDisposed(); @@ -323,59 +349,17 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi return this._ensureNodesHaveRanges(result); } - protected _acquireMarkersTracker(): MarkersTracker { - if (this._currentMarkersTrackerCnt === 0) { - this._currentMarkersTracker = new MarkersTracker(); - } + protected _acquireMarkersTracker(): void { this._currentMarkersTrackerCnt++; - return this._currentMarkersTracker; } protected _releaseMarkersTracker(): void { this._currentMarkersTrackerCnt--; if (this._currentMarkersTrackerCnt === 0) { - let markersTracker = this._currentMarkersTracker; - this._currentMarkersTracker = null; - this._handleTrackedMarkers(markersTracker); + this.emitModelDecorationsChangedEvent(); } } - /** - * Handle changed markers (i.e. update decorations ranges) - */ - private _handleTrackedMarkers(markersTracker: MarkersTracker): void { - this.emitModelDecorationsChangedEvent(); - } - - private _acquireDecorationsTracker(): DecorationsTracker { - if (this._currentDecorationsTrackerCnt === 0) { - this._currentDecorationsTracker = new DecorationsTracker(); - } - this._currentDecorationsTrackerCnt++; - return this._currentDecorationsTracker; - } - - private _releaseDecorationsTracker(): void { - this._currentDecorationsTrackerCnt--; - if (this._currentDecorationsTrackerCnt === 0) { - let decorationsTracker = this._currentDecorationsTracker; - this._currentDecorationsTracker = null; - this._handleTrackedDecorations(decorationsTracker); - } - } - - private _handleTrackedDecorations(decorationsTracker: DecorationsTracker): void { - if ( - !decorationsTracker.didAddDecorations - && !decorationsTracker.didChangeDecorations - && !decorationsTracker.didRemoveDecorations - ) { - return; - } - - this.emitModelDecorationsChangedEvent(); - } - private emitModelDecorationsChangedEvent(): void { if (!this._isDisposing) { let e: textModelEvents.IModelDecorationsChangedEvent = {}; @@ -599,21 +583,6 @@ const TRACKED_RANGE_OPTIONS = [ ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter }), ]; -class ModelDeltaDecoration implements editorCommon.IModelDeltaDecoration { - - _modelDeltaDecorationBrand: void; - - index: number; - range: Range; - options: ModelDecorationOptions; - - constructor(index: number, range: Range, options: ModelDecorationOptions) { - this.index = index; - this.range = range; - this.options = options; - } -} - function _normalizeOptions(options: editorCommon.IModelDecorationOptions): ModelDecorationOptions { if (options instanceof ModelDecorationOptions) { return options; diff --git a/src/vs/editor/test/common/commands/sideEditing.test.ts b/src/vs/editor/test/common/commands/sideEditing.test.ts index a5e2100692c..ceaa7df8265 100644 --- a/src/vs/editor/test/common/commands/sideEditing.test.ts +++ b/src/vs/editor/test/common/commands/sideEditing.test.ts @@ -10,15 +10,12 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon'; -import { ILineEdit, ModelLine, LineMarker, MarkersTracker } from 'vs/editor/common/model/modelLine'; import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { Model } from 'vs/editor/common/model/model'; import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration'; import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl'; import { Cursor } from 'vs/editor/common/controller/cursor'; -const NO_TAB_SIZE = 0; - function testCommand(lines: string[], selections: Selection[], edits: IIdentifiedSingleEditOperation[], expectedLines: string[], expectedSelections: Selection[]): void { withMockCodeEditor(lines, {}, (editor, cursor) => { const model = editor.getModel(); @@ -35,15 +32,6 @@ function testCommand(lines: string[], selections: Selection[], edits: IIdentifie }); } -function testLineEditMarker(text: string, column: number, stickToPreviousCharacter: boolean, edit: ILineEdit, expectedColumn: number): void { - var line = new ModelLine(text, NO_TAB_SIZE); - line.addMarker(new LineMarker('1', 0, new Position(0, column), stickToPreviousCharacter)); - - line.applyEdits(new MarkersTracker(), [edit], NO_TAB_SIZE); - - assert.equal(line.getMarkers()[0].position.column, expectedColumn); -} - suite('Editor Side Editing - collapsed selection', () => { test('replace at selection', () => { @@ -90,14 +78,6 @@ suite('Editor Side Editing - collapsed selection', () => { ); }); - test('ModelLine.applyEdits uses `isReplace`', () => { - testLineEditMarker('something', 1, true, { startColumn: 1, endColumn: 1, text: 'asd', forceMoveMarkers: false }, 1); - testLineEditMarker('something', 1, true, { startColumn: 1, endColumn: 1, text: 'asd', forceMoveMarkers: true }, 4); - - testLineEditMarker('something', 1, false, { startColumn: 1, endColumn: 1, text: 'asd', forceMoveMarkers: false }, 4); - testLineEditMarker('something', 1, false, { startColumn: 1, endColumn: 1, text: 'asd', forceMoveMarkers: true }, 4); - }); - test('insert at selection', () => { testCommand( [ diff --git a/src/vs/editor/test/common/model/model.line.test.ts b/src/vs/editor/test/common/model/model.line.test.ts index 81dbba468d5..a2e75ba4ae9 100644 --- a/src/vs/editor/test/common/model/model.line.test.ts +++ b/src/vs/editor/test/common/model/model.line.test.ts @@ -6,9 +6,8 @@ import * as assert from 'assert'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; -import { ModelLine, ILineEdit, LineMarker, MarkersTracker } from 'vs/editor/common/model/modelLine'; +import { ModelLine, ILineEdit } from 'vs/editor/common/model/modelLine'; import { MetadataConsts } from 'vs/editor/common/modes'; -import { Position } from 'vs/editor/common/core/position'; import { ViewLineToken, ViewLineTokenFactory } from 'vs/editor/common/core/viewLineToken'; function assertLineTokens(_actual: LineTokens, _expected: TestToken[]): void { @@ -54,7 +53,7 @@ suite('Editor Model - modelLine.applyEdits text', () => { function testEdits(initial: string, edits: ILineEdit[], expected: string): void { var line = new ModelLine(initial, NO_TAB_SIZE); - line.applyEdits(new MarkersTracker(), edits, NO_TAB_SIZE); + line.applyEdits(edits, NO_TAB_SIZE); assert.equal(line.text, expected); } @@ -62,8 +61,7 @@ suite('Editor Model - modelLine.applyEdits text', () => { return { startColumn: startColumn, endColumn: endColumn, - text: text, - forceMoveMarkers: false + text: text }; } @@ -201,7 +199,7 @@ suite('Editor Model - modelLine.split text', () => { function testLineSplit(initial: string, splitColumn: number, expected1: string, expected2: string): void { var line = new ModelLine(initial, NO_TAB_SIZE); - var newLine = line.split(new MarkersTracker(), splitColumn, false, NO_TAB_SIZE); + var newLine = line.split(splitColumn, NO_TAB_SIZE); assert.equal(line.text, expected1); assert.equal(newLine.text, expected2); } @@ -239,7 +237,7 @@ suite('Editor Model - modelLine.append text', () => { function testLineAppend(a: string, b: string, expected: string): void { var line1 = new ModelLine(a, NO_TAB_SIZE); var line2 = new ModelLine(b, NO_TAB_SIZE); - line1.append(new MarkersTracker(), 1, line2, NO_TAB_SIZE); + line1.append(line2, NO_TAB_SIZE); assert.equal(line1.text, expected); } @@ -301,7 +299,7 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { let line = new ModelLine(initialText, NO_TAB_SIZE); line.setTokens(0, TestToken.toTokens(initialTokens)); - line.applyEdits(new MarkersTracker(), edits, NO_TAB_SIZE); + line.applyEdits(edits, NO_TAB_SIZE); assert.equal(line.text, expectedText); assertLineTokens(line.getTokens(0), expectedTokens); @@ -311,10 +309,10 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { let line = new ModelLine('some text', NO_TAB_SIZE); line.setTokens(0, TestToken.toTokens([new TestToken(0, 1)])); - line.applyEdits(new MarkersTracker(), [{ startColumn: 1, endColumn: 10, text: '', forceMoveMarkers: false }], NO_TAB_SIZE); + line.applyEdits([{ startColumn: 1, endColumn: 10, text: '' }], NO_TAB_SIZE); line.setTokens(0, new Uint32Array(0)); - line.applyEdits(new MarkersTracker(), [{ startColumn: 1, endColumn: 1, text: 'a', forceMoveMarkers: false }], NO_TAB_SIZE); + line.applyEdits([{ startColumn: 1, endColumn: 1, text: 'a' }], NO_TAB_SIZE); assertLineTokens(line.getTokens(0), [new TestToken(0, 1)]); }); @@ -330,7 +328,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', [ @@ -353,7 +350,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 2, endColumn: 2, text: 'x', - forceMoveMarkers: false }], 'axabcd efgh', [ @@ -376,7 +372,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 3, endColumn: 3, text: 'stu', - forceMoveMarkers: false }], 'axstuabcd efgh', [ @@ -399,7 +394,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 10, endColumn: 10, text: '\t', - forceMoveMarkers: false }], 'axstuabcd\t efgh', [ @@ -422,7 +416,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 12, endColumn: 12, text: 'dd', - forceMoveMarkers: false }], 'axstuabcd\t ddefgh', [ @@ -445,7 +438,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 18, endColumn: 18, text: 'xyz', - forceMoveMarkers: false }], 'axstuabcd\t ddefghxyz', [ @@ -468,7 +460,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 1, text: 'x', - forceMoveMarkers: false }], 'xaxstuabcd\t ddefghxyz', [ @@ -491,7 +482,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 22, endColumn: 22, text: 'x', - forceMoveMarkers: false }], 'xaxstuabcd\t ddefghxyzx', [ @@ -514,7 +504,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 2, endColumn: 2, text: '', - forceMoveMarkers: false }], 'xaxstuabcd\t ddefghxyzx', [ @@ -533,7 +522,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'a', [ @@ -554,7 +542,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 4, endColumn: 7, text: '', - forceMoveMarkers: false }], 'abcghij', [ @@ -576,7 +563,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 4, endColumn: 4, text: 'hello', - forceMoveMarkers: false }], 'abchellodefghij', [ @@ -599,7 +585,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 2, text: '', - forceMoveMarkers: false }], 'bcd efgh', [ @@ -622,7 +607,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 2, endColumn: 4, text: '', - forceMoveMarkers: false }], 'ad efgh', [ @@ -645,7 +629,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 5, text: '', - forceMoveMarkers: false }], ' efgh', [ @@ -667,7 +650,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 5, endColumn: 6, text: '', - forceMoveMarkers: false }], 'abcdefgh', [ @@ -689,7 +671,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 5, endColumn: 7, text: '', - forceMoveMarkers: false }], 'abcdfgh', [ @@ -711,7 +692,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 5, endColumn: 10, text: '', - forceMoveMarkers: false }], 'abcd', [ @@ -732,7 +712,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 10, text: '', - forceMoveMarkers: false }], '', [ @@ -753,7 +732,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 1, text: '', - forceMoveMarkers: false }], 'abcd efgh', [ @@ -776,7 +754,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 3, text: '', - forceMoveMarkers: false }], 'cd efgh', [ @@ -799,7 +776,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 5, endColumn: 10, text: '', - forceMoveMarkers: false }], 'abcd', [ @@ -822,7 +798,6 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 6, text: 'Hi', - forceMoveMarkers: false }], 'Hi world, ciao', [ @@ -849,12 +824,10 @@ suite('Editor Model - modelLine.applyEdits text & tokens', () => { startColumn: 1, endColumn: 6, text: 'Hi', - forceMoveMarkers: false }, { startColumn: 8, endColumn: 12, text: 'my friends', - forceMoveMarkers: false }], 'Hi wmy friends, ciao', [ @@ -873,7 +846,7 @@ suite('Editor Model - modelLine.split text & tokens', () => { let line = new ModelLine(initialText, NO_TAB_SIZE); line.setTokens(0, TestToken.toTokens(initialTokens)); - let other = line.split(new MarkersTracker(), splitColumn, false, NO_TAB_SIZE); + let other = line.split(splitColumn, NO_TAB_SIZE); assert.equal(line.text, expectedText1); assert.equal(other.text, expectedText2); @@ -960,7 +933,7 @@ suite('Editor Model - modelLine.append text & tokens', () => { let b = new ModelLine(bText, NO_TAB_SIZE); b.setTokens(0, TestToken.toTokens(bTokens)); - a.append(new MarkersTracker(), 1, b, NO_TAB_SIZE); + a.append(b, NO_TAB_SIZE); assert.equal(a.text, expectedText); assertLineTokens(a.getTokens(0), expectedTokens); @@ -1071,1260 +1044,483 @@ suite('Editor Model - modelLine.append text & tokens', () => { }); }); -interface ILightWeightMarker { - id: string; - lineNumber: number; - column: number; - stickToPreviousCharacter: boolean; -} +suite('Editor Model - modelLine.applyEdits', () => { -suite('Editor Model - modelLine.applyEdits text & markers', () => { - - function marker(id: number, column: number, stickToPreviousCharacter: boolean): LineMarker { - return new LineMarker(String(id), id, new Position(0, column), stickToPreviousCharacter); - } - - function toLightWeightMarker(marker: LineMarker): ILightWeightMarker { - return { - id: marker.id, - lineNumber: marker.position.lineNumber, - column: marker.position.column, - stickToPreviousCharacter: marker.stickToPreviousCharacter - }; - } - - function testLineEditMarkers(initialText: string, initialMarkers: LineMarker[], edits: ILineEdit[], expectedText: string, expectedChangedMarkers: number[], _expectedMarkers: LineMarker[]): void { + function testLineEdit(initialText: string, edits: ILineEdit[], expectedText: string): void { let line = new ModelLine(initialText, NO_TAB_SIZE); - line.addMarkers(initialMarkers); - let changedMarkers = new MarkersTracker(); - line.applyEdits(changedMarkers, edits, NO_TAB_SIZE); + line.applyEdits(edits, NO_TAB_SIZE); assert.equal(line.text, expectedText, 'text'); - - let actualMarkers = line.getMarkers().map(toLightWeightMarker); - let expectedMarkers = _expectedMarkers.map(toLightWeightMarker); - assert.deepEqual(actualMarkers, expectedMarkers, 'markers'); - - let actualChangedMarkers = changedMarkers.getDecorationIds(); - actualChangedMarkers.sort(); - assert.deepEqual(actualChangedMarkers, expectedChangedMarkers, 'changed markers'); } test('insertion: updates markers 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 1, endColumn: 1, text: 'abc', - forceMoveMarkers: false }], 'abcabcd efgh', - [2, 3, 4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 4, false), - marker(3, 5, true), - marker(4, 5, false), - marker(5, 8, true), - marker(6, 8, false), - marker(7, 13, true), - marker(8, 13, false) - ] ); }); test('insertion: updates markers 2', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 2, endColumn: 2, text: 'abc', - forceMoveMarkers: false }], 'aabcbcd efgh', - [4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 5, false), - marker(5, 8, true), - marker(6, 8, false), - marker(7, 13, true), - marker(8, 13, false) - ] ); }); test('insertion: updates markers 3', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 3, endColumn: 3, text: 'abc', - forceMoveMarkers: false }], 'ababccd efgh', - [5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 8, true), - marker(6, 8, false), - marker(7, 13, true), - marker(8, 13, false) - ] ); }); test('insertion: updates markers 4', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 5, endColumn: 5, text: 'abc', - forceMoveMarkers: false }], 'abcdabc efgh', - [6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 8, false), - marker(7, 13, true), - marker(8, 13, false) - ] ); }); test('insertion: updates markers 5', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 10, endColumn: 10, text: 'abc', - forceMoveMarkers: false }], 'abcd efghabc', - [8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 13, false) - ] ); }); test('insertion bis: updates markers 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', - [2, 3, 4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 2, false), - marker(3, 3, true), - marker(4, 3, false), - marker(5, 6, true), - marker(6, 6, false), - marker(7, 11, true), - marker(8, 11, false) - ] ); }); test('insertion bis: updates markers 2', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 2, endColumn: 2, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', - [4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 3, false), - marker(5, 6, true), - marker(6, 6, false), - marker(7, 11, true), - marker(8, 11, false) - ] ); }); test('insertion bis: updates markers 3', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 3, endColumn: 3, text: 'a', - forceMoveMarkers: false }], 'abacd efgh', - [5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 6, true), - marker(6, 6, false), - marker(7, 11, true), - marker(8, 11, false) - ] ); }); test('insertion bis: updates markers 4', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 5, endColumn: 5, text: 'a', - forceMoveMarkers: false }], 'abcda efgh', - [6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 6, false), - marker(7, 11, true), - marker(8, 11, false) - ] ); }); test('insertion bis: updates markers 5', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 10, endColumn: 10, text: 'a', - forceMoveMarkers: false }], 'abcd efgha', - [8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 11, false) - ] ); }); test('insertion: does not move marker at column 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [marker(1, 1, true)], [{ startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', - [], - [marker(1, 1, true)] ); }); test('insertion: does move marker at column 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [marker(1, 1, false)], [{ startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', - [1], - [marker(1, 2, false)] ); }); test('insertion: two markers at column 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - ], [{ startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', - [2], - [ - marker(1, 1, true), - marker(2, 2, false) - ] ); }); test('insertion: two markers at column 1 unsorted', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(2, 1, false), - marker(1, 1, true), - ], [{ startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }], 'aabcd efgh', - [2], - [ - marker(1, 1, true), - marker(2, 2, false) - ] ); }); test('deletion: updates markers 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 1, endColumn: 2, text: '', - forceMoveMarkers: false }], 'bcd efgh', - [3, 4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 1, true), - marker(4, 1, false), - marker(5, 4, true), - marker(6, 4, false), - marker(7, 9, true), - marker(8, 9, false) - ] ); }); test('deletion: updates markers 2', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 1, endColumn: 4, text: '', - forceMoveMarkers: false }], 'd efgh', - [3, 4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 1, true), - marker(4, 1, false), - marker(5, 2, true), - marker(6, 2, false), - marker(7, 7, true), - marker(8, 7, false) - ] ); }); test('deletion: updates markers 3', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 5, endColumn: 6, text: '', - forceMoveMarkers: false }], 'abcdefgh', - [7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 9, true), - marker(8, 9, false) - ] ); }); test('replace: updates markers 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], [{ startColumn: 1, endColumn: 1, text: 'a', - forceMoveMarkers: false }, { startColumn: 2, endColumn: 3, text: '', - forceMoveMarkers: false }], 'aacd efgh', - [2, 3, 4], - [ - marker(1, 1, true), - marker(2, 2, false), - marker(3, 3, true), - marker(4, 3, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ] ); }); test('delete near markers', () => { - testLineEditMarkers( + testLineEdit( 'abcd', - [ - marker(1, 3, true), - marker(2, 3, false) - ], [{ startColumn: 3, endColumn: 4, text: '', - forceMoveMarkers: false }], 'abd', - [], - [ - marker(1, 3, true), - marker(2, 3, false) - ] ); }); test('replace: updates markers 2', () => { - testLineEditMarkers( + testLineEdit( 'Hello world, how are you', - [ - marker(1, 1, false), - marker(2, 6, true), - marker(3, 14, false), - marker(4, 21, true) - ], [{ startColumn: 1, endColumn: 1, text: ' - ', - forceMoveMarkers: false }, { startColumn: 6, endColumn: 12, text: '', - forceMoveMarkers: false }, { startColumn: 22, endColumn: 25, text: 'things', - forceMoveMarkers: false }], ' - Hello, how are things', - [1, 2, 3, 4], - [ - marker(1, 4, false), - marker(2, 9, true), - marker(3, 11, false), - marker(4, 18, true) - ] ); }); test('sorts markers', () => { - testLineEditMarkers( + testLineEdit( 'Hello world, how are you', - [ - marker(4, 21, true), - marker(2, 6, true), - marker(1, 1, false), - marker(3, 14, false) - ], [{ startColumn: 1, endColumn: 1, text: ' - ', - forceMoveMarkers: false }, { startColumn: 6, endColumn: 12, text: '', - forceMoveMarkers: false }, { startColumn: 22, endColumn: 25, text: 'things', - forceMoveMarkers: false }], ' - Hello, how are things', - [1, 2, 3, 4], - [ - marker(1, 4, false), - marker(2, 9, true), - marker(3, 11, false), - marker(4, 18, true) - ] ); }); test('change text inside markers', () => { - testLineEditMarkers( + testLineEdit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 6, false), - marker(4, 10, true) - ], [{ startColumn: 6, endColumn: 10, text: '1234567', - forceMoveMarkers: false }], 'abcd 1234567', - [], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 6, false), - marker(4, 10, true) - ] ); }); test('inserting is different than replacing for markers part 1', () => { - testLineEditMarkers( + testLineEdit( 'abcd', - [ - marker(1, 2, false) - ], [{ startColumn: 2, endColumn: 2, text: 'INSERT', - forceMoveMarkers: false }], 'aINSERTbcd', - [1], - [ - marker(1, 8, false) - ] ); }); test('inserting is different than replacing for markers part 2', () => { - testLineEditMarkers( + testLineEdit( 'abcd', - [ - marker(1, 2, false) - ], [{ startColumn: 2, endColumn: 3, text: 'REPLACED', - forceMoveMarkers: false }], 'aREPLACEDcd', - [], - [ - marker(1, 2, false) - ] ); }); test('replacing the entire line with more text', () => { - testLineEditMarkers( + testLineEdit( 'this is a short text', - [ - marker(1, 1, false), - marker(2, 16, true), - ], [{ startColumn: 1, endColumn: 21, text: 'Some new text here', - forceMoveMarkers: false }], 'Some new text here', - [], - [ - marker(1, 1, false), - marker(2, 16, true), - ] ); }); test('replacing the entire line with less text', () => { - testLineEditMarkers( + testLineEdit( 'this is a short text', - [ - marker(1, 1, false), - marker(2, 16, true), - ], [{ startColumn: 1, endColumn: 21, text: 'ttt', - forceMoveMarkers: false }], 'ttt', - [2], - [ - marker(1, 1, false), - marker(2, 4, true), - ] ); }); test('replace selection', () => { - testLineEditMarkers( + testLineEdit( 'first', - [ - marker(1, 1, true), - marker(2, 6, false), - ], [{ startColumn: 1, endColumn: 6, text: 'something', - forceMoveMarkers: false }], 'something', - [2], - [ - marker(1, 1, true), - marker(2, 10, false), - ] ); }); }); -suite('Editor Model - modelLine.split text & markers', () => { +suite('Editor Model - modelLine.split', () => { - function marker(id: number, column: number, stickToPreviousCharacter: boolean): LineMarker { - return new LineMarker(String(id), id, new Position(0, column), stickToPreviousCharacter); - } - - function toLightWeightMarker(marker: LineMarker): ILightWeightMarker { - return { - id: marker.id, - lineNumber: marker.position.lineNumber, - column: marker.position.column, - stickToPreviousCharacter: marker.stickToPreviousCharacter - }; - } - - function testLineSplitMarkers(initialText: string, initialMarkers: LineMarker[], splitColumn: number, forceMoveMarkers: boolean, expectedText1: string, expectedText2: string, expectedChangedMarkers: number[], _expectedMarkers1: LineMarker[], _expectedMarkers2: LineMarker[]): void { + function testLineSplit(initialText: string, splitColumn: number, forceMoveMarkers: boolean, expectedText1: string, expectedText2: string): void { let line = new ModelLine(initialText, NO_TAB_SIZE); - line.addMarkers(initialMarkers); - let changedMarkers = new MarkersTracker(); - let otherLine = line.split(changedMarkers, splitColumn, forceMoveMarkers, NO_TAB_SIZE); + let otherLine = line.split(splitColumn, NO_TAB_SIZE); assert.equal(line.text, expectedText1, 'text'); assert.equal(otherLine.text, expectedText2, 'text'); - - let actualMarkers1 = line.getMarkers().map(toLightWeightMarker); - let expectedMarkers1 = _expectedMarkers1.map(toLightWeightMarker); - assert.deepEqual(actualMarkers1, expectedMarkers1, 'markers'); - - let actualMarkers2 = otherLine.getMarkers().map(toLightWeightMarker); - let expectedMarkers2 = _expectedMarkers2.map(toLightWeightMarker); - assert.deepEqual(actualMarkers2, expectedMarkers2, 'markers'); - - let actualChangedMarkers = changedMarkers.getDecorationIds(); - actualChangedMarkers.sort(); - assert.deepEqual(actualChangedMarkers, expectedChangedMarkers, 'changed markers'); } test('split at the beginning', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 1, false, '', 'abcd efgh', - [], - [ - marker(1, 1, true) - ], - [ - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ] ); }); test('split at the beginning 2', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 1, true, '', 'abcd efgh', - [], - [], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ] ); }); test('split at the end', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 10, false, 'abcd efgh', '', - [8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - ], - [ - marker(8, 1, false) - ] ); }); test('split it the middle 1', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 2, false, 'a', 'bcd efgh', - [4, 5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - ], - [ - marker(4, 1, false), - marker(5, 4, true), - marker(6, 4, false), - marker(7, 9, true), - marker(8, 9, false) - ] ); }); test('split it the middle 2', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 3, false, 'ab', 'cd efgh', - [5, 6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - ], - [ - marker(5, 3, true), - marker(6, 3, false), - marker(7, 8, true), - marker(8, 8, false) - ] ); }); test('split it the middle 3', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 5, false, 'abcd', ' efgh', - [6, 7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - ], - [ - marker(6, 1, false), - marker(7, 6, true), - marker(8, 6, false) - ] ); }); test('split it the middle 4', () => { - testLineSplitMarkers( + testLineSplit( 'abcd efgh', - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - marker(7, 10, true), - marker(8, 10, false) - ], 6, false, 'abcd ', 'efgh', - [7, 8], - [ - marker(1, 1, true), - marker(2, 1, false), - marker(3, 2, true), - marker(4, 2, false), - marker(5, 5, true), - marker(6, 5, false), - ], - [ - marker(7, 5, true), - marker(8, 5, false) - ] ); }); }); -suite('Editor Model - modelLine.append text & markers', () => { +suite('Editor Model - modelLine.append', () => { - function markerOnFirstLine(id: number, column: number, stickToPreviousCharacter: boolean): LineMarker { - return new LineMarker(String(id), id, new Position(1, column), stickToPreviousCharacter); - } - - function markerOnSecondLine(id: number, column: number, stickToPreviousCharacter: boolean): LineMarker { - return new LineMarker(String(id), id, new Position(2, column), stickToPreviousCharacter); - } - - function toLightWeightMarker(marker: LineMarker): ILightWeightMarker { - return { - id: marker.id, - lineNumber: marker.position.lineNumber, - column: marker.position.column, - stickToPreviousCharacter: marker.stickToPreviousCharacter - }; - } - - function testLinePrependMarkers(aText: string, aMarkers: LineMarker[], bText: string, bMarkers: LineMarker[], expectedText: string, expectedChangedMarkers: number[], _expectedMarkers: LineMarker[]): void { + function testLinePrependMarkers(aText: string, bText: string, expectedText: string): void { let a = new ModelLine(aText, NO_TAB_SIZE); - a.addMarkers(aMarkers); - let b = new ModelLine(bText, NO_TAB_SIZE); - b.addMarkers(bMarkers); - let changedMarkers = new MarkersTracker(); - a.append(changedMarkers, 1, b, NO_TAB_SIZE); + a.append(b, NO_TAB_SIZE); assert.equal(a.text, expectedText, 'text'); - - let actualMarkers = a.getMarkers().map(toLightWeightMarker); - let expectedMarkers = _expectedMarkers.map(toLightWeightMarker); - assert.deepEqual(actualMarkers, expectedMarkers, 'markers'); - - let actualChangedMarkers = changedMarkers.getDecorationIds(); - actualChangedMarkers.sort(); - assert.deepEqual(actualChangedMarkers, expectedChangedMarkers, 'changed markers'); } test('append to an empty', () => { testLinePrependMarkers( 'abcd efgh', - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false), - markerOnFirstLine(5, 5, true), - markerOnFirstLine(6, 5, false), - markerOnFirstLine(7, 10, true), - markerOnFirstLine(8, 10, false), - ], '', - [ - ], 'abcd efgh', - [], - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false), - markerOnFirstLine(5, 5, true), - markerOnFirstLine(6, 5, false), - markerOnFirstLine(7, 10, true), - markerOnFirstLine(8, 10, false) - ] ); }); test('append an empty', () => { testLinePrependMarkers( '', - [ - ], 'abcd efgh', - [ - markerOnSecondLine(1, 1, true), - markerOnSecondLine(2, 1, false), - markerOnSecondLine(3, 2, true), - markerOnSecondLine(4, 2, false), - markerOnSecondLine(5, 5, true), - markerOnSecondLine(6, 5, false), - markerOnSecondLine(7, 10, true), - markerOnSecondLine(8, 10, false), - ], 'abcd efgh', - [1, 2, 3, 4, 5, 6, 7, 8], - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false), - markerOnFirstLine(5, 5, true), - markerOnFirstLine(6, 5, false), - markerOnFirstLine(7, 10, true), - markerOnFirstLine(8, 10, false) - ] ); }); test('append 1', () => { testLinePrependMarkers( 'abcd', - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false) - ], ' efgh', - [ - markerOnSecondLine(5, 1, true), - markerOnSecondLine(6, 1, false), - markerOnSecondLine(7, 6, true), - markerOnSecondLine(8, 6, false), - ], 'abcd efgh', - [5, 6, 7, 8], - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false), - markerOnFirstLine(5, 5, true), - markerOnFirstLine(6, 5, false), - markerOnFirstLine(7, 10, true), - markerOnFirstLine(8, 10, false) - ] ); }); test('append 2', () => { testLinePrependMarkers( 'abcd e', - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false), - markerOnFirstLine(5, 5, true), - markerOnFirstLine(6, 5, false) - ], 'fgh', - [ - markerOnSecondLine(7, 4, true), - markerOnSecondLine(8, 4, false), - ], 'abcd efgh', - [7, 8], - [ - markerOnFirstLine(1, 1, true), - markerOnFirstLine(2, 1, false), - markerOnFirstLine(3, 2, true), - markerOnFirstLine(4, 2, false), - markerOnFirstLine(5, 5, true), - markerOnFirstLine(6, 5, false), - markerOnFirstLine(7, 10, true), - markerOnFirstLine(8, 10, false) - ] ); }); }); From fcd266b58670db7e13c24c53ee3755ee46298871 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Tue, 17 Oct 2017 16:15:37 +0200 Subject: [PATCH 171/394] Log 0 for count telementries not undefined --- src/vs/workbench/electron-browser/shell.ts | 6 +++--- .../workbench/services/telemetry/common/workspaceStats.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index c5eb4b88f20..0430727fa3e 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -225,9 +225,9 @@ export class WorkbenchShell { userAgent: navigator.userAgent, windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth }, emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY, - 'workbench.filesToOpen': filesToOpen && filesToOpen.length || void 0, - 'workbench.filesToCreate': filesToCreate && filesToCreate.length || void 0, - 'workbench.filesToDiff': filesToDiff && filesToDiff.length || void 0, + 'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0, + 'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0, + 'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0, customKeybindingsCount: info.customKeybindingsCount, theme: this.themeService.getColorTheme().id, language: platform.language, diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/common/workspaceStats.ts index 5bdecfc2d37..9275928cd44 100644 --- a/src/vs/workbench/services/telemetry/common/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/common/workspaceStats.ts @@ -176,9 +176,9 @@ export class WorkspaceStats { const tags: Tags = Object.create(null); const { filesToOpen, filesToCreate, filesToDiff } = configuration; - tags['workbench.filesToOpen'] = filesToOpen && filesToOpen.length || undefined; - tags['workbench.filesToCreate'] = filesToCreate && filesToCreate.length || undefined; - tags['workbench.filesToDiff'] = filesToDiff && filesToDiff.length || undefined; + tags['workbench.filesToOpen'] = filesToOpen && filesToOpen.length || 0; + tags['workbench.filesToCreate'] = filesToCreate && filesToCreate.length || 0; + tags['workbench.filesToDiff'] = filesToDiff && filesToDiff.length || 0; const isEmpty = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; const workspace = this.contextService.getWorkspace(); From 281bfeb0781cc8709d88403d98f6efaa6d43c48c Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 17 Oct 2017 16:19:39 +0200 Subject: [PATCH 172/394] activityService: move pin methods to composite bar --- .../parts/activitybar/activitybarActions.ts | 26 --------- .../parts/activitybar/activitybarPart.ts | 23 ++------ .../parts/compositebar/compositeBar.ts | 6 +-- .../parts/compositebar/compositeBarActions.ts | 54 +++++++++++++++++-- .../activity/common/activityBarService.ts | 20 ------- 5 files changed, 57 insertions(+), 72 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 20c50332d10..2b03a25ffec 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -6,11 +6,9 @@ 'use strict'; import 'vs/css!./media/activityaction'; -import nls = require('vs/nls'); import DOM = require('vs/base/browser/dom'); import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; -import { IActivityBarService } from 'vs/workbench/services/activity/common/activityBarService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IActivity, IGlobalActivity } from 'vs/workbench/common/activity'; @@ -85,30 +83,6 @@ export class ToggleViewletAction extends Action { } } -export class ToggleViewletPinnedAction extends Action { - - constructor( - private activity: IActivity, - @IActivityBarService private activityBarService: IActivityBarService - ) { - super('activitybar.show.toggleViewletPinned', activity ? activity.name : nls.localize('toggle', "Toggle View Pinned")); - - this.checked = this.activity && this.activityBarService.isPinned(this.activity.id); - } - - public run(context: string): TPromise { - const id = this.activity ? this.activity.id : context; - - if (this.activityBarService.isPinned(id)) { - this.activityBarService.unpin(id); - } else { - this.activityBarService.pin(id); - } - - return TPromise.as(true); - } -} - export class GlobalActivityAction extends ActivityAction { constructor(activity: IGlobalActivity) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 72b3f6e451a..fea8ca6ef32 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -15,7 +15,7 @@ import { ActionsOrientation, ActionBar, Separator } from 'vs/base/browser/ui/act import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity'; import { Registry } from 'vs/platform/registry/common/platform'; import { Part } from 'vs/workbench/browser/part'; -import { ToggleViewletPinnedAction, GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, ToggleViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, ToggleViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IActivityBarService, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; import { IPartService, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService'; @@ -30,6 +30,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; +import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; export class ActivitybarPart extends Part implements IActivityBarService { @@ -66,7 +67,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { getCompositeSize: (compositeId: string) => ActivitybarPart.ACTIVITY_ACTION_HEIGHT, openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true), getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)), - getCompositePinnedAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletPinnedAction, this.viewletService.getViewlet(compositeId)), + getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.viewletService.getViewlet(compositeId), this.compositeBar), getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), hidePart: () => this.partService.setSideBarHidden(true) @@ -142,7 +143,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private showContextMenu(e: MouseEvent): void { const event = new StandardMouseEvent(e); - const actions: Action[] = this.viewletService.getViewlets().map(viewlet => this.instantiationService.createInstance(ToggleViewletPinnedAction, viewlet)); + const actions: Action[] = this.viewletService.getViewlets().map(viewlet => this.instantiationService.createInstance(ToggleCompositePinnedAction, viewlet, this.compositeBar)); actions.push(new Separator()); actions.push(this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"))); @@ -177,22 +178,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { return this.viewletService.getViewlets().map(v => v.id).filter(id => this.compositeBar.isPinned(id));; } - public unpin(viewletId: string): void { - this.compositeBar.unpin(viewletId); - } - - public isPinned(viewletId: string): boolean { - return this.compositeBar.isPinned(viewletId); - } - - public pin(viewletId: string, update = true): void { - this.compositeBar.pin(viewletId, update); - } - - public move(viewletId: string, toViewletId: string): void { - this.compositeBar.move(viewletId, toViewletId); - } - /** * Layout title, content and status area in the given dimension. */ diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 12c90a5638a..04db733600d 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -17,7 +17,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import Event, { Emitter } from 'vs/base/common/event'; -import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; import { TPromise } from 'vs/base/common/winjs.base'; export interface ICompositeBarOptions { @@ -34,7 +34,7 @@ export interface ICompositeBarOptions { hidePart: () => TPromise; } -export class CompositeBar { +export class CompositeBar implements ICompositeBar { private _onDidContextMenu: Emitter; @@ -312,7 +312,7 @@ export class CompositeBar { private toAction(compositeId: string): ActivityAction { const compositeActivityAction = this.options.getActivityAction(compositeId); const pinnedAction = this.options.getCompositePinnedAction(compositeId); - this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction); + this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this); this.compositeIdToActions[compositeId] = compositeActivityAction; return compositeActivityAction; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 184dd5ae36e..617c17f714d 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -15,7 +15,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { dispose } from 'vs/base/common/lifecycle'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; -import { IActivityBarService, TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activityBarService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; @@ -29,6 +29,28 @@ export interface ICompositeActivity { clazz: string; } +export interface ICompositeBar { + /** + * Unpins a viewlet from the activitybar. + */ + unpin(viewletId: string): void; + + /** + * Pin a viewlet inside the activity bar. + */ + pin(viewletId: string): void; + + /** + * Find out if a viewlet is pinned in the activity bar. + */ + isPinned(viewletId: string): boolean; + + /** + * Reorder viewlet ordering by moving a viewlet to the location of another viewlet. + */ + move(viewletId: string, toViewletId: string): void; +} + export class ActivityAction extends Action { private badge: IBadge; private _onDidChangeBadge = new Emitter(); @@ -342,8 +364,8 @@ export class CompositeActionItem extends ActivityActionItem { constructor( private compositeActivityAction: ActivityAction, private toggleCompositePinnedAction: Action, + private compositeBar: ICompositeBar, @IContextMenuService private contextMenuService: IContextMenuService, - @IActivityBarService private activityBarService: IActivityBarService, @IKeybindingService private keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService @@ -448,7 +470,7 @@ export class CompositeActionItem extends ActivityActionItem { this.updateFromDragging(container, false); CompositeActionItem.clearDraggedComposite(); - this.activityBarService.move(draggedCompositeId, this.activity.id); + this.compositeBar.move(draggedCompositeId, this.activity.id); } }); @@ -488,7 +510,7 @@ export class CompositeActionItem extends ActivityActionItem { actions.push(CompositeActionItem.manageExtensionAction); } - const isPinned = this.activityBarService.isPinned(this.activity.id); + const isPinned = this.compositeBar.isPinned(this.activity.id); if (isPinned) { this.toggleCompositePinnedAction.label = nls.localize('removeFromActivityBar', "Hide from Activity Bar"); this.toggleCompositePinnedAction.checked = false; @@ -540,3 +562,27 @@ export class CompositeActionItem extends ActivityActionItem { this.$label.destroy(); } } + +export class ToggleCompositePinnedAction extends Action { + + constructor( + private activity: IActivity, + private compositeBar: ICompositeBar + ) { + super('activitybar.show.toggleViewletPinned', activity ? activity.name : nls.localize('toggle', "Toggle View Pinned")); + + this.checked = this.activity && this.compositeBar.isPinned(this.activity.id); + } + + public run(context: string): TPromise { + const id = this.activity ? this.activity.id : context; + + if (this.compositeBar.isPinned(id)) { + this.compositeBar.unpin(id); + } else { + this.compositeBar.pin(id); + } + + return TPromise.as(true); + } +} diff --git a/src/vs/workbench/services/activity/common/activityBarService.ts b/src/vs/workbench/services/activity/common/activityBarService.ts index 35732c5c1c4..2d7d55ce74b 100644 --- a/src/vs/workbench/services/activity/common/activityBarService.ts +++ b/src/vs/workbench/services/activity/common/activityBarService.ts @@ -67,24 +67,4 @@ export interface IActivityBarService { * Show activity in the activitybar for the given viewlet or global action. */ showActivity(viewletOrActionId: string, badge: IBadge, clazz?: string): IDisposable; - - /** - * Unpins a viewlet from the activitybar. - */ - unpin(viewletId: string): void; - - /** - * Pin a viewlet inside the activity bar. - */ - pin(viewletId: string): void; - - /** - * Find out if a viewlet is pinned in the activity bar. - */ - isPinned(viewletId: string): boolean; - - /** - * Reorder viewlet ordering by moving a viewlet to the location of another viewlet. - */ - move(viewletId: string, toViewletId: string): void; } From 5b90c9f13ccb0ed97e5caf43ab5b120cf1e93c6c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 Oct 2017 16:25:22 +0200 Subject: [PATCH 173/394] electron 1.7.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2133570b711..417c30f2a2a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.18.0", - "electronVersion": "1.7.7", + "electronVersion": "1.7.9", "distro": "59a68f7780bb6571a1460ea00ca7b994126baeda", "author": { "name": "Microsoft Corporation" From bf8282b1e6ff643284f387f54077a5d92349431a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 16:31:33 +0200 Subject: [PATCH 174/394] Simplify TextModelWithDecorations --- src/vs/editor/common/controller/cursor.ts | 4 +- src/vs/editor/common/controller/oneCursor.ts | 4 +- src/vs/editor/common/editorCommon.ts | 2 +- .../editor/common/model/editableTextModel.ts | 14 +- .../common/model/textModelWithDecorations.ts | 259 +++++++----------- 5 files changed, 104 insertions(+), 179 deletions(-) diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 91ea1e17dcb..bbe2d1aa6ee 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -583,7 +583,7 @@ class CommandExecutor { const result = this._innerExecuteCommands(ctx, commands); for (let i = 0, len = ctx.trackedRanges.length; i < len; i++) { - ctx.model._deltaTrackedRange(ctx.trackedRanges[i], null, editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + ctx.model._setTrackedRange(ctx.trackedRanges[i], null, editorCommon.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } return result; @@ -773,7 +773,7 @@ class CommandExecutor { } const l = ctx.trackedRanges.length; - const id = ctx.model._deltaTrackedRange(null, selection, stickiness); + const id = ctx.model._setTrackedRange(null, selection, stickiness); ctx.trackedRanges[l] = id; ctx.trackedRangesDirection[l] = selection.getDirection(); return l.toString(); diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index f4be4b16a78..fc2690244fb 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -31,7 +31,7 @@ export class OneCursor { } public dispose(context: CursorContext): void { - this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, null, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, null, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } public asCursorState(): CursorState { @@ -101,6 +101,6 @@ export class OneCursor { this.modelState = modelState; this.viewState = viewState; - this._selTrackedRange = context.model._deltaTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 6b46304bbeb..cc577de02dd 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -1024,7 +1024,7 @@ export interface ITextModelWithDecorations { /** * @internal */ - _deltaTrackedRange(id: string, newRange: Range, newStickiness: TrackedRangeStickiness): string; + _setTrackedRange(id: string, newRange: Range, newStickiness: TrackedRangeStickiness): string; } /** diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index ca0508e2ad1..d71d8c9b2ab 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -276,10 +276,10 @@ export class EditableTextModel extends TextModelWithDecorations implements edito public applyEdits(rawOperations: editorCommon.IIdentifiedSingleEditOperation[]): editorCommon.IIdentifiedSingleEditOperation[] { try { this._eventEmitter.beginDeferredEmit(); - this._acquireMarkersTracker(); + this._acquireDecorationsTracker(); return this._applyEdits(rawOperations); } finally { - this._releaseMarkersTracker(); + this._releaseDecorationsTracker(); this._eventEmitter.endDeferredEmit(); } } @@ -661,7 +661,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito text: text }); - this._tree.acceptReplace(op.rangeOffset, op.rangeLength, text.length, op.forceMoveMarkers); + this._decorationsTree.acceptReplace(op.rangeOffset, op.rangeLength, text.length, op.forceMoveMarkers); // console.log('AFTER:'); // console.log('<<<\n' + this._lines.map(l => l.text).join('\n') + '\n>>>'); @@ -710,10 +710,10 @@ export class EditableTextModel extends TextModelWithDecorations implements edito public undo(): Selection[] { try { this._eventEmitter.beginDeferredEmit(); - this._acquireMarkersTracker(); + this._acquireDecorationsTracker(); return this._undo(); } finally { - this._releaseMarkersTracker(); + this._releaseDecorationsTracker(); this._eventEmitter.endDeferredEmit(); } } @@ -735,10 +735,10 @@ export class EditableTextModel extends TextModelWithDecorations implements edito public redo(): Selection[] { try { this._eventEmitter.beginDeferredEmit(); - this._acquireMarkersTracker(); + this._acquireDecorationsTracker(); return this._redo(); } finally { - this._releaseMarkersTracker(); + this._releaseDecorationsTracker(); this._eventEmitter.endDeferredEmit(); } } diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 40e9add2c52..fe9306fdfc2 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -23,33 +23,6 @@ export const ClassName = { EditorErrorDecoration: 'errorsquiggly' }; -class DecorationsTracker { - - public didAddDecorations: boolean; - public didRemoveDecorations: boolean; - public didChangeDecorations: boolean; - - constructor() { - this.didAddDecorations = false; - this.didRemoveDecorations = false; - this.didChangeDecorations = false; - } - - // --- Build decoration events - - public markDidAddDecorations(): void { - this.didAddDecorations = true; - } - - public markDidRemoveDecorations(): void { - this.didRemoveDecorations = true; - } - - public markDidChangeDecorations(): void { - this.didChangeDecorations = true; - } -} - let _INSTANCE_COUNT = 0; /** * Produces 'a'-'z', followed by 'A'-'Z'... followed by 'a'-'z', etc. @@ -75,34 +48,23 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi */ private readonly _instanceId: string; private _lastDecorationId: number; - - private _currentDecorationsTracker: DecorationsTracker; private _currentDecorationsTrackerCnt: number; - - private _currentMarkersTrackerCnt: number; - - protected _tree: IntervalTree; - private _treeDecorations: { [decorationId: string]: IntervalNode; }; + private _decorations: { [decorationId: string]: IntervalNode; }; + protected _decorationsTree: IntervalTree; constructor(rawTextSource: IRawTextSource, creationOptions: editorCommon.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier) { super(rawTextSource, creationOptions, languageIdentifier); this._instanceId = nextInstanceId(); this._lastDecorationId = 0; - - // Initialize decorations - this._currentDecorationsTracker = null; this._currentDecorationsTrackerCnt = 0; - - this._currentMarkersTrackerCnt = 0; - - this._tree = new IntervalTree(); - this._treeDecorations = Object.create(null); + this._decorations = Object.create(null); + this._decorationsTree = new IntervalTree(); } public dispose(): void { - this._tree = null; - this._treeDecorations = null; + this._decorations = null; + this._decorationsTree = null; super.dispose(); } @@ -111,80 +73,56 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi super._resetValue(newValue); // Destroy all my decorations - this._tree = new IntervalTree(); - this._treeDecorations = Object.create(null); + this._decorations = Object.create(null); + this._decorationsTree = new IntervalTree(); } _getTrackedRangesCount(): number { - return this._tree.count(); + return this._decorationsTree.count(); } // --- END TrackedRanges - private _acquireDecorationsTracker(): DecorationsTracker { - if (this._currentDecorationsTrackerCnt === 0) { - this._currentDecorationsTracker = new DecorationsTracker(); - } + protected _acquireDecorationsTracker(): void { this._currentDecorationsTrackerCnt++; - return this._currentDecorationsTracker; } - private _releaseDecorationsTracker(): void { + protected _releaseDecorationsTracker(): void { this._currentDecorationsTrackerCnt--; if (this._currentDecorationsTrackerCnt === 0) { - let decorationsTracker = this._currentDecorationsTracker; - this._currentDecorationsTracker = null; - this._handleTrackedDecorations(decorationsTracker); + this._emitModelDecorationsChangedEvent(); } } - private _handleTrackedDecorations(decorationsTracker: DecorationsTracker): void { - if ( - !decorationsTracker.didAddDecorations - && !decorationsTracker.didChangeDecorations - && !decorationsTracker.didRemoveDecorations - ) { - return; - } - - this.emitModelDecorationsChangedEvent(); - } - public changeDecorations(callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T { this._assertNotDisposed(); try { this._eventEmitter.beginDeferredEmit(); - let decorationsTracker = this._acquireDecorationsTracker(); - return this._changeDecorations(decorationsTracker, ownerId, callback); + this._acquireDecorationsTracker(); + return this._changeDecorations(ownerId, callback); } finally { this._releaseDecorationsTracker(); this._eventEmitter.endDeferredEmit(); } } - private _changeDecorations(decorationsTracker: DecorationsTracker, ownerId: number, callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T): T { + private _changeDecorations(ownerId: number, callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T): T { let changeAccessor: editorCommon.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: editorCommon.IModelDecorationOptions): string => { - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - return this._deltaDecorationsImpl2(ownerId, [], [{ range: range, options: options }])[0]; + return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0]; }, changeDecoration: (id: string, newRange: IRange): void => { - this._changeDecorationImpl2(decorationsTracker, id, newRange); + this._changeDecorationImpl(id, newRange); }, changeDecorationOptions: (id: string, options: editorCommon.IModelDecorationOptions) => { - this._changeDecorationOptionsImpl2(decorationsTracker, id, _normalizeOptions(options)); + this._changeDecorationOptionsImpl(id, _normalizeOptions(options)); }, removeDecoration: (id: string): void => { - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - this._deltaDecorationsImpl2(ownerId, [id], []); + this._deltaDecorationsImpl(ownerId, [id], []); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { - decorationsTracker.markDidAddDecorations(); - decorationsTracker.markDidRemoveDecorations(); - return this._deltaDecorationsImpl2(ownerId, oldDecorations, newDecorations); + return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations); } }; let result: T = null; @@ -206,17 +144,23 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi if (!oldDecorations) { oldDecorations = []; } - return this.changeDecorations((changeAccessor) => { - return changeAccessor.deltaDecorations(oldDecorations, newDecorations); - }, ownerId); + + try { + this._eventEmitter.beginDeferredEmit(); + this._acquireDecorationsTracker(); + return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations); + } finally { + this._releaseDecorationsTracker(); + this._eventEmitter.endDeferredEmit(); + } } _getTrackedRange(id: string): Range { return this.getDecorationRange(id); } - _deltaTrackedRange(id: string, newRange: Range, newStickiness: editorCommon.TrackedRangeStickiness): string { - const node = (id ? this._treeDecorations[id] : null); + _setTrackedRange(id: string, newRange: Range, newStickiness: editorCommon.TrackedRangeStickiness): string { + const node = (id ? this._decorations[id] : null); if (!node) { if (!newRange) { @@ -224,13 +168,13 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi return null; } // node doesn't exist, the request is to set => add the tracked range - return this._deltaDecorationsImpl2(0, [], [{ range: newRange, options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0]; + return this._deltaDecorationsImpl(0, [], [{ range: newRange, options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0]; } if (!newRange) { // node exists, the request is to delete => delete node - this._tree.delete(node); - delete this._treeDecorations[node.id]; + this._decorationsTree.delete(node); + delete this._decorations[node.id]; return null; } @@ -239,51 +183,39 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._ensureLineStarts(); const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; - this._tree.delete(node); + this._decorationsTree.delete(node); node.reset(this.getVersionId(), startOffset, endOffset, range); node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]); - this._tree.insert(node); + this._decorationsTree.insert(node); return node.id; } public removeAllDecorationsWithOwnerId(ownerId: number): void { - const nodes = this._tree.collectNodesFromOwner(ownerId); + const nodes = this._decorationsTree.collectNodesFromOwner(ownerId); for (let i = 0, len = nodes.length; i < len; i++) { const node = nodes[i]; - this._tree.delete(node); - delete this._treeDecorations[node.id]; + this._decorationsTree.delete(node); + delete this._decorations[node.id]; } } public getDecorationOptions(decorationId: string): editorCommon.IModelDecorationOptions { - const node = this._treeDecorations[decorationId]; + const node = this._decorations[decorationId]; if (!node) { return null; } return node.options; } - private _getRangeAt(start: number, end: number): Range { - const startResult = this._lineStarts.getIndexOf(start); - const startLineLength = this._lines[startResult.index].text.length; - const startColumn = Math.min(startResult.remainder + 1, startLineLength + 1); - - const endResult = this._lineStarts.getIndexOf(end); - const endLineLength = this._lines[endResult.index].text.length; - const endColumn = Math.min(endResult.remainder + 1, endLineLength + 1); - - return new Range(startResult.index + 1, startColumn, endResult.index + 1, endColumn); - } - public getDecorationRange(decorationId: string): Range { - const node = this._treeDecorations[decorationId]; + const node = this._decorations[decorationId]; if (!node) { return null; } const versionId = this.getVersionId(); if (node.cachedVersionId !== versionId) { - this._tree.resolveNode(node, versionId); + this._decorationsTree.resolveNode(node, versionId); } if (node.range === null) { this._ensureLineStarts(); @@ -300,30 +232,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi return this.getLinesDecorations(lineNumber, lineNumber, ownerId, filterOutValidation); } - private _ensureNodesHaveRanges(nodes: IntervalNode[]): IntervalNode[] { - this._ensureLineStarts(); - - for (let i = 0, len = nodes.length; i < len; i++) { - const node = nodes[i]; - if (node.range === null) { - node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); - } - } - return nodes; - } - - private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): IntervalNode[] { - this._ensureLineStarts(); - - const startOffset = this._lineStarts.getAccumulatedValue(filterRange.startLineNumber - 2) + filterRange.startColumn - 1; - const endOffset = this._lineStarts.getAccumulatedValue(filterRange.endLineNumber - 2) + filterRange.endColumn - 1; - - const versionId = this.getVersionId(); - const result = this._tree.intervalSearch(startOffset, endOffset, filterOwnerId, filterOutValidation, versionId); - - return this._ensureNodesHaveRanges(result); - } - public getLinesDecorations(_startLineNumber: number, _endLineNumber: number, ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { let lineCount = this.getLineCount(); let startLineNumber = Math.min(lineCount, Math.max(1, _startLineNumber)); @@ -339,40 +247,61 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi public getOverviewRulerDecorations(ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { const versionId = this.getVersionId(); - const result = this._tree.search(ownerId, filterOutValidation, true, versionId); + const result = this._decorationsTree.search(ownerId, filterOutValidation, true, versionId); return this._ensureNodesHaveRanges(result); } public getAllDecorations(ownerId: number = 0, filterOutValidation: boolean = false): editorCommon.IModelDecoration[] { const versionId = this.getVersionId(); - const result = this._tree.search(ownerId, filterOutValidation, false, versionId); + const result = this._decorationsTree.search(ownerId, filterOutValidation, false, versionId); return this._ensureNodesHaveRanges(result); } - protected _acquireMarkersTracker(): void { - this._currentMarkersTrackerCnt++; - } - - protected _releaseMarkersTracker(): void { - this._currentMarkersTrackerCnt--; - if (this._currentMarkersTrackerCnt === 0) { - this.emitModelDecorationsChangedEvent(); - } - } - - private emitModelDecorationsChangedEvent(): void { + private _emitModelDecorationsChangedEvent(): void { if (!this._isDisposing) { let e: textModelEvents.IModelDecorationsChangedEvent = {}; this._eventEmitter.emit(textModelEvents.TextModelEventType.ModelDecorationsChanged, e); } } - private _externalDecorationId(internalId: number): string { - return `${this._instanceId};${internalId}`; + private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): IntervalNode[] { + this._ensureLineStarts(); + + const startOffset = this._lineStarts.getAccumulatedValue(filterRange.startLineNumber - 2) + filterRange.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(filterRange.endLineNumber - 2) + filterRange.endColumn - 1; + + const versionId = this.getVersionId(); + const result = this._decorationsTree.intervalSearch(startOffset, endOffset, filterOwnerId, filterOutValidation, versionId); + + return this._ensureNodesHaveRanges(result); } - private _changeDecorationImpl2(decorationsTracker: DecorationsTracker, decorationId: string, _range: IRange): void { - const node = this._treeDecorations[decorationId]; + private _ensureNodesHaveRanges(nodes: IntervalNode[]): IntervalNode[] { + this._ensureLineStarts(); + + for (let i = 0, len = nodes.length; i < len; i++) { + const node = nodes[i]; + if (node.range === null) { + node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); + } + } + return nodes; + } + + private _getRangeAt(start: number, end: number): Range { + const startResult = this._lineStarts.getIndexOf(start); + const startLineLength = this._lines[startResult.index].text.length; + const startColumn = Math.min(startResult.remainder + 1, startLineLength + 1); + + const endResult = this._lineStarts.getIndexOf(end); + const endLineLength = this._lines[endResult.index].text.length; + const endColumn = Math.min(endResult.remainder + 1, endLineLength + 1); + + return new Range(startResult.index + 1, startColumn, endResult.index + 1, endColumn); + } + + private _changeDecorationImpl(decorationId: string, _range: IRange): void { + const node = this._decorations[decorationId]; if (!node) { return; } @@ -381,25 +310,21 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; - this._tree.delete(node); + this._decorationsTree.delete(node); node.reset(this.getVersionId(), startOffset, endOffset, range); - this._tree.insert(node); - - decorationsTracker.markDidChangeDecorations(); + this._decorationsTree.insert(node); } - private _changeDecorationOptionsImpl2(decorationsTracker: DecorationsTracker, decorationId: string, options: ModelDecorationOptions): void { - const node = this._treeDecorations[decorationId]; + private _changeDecorationOptionsImpl(decorationId: string, options: ModelDecorationOptions): void { + const node = this._decorations[decorationId]; if (!node) { return; } node.setOptions(options); - - decorationsTracker.markDidChangeDecorations(); } - private _deltaDecorationsImpl2(ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { + private _deltaDecorationsImpl(ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { this._ensureLineStarts(); const versionId = this.getVersionId(); @@ -417,12 +342,12 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi if (oldDecorationIndex < oldDecorationsLen) { // (1) get ourselves an old node do { - node = this._treeDecorations[oldDecorationsIds[oldDecorationIndex++]]; + node = this._decorations[oldDecorationsIds[oldDecorationIndex++]]; } while (!node && oldDecorationIndex < oldDecorationsLen); // (2) remove the node from the tree (if it exists) if (node) { - this._tree.delete(node); + this._decorationsTree.delete(node); } } @@ -430,9 +355,9 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi // (3) create a new node if necessary if (!node) { const internalDecorationId = (++this._lastDecorationId); - const decorationId = this._externalDecorationId(internalDecorationId); + const decorationId = `${this._instanceId};${internalDecorationId}`; node = new IntervalNode(decorationId, 0, 0); - this._treeDecorations[decorationId] = node; + this._decorations[decorationId] = node; } // (4) initialize node @@ -446,14 +371,14 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi node.reset(versionId, startOffset, endOffset, range); node.setOptions(options); - this._tree.insert(node); + this._decorationsTree.insert(node); result[newDecorationIndex] = node.id; newDecorationIndex++; } else { if (node) { - delete this._treeDecorations[node.id]; + delete this._decorations[node.id]; } } } From 68797abd3146c005e90d3aa111d9cec4cb87a237 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 17 Oct 2017 16:44:42 +0200 Subject: [PATCH 175/394] fix activity bar context menu --- .../browser/parts/activitybar/activitybarPart.ts | 2 +- .../browser/parts/compositebar/compositeBar.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index fea8ca6ef32..49b1cb6a684 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -113,7 +113,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { const $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action - this.compositeBar.create($('.viewlets').appendTo($result).getHTMLElement()); + this.compositeBar.create($result.getHTMLElement()); // Top Actionbar with action items for each viewlet action this.createGlobalActivityActionBar($('.global-activity').appendTo($result).getHTMLElement()); diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 04db733600d..74ea9884843 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -152,9 +152,9 @@ export class CompositeBar implements ICompositeBar { } } - public create(container: HTMLElement): void { - dom.addClass(container, 'composite-bar'); - this.compositeSwitcherBar = new ActionBar(container, { + public create(parent: HTMLElement): void { + const actionBarDiv = parent.appendChild(dom.$('composite-bar')); + this.compositeSwitcherBar = new ActionBar(actionBarDiv, { actionItemProvider: (action: Action) => action instanceof CompositeOverflowActivityAction ? this.compositeOverflowActionItem : this.compositeIdToActionItems[action.id], orientation: this.options.orientation, ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher"), @@ -163,13 +163,13 @@ export class CompositeBar implements ICompositeBar { this.updateCompositeSwitcher(); // Contextmenu for composites - this.toDispose.push(dom.addDisposableListener(container, dom.EventType.CONTEXT_MENU, (e: MouseEvent) => { + this.toDispose.push(dom.addDisposableListener(parent, dom.EventType.CONTEXT_MENU, (e: MouseEvent) => { dom.EventHelper.stop(e, true); this._onDidContextMenu.fire(e); })); // Allow to drop at the end to move composites to the end - this.toDispose.push(dom.addDisposableListener(container, dom.EventType.DROP, (e: DragEvent) => { + this.toDispose.push(dom.addDisposableListener(parent, dom.EventType.DROP, (e: DragEvent) => { const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); if (draggedCompositeId) { dom.EventHelper.stop(e, true); From 1262a9824076a3741efa34d821443623bf5a5f53 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 16:52:15 +0200 Subject: [PATCH 176/394] Simplify usage of lineStarts in model --- .../editor/common/model/editableTextModel.ts | 37 ++++--------------- src/vs/editor/common/model/textModel.ts | 32 +++++++--------- .../common/model/textModelWithDecorations.ts | 8 ---- 3 files changed, 20 insertions(+), 57 deletions(-) diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index d71d8c9b2ab..db5b3639da5 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -289,8 +289,6 @@ export class EditableTextModel extends TextModelWithDecorations implements edito return []; } - this._ensureLineStarts(); - let mightContainRTL = this._mightContainRTL; let mightContainNonBasicASCII = this._mightContainNonBasicASCII; let canReduceOperations = true; @@ -508,10 +506,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._invalidateLine(currentLineNumber - 1); this._lines[currentLineNumber - 1].applyEdits(lineEditsQueue.slice(currentLineNumberStart, i), tabSize); - if (this._lineStarts) { - // update prefix sum - this._lineStarts.changeValue(currentLineNumber - 1, this._lines[currentLineNumber - 1].text.length + this._EOL.length); - } + this._lineStarts.changeValue(currentLineNumber - 1, this._lines[currentLineNumber - 1].text.length + this._EOL.length); rawContentChanges.push( new textModelEvents.ModelRawLineChanged(currentLineNumber, this._lines[currentLineNumber - 1].text) ); @@ -522,10 +517,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._invalidateLine(currentLineNumber - 1); this._lines[currentLineNumber - 1].applyEdits(lineEditsQueue.slice(currentLineNumberStart, lineEditsQueue.length), tabSize); - if (this._lineStarts) { - // update prefix sum - this._lineStarts.changeValue(currentLineNumber - 1, this._lines[currentLineNumber - 1].text.length + this._EOL.length); - } + this._lineStarts.changeValue(currentLineNumber - 1, this._lines[currentLineNumber - 1].text.length + this._EOL.length); rawContentChanges.push( new textModelEvents.ModelRawLineChanged(currentLineNumber, this._lines[currentLineNumber - 1].text) ); @@ -583,17 +575,11 @@ export class EditableTextModel extends TextModelWithDecorations implements edito const spliceCnt = endLineNumber - spliceStartLineNumber; this._lines.splice(spliceStartLineNumber, spliceCnt); - if (this._lineStarts) { - // update prefix sum - this._lineStarts.removeValues(spliceStartLineNumber, spliceCnt); - } + this._lineStarts.removeValues(spliceStartLineNumber, spliceCnt); // Reconstruct first line this._lines[spliceStartLineNumber - 1].append(endLineRemains, tabSize); - if (this._lineStarts) { - // update prefix sum - this._lineStarts.changeValue(spliceStartLineNumber - 1, this._lines[spliceStartLineNumber - 1].text.length + this._EOL.length); - } + this._lineStarts.changeValue(spliceStartLineNumber - 1, this._lines[spliceStartLineNumber - 1].text.length + this._EOL.length); rawContentChanges.push( new textModelEvents.ModelRawLineChanged(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1].text) @@ -618,10 +604,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito // Split last line let leftoverLine = this._lines[spliceLineNumber - 1].split(spliceColumn, tabSize); - if (this._lineStarts) { - // update prefix sum - this._lineStarts.changeValue(spliceLineNumber - 1, this._lines[spliceLineNumber - 1].text.length + this._EOL.length); - } + this._lineStarts.changeValue(spliceLineNumber - 1, this._lines[spliceLineNumber - 1].text.length + this._EOL.length); rawContentChanges.push( new textModelEvents.ModelRawLineChanged(spliceLineNumber, this._lines[spliceLineNumber - 1].text) ); @@ -638,17 +621,11 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } this._lines = arrays.arrayInsert(this._lines, startLineNumber + editingLinesCnt, newLines); newLinesContent[newLinesContent.length - 1] += leftoverLine.text; - if (this._lineStarts) { - // update prefix sum - this._lineStarts.insertValues(startLineNumber + editingLinesCnt, newLinesLengths); - } + this._lineStarts.insertValues(startLineNumber + editingLinesCnt, newLinesLengths); // Last line this._lines[startLineNumber + insertingLinesCnt - 1].append(leftoverLine, tabSize); - if (this._lineStarts) { - // update prefix sum - this._lineStarts.changeValue(startLineNumber + insertingLinesCnt - 1, this._lines[startLineNumber + insertingLinesCnt - 1].text.length + this._EOL.length); - } + this._lineStarts.changeValue(startLineNumber + insertingLinesCnt - 1, this._lines[startLineNumber + insertingLinesCnt - 1].text.length + this._EOL.length); rawContentChanges.push( new textModelEvents.ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLinesContent.join('\n')) ); diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index e932ce350c3..b5eb35f4e52 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -19,8 +19,6 @@ import { TextSource, ITextSource, IRawTextSource, RawTextSource } from 'vs/edito import { IDisposable } from 'vs/base/common/lifecycle'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; -const USE_MIMINAL_MODEL_LINE = true; - const LIMIT_FIND_COUNT = 999; export const LONG_LINE_BOUNDARY = 10000; @@ -124,7 +122,7 @@ export class TextModel implements editorCommon.ITextModel { } protected _createModelLine(text: string, tabSize: number): IModelLine { - if (USE_MIMINAL_MODEL_LINE && this._isTooLargeForTokenization) { + if (this._isTooLargeForTokenization) { return new MinimalModelLine(text, tabSize); } return new ModelLine(text, tabSize); @@ -262,22 +260,9 @@ export class TextModel implements editorCommon.ITextModel { return this._alternativeVersionId; } - protected _ensureLineStarts(): void { - if (!this._lineStarts) { - const eolLength = this._EOL.length; - const linesLength = this._lines.length; - const lineStartValues = new Uint32Array(linesLength); - for (let i = 0; i < linesLength; i++) { - lineStartValues[i] = this._lines[i].text.length + eolLength; - } - this._lineStarts = new PrefixSumComputer(lineStartValues); - } - } - public getOffsetAt(rawPosition: IPosition): number { this._assertNotDisposed(); let position = this._validatePosition(rawPosition.lineNumber, rawPosition.column, false); - this._ensureLineStarts(); return this._lineStarts.getAccumulatedValue(position.lineNumber - 2) + position.column - 1; } @@ -286,7 +271,6 @@ export class TextModel implements editorCommon.ITextModel { offset = Math.floor(offset); offset = Math.max(0, offset); - this._ensureLineStarts(); let out = this._lineStarts.getIndexOf(offset); let lineLength = this._lines[out.index].text.length; @@ -541,7 +525,7 @@ export class TextModel implements editorCommon.ITextModel { const endColumn = this.getLineMaxColumn(endLineNumber); this._EOL = newEOL; - this._lineStarts = null; + this._constructLineStarts(); this._increaseVersionId(); this._emitModelRawContentChangedEvent( @@ -796,7 +780,17 @@ export class TextModel implements editorCommon.ITextModel { this._mightContainNonBasicASCII = !textSource.isBasicASCII; this._EOL = textSource.EOL; this._lines = modelLines; - this._lineStarts = null; + this._constructLineStarts(); + } + + private _constructLineStarts(): void { + const eolLength = this._EOL.length; + const linesLength = this._lines.length; + const lineStartValues = new Uint32Array(linesLength); + for (let i = 0; i < linesLength; i++) { + lineStartValues[i] = this._lines[i].text.length + eolLength; + } + this._lineStarts = new PrefixSumComputer(lineStartValues); } private _getEndOfLine(eol: editorCommon.EndOfLinePreference): string { diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index fe9306fdfc2..6a2d9cffcf1 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -180,7 +180,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi // node exists, the request is to set => change the tracked range and its options const range = this._validateRangeRelaxedNoAllocations(newRange); - this._ensureLineStarts(); const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; this._decorationsTree.delete(node); @@ -218,7 +217,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._decorationsTree.resolveNode(node, versionId); } if (node.range === null) { - this._ensureLineStarts(); node.range = this._getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd); } return node.range; @@ -265,8 +263,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi } private _getDecorationsInRange(filterRange: Range, filterOwnerId: number, filterOutValidation: boolean): IntervalNode[] { - this._ensureLineStarts(); - const startOffset = this._lineStarts.getAccumulatedValue(filterRange.startLineNumber - 2) + filterRange.startColumn - 1; const endOffset = this._lineStarts.getAccumulatedValue(filterRange.endLineNumber - 2) + filterRange.endColumn - 1; @@ -277,8 +273,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi } private _ensureNodesHaveRanges(nodes: IntervalNode[]): IntervalNode[] { - this._ensureLineStarts(); - for (let i = 0, len = nodes.length; i < len; i++) { const node = nodes[i]; if (node.range === null) { @@ -305,7 +299,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi if (!node) { return; } - this._ensureLineStarts(); const range = this._validateRangeRelaxedNoAllocations(_range); const startOffset = this._lineStarts.getAccumulatedValue(range.startLineNumber - 2) + range.startColumn - 1; const endOffset = this._lineStarts.getAccumulatedValue(range.endLineNumber - 2) + range.endColumn - 1; @@ -325,7 +318,6 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi } private _deltaDecorationsImpl(ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { - this._ensureLineStarts(); const versionId = this.getVersionId(); const oldDecorationsLen = oldDecorationsIds.length; From d5880b1a5948b3bffd40f932dfb63ec8a4be58f9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 Oct 2017 17:19:24 +0200 Subject: [PATCH 177/394] deco - decorate ignored files --- extensions/git/src/decorationProvider.ts | 56 ++++++++++++++++++- extensions/git/src/repository.ts | 36 ++++++++++++ .../decorations/browser/decorationsService.ts | 7 ++- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index ed4bad8aef0..7adbb51003d 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -8,6 +8,57 @@ import { window, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider } from 'vscode'; import { Repository, GitResourceGroup } from './repository'; import { Model } from './model'; +import { debounce } from './decorators'; + +class GitIgnoreDecorationProvider implements DecorationProvider { + + private readonly _onDidChangeDecorations = new EventEmitter(); + readonly onDidChangeDecorations: Event = this._onDidChangeDecorations.event; + + private checkIgnoreQueue = new Map void, reject: (err: any) => void }>(); + private disposables: Disposable[] = []; + + constructor(private repository: Repository) { + this.disposables.push( + window.registerDecorationProvider(this, '.gitignore') + //todo@joh -> events when the ignore status actually changes, not when the file changes + ); + } + + dispose(): void { + this.disposables.forEach(d => d.dispose()); + this.checkIgnoreQueue.clear(); + } + + provideDecoration(uri: Uri): Promise { + return new Promise((resolve, reject) => { + this.checkIgnoreQueue.set(uri.fsPath, { resolve, reject }); + this.checkIgnoreSoon(); + }).then(ignored => { + if (ignored) { + return { + priority: 3, + opacity: 0.75 + }; + } + }); + } + + @debounce(500) + private checkIgnoreSoon(): void { + const queue = new Map(this.checkIgnoreQueue.entries()); + this.checkIgnoreQueue.clear(); + this.repository.checkIgnore([...queue.keys()]).then(ignoreSet => { + for (const [key, value] of queue.entries()) { + value.resolve(ignoreSet.has(key)); + } + }, err => { + for (const [, value] of queue.entries()) { + value.reject(err); + } + }); + } +} class GitDecorationProvider implements DecorationProvider { @@ -65,7 +116,7 @@ class GitDecorationProvider implements DecorationProvider { export class GitDecorations { private disposables: Disposable[] = []; - private providers = new Map(); + private providers = new Map(); constructor(private model: Model) { this.disposables.push( @@ -77,7 +128,8 @@ export class GitDecorations { private onDidOpenRepository(repository: Repository): void { const provider = new GitDecorationProvider(repository); - this.providers.set(repository, provider); + const ignoreProvider = new GitIgnoreDecorationProvider(repository); + this.providers.set(repository, Disposable.from(provider, ignoreProvider)); } private onDidCloseRepository(repository: Repository): void { diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 319edc3a07e..74cd6c48bfd 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -646,6 +646,42 @@ export class Repository implements Disposable { }); } + checkIgnore(filePaths: string[]): Promise> { + return this.run(Operation.Ignore, () => { + return new Promise>((resolve, reject) => { + + const child = this.repository.stream(['check-ignore', ...filePaths]); + + const onExit = exitCode => { + if (exitCode === 1) { + // nothing ignored + resolve(new Set()); + } else if (exitCode === 0) { + // each line is something ignored + resolve(new Set(data.split('\n'))); + } else { + reject(); + } + }; + + let data = ''; + const onStdoutData = (raw: string) => { + data += raw; + }; + + child.stdout.setEncoding('utf8'); + child.stdout.on('data', onStdoutData); + + // const stderrData: string[] = []; + // child.stderr.setEncoding('utf8'); + // child.stderr.on('data', raw => stderrData.push(raw as string)); + + child.on('error', reject); + child.on('exit', onExit); + }); + }); + } + private async run(operation: Operation, runOperation: () => Promise = () => Promise.resolve(null)): Promise { if (this.state !== RepositoryState.Idle) { throw new Error('Repository not initialized'); diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index ddbf12c6133..a6320b0fe65 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -249,15 +249,16 @@ class DecorationProviderWrapper { return; } - if (item === undefined && !includeChildren) { - // unknown, a leaf node -> trigger request + if (item === undefined) { + // unknown -> trigger request item = this._fetchData(uri); } if (item) { - // leaf node + // found something callback(item, false); } + if (includeChildren) { // (resolved) children const childTree = this.data.findSuperstr(key); From 12f9753dc4b516595f740e9ed170af8be3e772b7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 Oct 2017 17:42:39 +0200 Subject: [PATCH 178/394] force a change --- src/typings/electron.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index 75bf1761b46..e9530251310 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Electron 1.7.7 +// Type definitions for Electron 1.7.9 // Project: http://electron.atom.io/ // Definitions by: The Electron Team // Definitions: https://github.com/electron/electron-typescript-definitions From 4616b4ccde2e77d6071d9b39d47915969d99191b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 17:56:03 +0200 Subject: [PATCH 179/394] Small tweaks --- .../contrib/find/common/findDecorations.ts | 39 +++++++++++-------- .../editor/contrib/find/common/findModel.ts | 2 +- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findDecorations.ts b/src/vs/editor/contrib/find/common/findDecorations.ts index 202e32602fa..4a59a7b7e56 100644 --- a/src/vs/editor/contrib/find/common/findDecorations.ts +++ b/src/vs/editor/contrib/find/common/findDecorations.ts @@ -68,11 +68,21 @@ export class FindDecorations implements IDisposable { this.setCurrentFindMatch(null); } + private _getDecorationIndex(decorationId: string): number { + const index = this._decorations.indexOf(decorationId); + if (index >= 0) { + return index + 1; + } + return 1; + } + public getCurrentMatchesPosition(desiredRange: Range): number { - for (let i = 0, len = this._decorations.length; i < len; i++) { - let range = this._editor.getModel().getDecorationRange(this._decorations[i]); - if (desiredRange.equalsRange(range)) { - return (i + 1); + let candidates = this._editor.getModel().getDecorationsInRange(desiredRange); + for (let i = 0, len = candidates.length; i < len; i++) { + const candidate = candidates[i]; + const candidateOpts = candidate.options; + if (candidateOpts === FindDecorations._FIND_MATCH_DECORATION || candidateOpts === FindDecorations._CURRENT_FIND_MATCH_DECORATION) { + return this._getDecorationIndex(candidate.id); } } return 1; @@ -95,12 +105,12 @@ export class FindDecorations implements IDisposable { if (this._highlightedDecorationId !== null || newCurrentDecorationId !== null) { this._editor.changeDecorations((changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => { if (this._highlightedDecorationId !== null) { - changeAccessor.changeDecorationOptions(this._highlightedDecorationId, FindDecorations.createFindMatchDecorationOptions(false)); + changeAccessor.changeDecorationOptions(this._highlightedDecorationId, FindDecorations._FIND_MATCH_DECORATION); this._highlightedDecorationId = null; } if (newCurrentDecorationId !== null) { this._highlightedDecorationId = newCurrentDecorationId; - changeAccessor.changeDecorationOptions(this._highlightedDecorationId, FindDecorations.createFindMatchDecorationOptions(true)); + changeAccessor.changeDecorationOptions(this._highlightedDecorationId, FindDecorations._CURRENT_FIND_MATCH_DECORATION); } if (this._rangeHighlightDecorationId !== null) { changeAccessor.removeDecoration(this._rangeHighlightDecorationId); @@ -121,13 +131,14 @@ export class FindDecorations implements IDisposable { return matchPosition; } - public set(matches: Range[], findScope: Range): void { - let newDecorations: editorCommon.IModelDeltaDecoration[] = matches.map((match) => { - return { - range: match, - options: FindDecorations.createFindMatchDecorationOptions(false) + public set(findMatches: editorCommon.FindMatch[], findScope: Range): void { + let newDecorations: editorCommon.IModelDeltaDecoration[] = new Array(findMatches.length); + for (let i = 0, len = findMatches.length; i < len; i++) { + newDecorations[i] = { + range: findMatches[i].range, + options: FindDecorations._FIND_MATCH_DECORATION }; - }); + } if (findScope) { newDecorations.unshift({ range: findScope, @@ -158,10 +169,6 @@ export class FindDecorations implements IDisposable { return result; } - private static createFindMatchDecorationOptions(isCurrent: boolean): ModelDecorationOptions { - return (isCurrent ? this._CURRENT_FIND_MATCH_DECORATION : this._FIND_MATCH_DECORATION); - } - private static _CURRENT_FIND_MATCH_DECORATION = ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, className: 'currentFindMatch', diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index be3705b47f7..1816df33d59 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -171,7 +171,7 @@ export class FindModelBoundToEditorModel { } let findMatches = this._findMatches(findScope, false, MATCHES_LIMIT); - this._decorations.set(findMatches.map(match => match.range), findScope); + this._decorations.set(findMatches, findScope); this._state.changeMatchInfo( this._decorations.getCurrentMatchesPosition(this._editor.getSelection()), From 65743658c463393bff3b648c4763a544775d44eb Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 Oct 2017 17:57:02 +0200 Subject: [PATCH 180/394] Emit a decoration change event only when methods are called on the change accessor --- .../editor/common/model/editableTextModel.ts | 2 +- .../common/model/textModelWithDecorations.ts | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index db5b3639da5..77c0bd9f8a8 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -638,7 +638,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito text: text }); - this._decorationsTree.acceptReplace(op.rangeOffset, op.rangeLength, text.length, op.forceMoveMarkers); + this._adjustDecorationsForEdit(op.rangeOffset, op.rangeLength, text.length, op.forceMoveMarkers); // console.log('AFTER:'); // console.log('<<<\n' + this._lines.map(l => l.text).join('\n') + '\n>>>'); diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 6a2d9cffcf1..5a500265f8d 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -49,8 +49,9 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi private readonly _instanceId: string; private _lastDecorationId: number; private _currentDecorationsTrackerCnt: number; + private _currentDecorationsTrackerDidChange: boolean; private _decorations: { [decorationId: string]: IntervalNode; }; - protected _decorationsTree: IntervalTree; + private _decorationsTree: IntervalTree; constructor(rawTextSource: IRawTextSource, creationOptions: editorCommon.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier) { super(rawTextSource, creationOptions, languageIdentifier); @@ -58,6 +59,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._instanceId = nextInstanceId(); this._lastDecorationId = 0; this._currentDecorationsTrackerCnt = 0; + this._currentDecorationsTrackerDidChange = false; this._decorations = Object.create(null); this._decorationsTree = new IntervalTree(); } @@ -84,16 +86,26 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi // --- END TrackedRanges protected _acquireDecorationsTracker(): void { + if (this._currentDecorationsTrackerCnt === 0) { + this._currentDecorationsTrackerDidChange = false; + } this._currentDecorationsTrackerCnt++; } protected _releaseDecorationsTracker(): void { this._currentDecorationsTrackerCnt--; if (this._currentDecorationsTrackerCnt === 0) { - this._emitModelDecorationsChangedEvent(); + if (this._currentDecorationsTrackerDidChange) { + this._emitModelDecorationsChangedEvent(); + } } } + protected _adjustDecorationsForEdit(offset: number, length: number, textLength: number, forceMoveMarkers: boolean): void { + this._currentDecorationsTrackerDidChange = true; + this._decorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers); + } + public changeDecorations(callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T { this._assertNotDisposed(); @@ -110,18 +122,23 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi private _changeDecorations(ownerId: number, callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T): T { let changeAccessor: editorCommon.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: editorCommon.IModelDecorationOptions): string => { + this._currentDecorationsTrackerDidChange = true; return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0]; }, changeDecoration: (id: string, newRange: IRange): void => { + this._currentDecorationsTrackerDidChange = true; this._changeDecorationImpl(id, newRange); }, changeDecorationOptions: (id: string, options: editorCommon.IModelDecorationOptions) => { + this._currentDecorationsTrackerDidChange = true; this._changeDecorationOptionsImpl(id, _normalizeOptions(options)); }, removeDecoration: (id: string): void => { + this._currentDecorationsTrackerDidChange = true; this._deltaDecorationsImpl(ownerId, [id], []); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { + this._currentDecorationsTrackerDidChange = true; return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations); } }; @@ -148,6 +165,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi try { this._eventEmitter.beginDeferredEmit(); this._acquireDecorationsTracker(); + this._currentDecorationsTrackerDidChange = true; return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations); } finally { this._releaseDecorationsTracker(); From 9dc080f80b943a1cd3df6432c6b16ad885bfa7aa Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 17 Oct 2017 11:08:08 -0700 Subject: [PATCH 181/394] Change "Remove" to "Dismiss" - fix #36440 --- src/vs/workbench/parts/search/browser/searchActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index 8c65a7a44b1..e50b636779e 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -507,7 +507,7 @@ export abstract class AbstractSearchAndReplaceAction extends Action { export class RemoveAction extends AbstractSearchAndReplaceAction { constructor(private viewer: ITree, private element: RenderableMatch) { - super('remove', nls.localize('RemoveAction.label', "Remove"), 'action-remove'); + super('remove', nls.localize('RemoveAction.label', "Dismiss"), 'action-remove'); } public run(): TPromise { From f6ab9915c7c7a27a456cb386aa355b8d835db4b7 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 17 Oct 2017 12:50:12 -0700 Subject: [PATCH 182/394] Configure for 1.17.2 --- .github/new_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/new_release.yml b/.github/new_release.yml index 1a0465c011d..902078aa79c 100644 --- a/.github/new_release.yml +++ b/.github/new_release.yml @@ -1,5 +1,5 @@ { newReleaseLabel: 'new release', - newReleases: ['1.17.1'], + newReleases: ['1.17.2'], perform: true } \ No newline at end of file From 4d09bef3c510bb23800de1b6d2ee5ad4e42e4a0c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 17 Oct 2017 12:53:09 -0700 Subject: [PATCH 183/394] Update coffeescript grammar Fixes #36422 --- .../syntaxes/coffeescript.tmLanguage.json | 154 ++++++++++++++---- 1 file changed, 118 insertions(+), 36 deletions(-) diff --git a/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json b/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json index 86441c11dd8..68e1bc4e83b 100644 --- a/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json +++ b/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json @@ -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/atom/language-coffee-script/commit/da81e3f537ccbbb70e542fa5af79583eb58ec50b", + "version": "https://github.com/atom/language-coffee-script/commit/8873cbc4e2f3b790603cbe7102d60f41fc82f726", "scopeName": "source.coffee", "name": "CoffeeScript", "fileTypes": [ @@ -535,13 +535,13 @@ "arguments": { "patterns": [ { - "begin": "(?=(@|@?[\\w$]+|[=-]>|\\-\\d|\\[|{|\"|'))|\\(", + "begin": "\\(", "beginCaptures": { "0": { "name": "punctuation.definition.arguments.begin.bracket.round.coffee" } }, - "end": "\\)|(?=\\s*(?|\\-\\d|\\[|{|\"|'))", + "end": "(?=\\s*(?|\\-\\d|\\[|\\{|\"|'))|(?=\\())", + "begin": "(@)?([\\w$]+)(?=\\()", "beginCaptures": { "1": { "name": "variable.other.readwrite.instance.coffee" @@ -600,27 +610,56 @@ "2": { "patterns": [ { - "match": "(?x)\n\\b(isNaN|isFinite|eval|uneval|parseInt|parseFloat|decodeURI|\ndecodeURIComponent|encodeURI|encodeURIComponent|escape|unescape|\nrequire|set(Interval|Timeout)|clear(Interval|Timeout))\\b", - "name": "support.function.coffee" - }, - { - "match": "[a-zA-Z_$][\\w$]*", - "name": "entity.name.function.coffee" - }, - { - "match": "\\d[\\w$]*", - "name": "invalid.illegal.identifier.coffee" + "include": "#function_names" } ] } }, - "end": "(?<=\\))|(?=\\s*(?|\\-\\d|\\[|{|\"|')))", + "beginCaptures": { + "1": { + "name": "variable.other.readwrite.instance.coffee" + }, + "2": { + "patterns": [ + { + "include": "#function_names" + } + ] + } + }, + "end": "(?=\\s*(?|\\-\\d|\\[|\\{|\"|'))|(?=\\())", + "begin": "(?:(\\.)|(::))\\s*([\\w$]+)\\s*(?=\\()", "beginCaptures": { "1": { "name": "punctuation.separator.method.period.coffee" @@ -724,35 +763,67 @@ "3": { "patterns": [ { - "match": "(?x)\n\\bon(Rowsinserted|Rowsdelete|Rowenter|Rowexit|Resize|Resizestart|Resizeend|Reset|\nReadystatechange|Mouseout|Mouseover|Mousedown|Mouseup|Mousemove|\nBefore(cut|deactivate|unload|update|paste|print|editfocus|activate)|\nBlur|Scrolltop|Submit|Select|Selectstart|Selectionchange|Hover|Help|\nChange|Contextmenu|Controlselect|Cut|Cellchange|Clock|Close|Deactivate|\nDatasetchanged|Datasetcomplete|Dataavailable|Drop|Drag|Dragstart|Dragover|\nDragdrop|Dragenter|Dragend|Dragleave|Dblclick|Unload|Paste|Propertychange|Error|\nErrorupdate|Keydown|Keyup|Keypress|Focus|Load|Activate|Afterupdate|Afterprint|Abort)\\b", - "name": "support.function.event-handler.coffee" - }, - { - "match": "(?x)\n\\b(shift|showModelessDialog|showModalDialog|showHelp|scroll|scrollX|scrollByPages|\nscrollByLines|scrollY|scrollTo|stop|strike|sizeToContent|sidebar|signText|sort|\nsup|sub|substr|substring|splice|split|send|set(Milliseconds|Seconds|Minutes|Hours|\nMonth|Year|FullYear|Date|UTC(Milliseconds|Seconds|Minutes|Hours|Month|FullYear|Date)|\nTime|Hotkeys|Cursor|ZOptions|Active|Resizable|RequestHeader)|search|slice|\nsavePreferences|small|home|handleEvent|navigate|char|charCodeAt|charAt|concat|\ncontextual|confirm|compile|clear|captureEvents|call|createStyleSheet|createPopup|\ncreateEventObject|to(GMTString|UTCString|String|Source|UpperCase|LowerCase|LocaleString)|\ntest|taint|taintEnabled|indexOf|italics|disableExternalCapture|dump|detachEvent|unshift|\nuntaint|unwatch|updateCommands|join|javaEnabled|pop|push|plugins.refresh|paddings|parse|\nprint|prompt|preference|enableExternalCapture|exec|execScript|valueOf|UTC|find|file|\nfileModifiedDate|fileSize|fileCreatedDate|fileUpdatedDate|fixed|fontsize|fontcolor|\nforward|fromCharCode|watch|link|load|lastIndexOf|anchor|attachEvent|atob|apply|alert|\nabort|routeEvents|resize|resizeBy|resizeTo|recalc|returnValue|replace|reverse|reload|\nreleaseCapture|releaseEvents|go|get(Milliseconds|Seconds|Minutes|Hours|Month|Day|Year|FullYear|\nTime|Date|TimezoneOffset|UTC(Milliseconds|Seconds|Minutes|Hours|Day|Month|FullYear|Date)|\nAttention|Selection|ResponseHeader|AllResponseHeaders)|moveBy|moveBelow|moveTo|\nmoveToAbsolute|moveAbove|mergeAttributes|match|margins|btoa|big|bold|borderWidths|blink|back)\\b", - "name": "support.function.coffee" - }, - { - "match": "(?x)\n\\b(acceptNode|add|addEventListener|addTextTrack|adoptNode|after|animate|append|\nappendChild|appendData|before|blur|canPlayType|captureStream|\ncaretPositionFromPoint|caretRangeFromPoint|checkValidity|clear|click|\ncloneContents|cloneNode|cloneRange|close|closest|collapse|\ncompareBoundaryPoints|compareDocumentPosition|comparePoint|contains|\nconvertPointFromNode|convertQuadFromNode|convertRectFromNode|createAttribute|\ncreateAttributeNS|createCaption|createCDATASection|createComment|\ncreateContextualFragment|createDocument|createDocumentFragment|\ncreateDocumentType|createElement|createElementNS|createEntityReference|\ncreateEvent|createExpression|createHTMLDocument|createNodeIterator|\ncreateNSResolver|createProcessingInstruction|createRange|createShadowRoot|\ncreateTBody|createTextNode|createTFoot|createTHead|createTreeWalker|delete|\ndeleteCaption|deleteCell|deleteContents|deleteData|deleteRow|deleteTFoot|\ndeleteTHead|detach|disconnect|dispatchEvent|elementFromPoint|elementsFromPoint|\nenableStyleSheetsForSet|entries|evaluate|execCommand|exitFullscreen|\nexitPointerLock|expand|extractContents|fastSeek|firstChild|focus|forEach|get|\ngetAll|getAnimations|getAttribute|getAttributeNames|getAttributeNode|\ngetAttributeNodeNS|getAttributeNS|getBoundingClientRect|getBoxQuads|\ngetClientRects|getContext|getDestinationInsertionPoints|getElementById|\ngetElementsByClassName|getElementsByName|getElementsByTagName|\ngetElementsByTagNameNS|getItem|getNamedItem|getSelection|getStartDate|\ngetVideoPlaybackQuality|has|hasAttribute|hasAttributeNS|hasAttributes|\nhasChildNodes|hasFeature|hasFocus|importNode|initEvent|insertAdjacentElement|\ninsertAdjacentHTML|insertAdjacentText|insertBefore|insertCell|insertData|\ninsertNode|insertRow|intersectsNode|isDefaultNamespace|isEqualNode|\nisPointInRange|isSameNode|item|key|keys|lastChild|load|lookupNamespaceURI|\nlookupPrefix|matches|move|moveAttribute|moveAttributeNode|moveChild|\nmoveNamedItem|namedItem|nextNode|nextSibling|normalize|observe|open|\nparentNode|pause|play|postMessage|prepend|preventDefault|previousNode|\npreviousSibling|probablySupportsContext|queryCommandEnabled|\nqueryCommandIndeterm|queryCommandState|queryCommandSupported|queryCommandValue|\nquerySelector|querySelectorAll|registerContentHandler|registerElement|\nregisterProtocolHandler|releaseCapture|releaseEvents|remove|removeAttribute|\nremoveAttributeNode|removeAttributeNS|removeChild|removeEventListener|\nremoveItem|replace|replaceChild|replaceData|replaceWith|reportValidity|\nrequestFullscreen|requestPointerLock|reset|scroll|scrollBy|scrollIntoView|\nscrollTo|seekToNextFrame|select|selectNode|selectNodeContents|set|setAttribute|\nsetAttributeNode|setAttributeNodeNS|setAttributeNS|setCapture|\nsetCustomValidity|setEnd|setEndAfter|setEndBefore|setItem|setNamedItem|\nsetRangeText|setSelectionRange|setSinkId|setStart|setStartAfter|setStartBefore|\nslice|splitText|stepDown|stepUp|stopImmediatePropagation|stopPropagation|\nsubmit|substringData|supports|surroundContents|takeRecords|terminate|toBlob|\ntoDataURL|toggle|toString|values|write|writeln)\\b", - "name": "support.function.dom.coffee" - }, - { - "match": "[a-zA-Z_$][\\w$]*", - "name": "entity.name.function.coffee" - }, - { - "match": "\\d[\\w$]*", - "name": "invalid.illegal.identifier.coffee" + "include": "#method_names" } ] } }, - "end": "(?<=\\))|(?=\\s*(?|\\-\\d|\\[|{|\"|')))", + "beginCaptures": { + "1": { + "name": "punctuation.separator.method.period.coffee" + }, + "2": { + "name": "keyword.operator.prototype.coffee" + }, + "3": { + "patterns": [ + { + "include": "#method_names" + } + ] + } + }, + "end": "(?=\\s*(? Date: Tue, 17 Oct 2017 16:00:03 -0700 Subject: [PATCH 184/394] Add "code" to copied marker metadata info Fixes #36449 --- .../workbench/parts/markers/common/markersModel.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/markers/common/markersModel.ts b/src/vs/workbench/parts/markers/common/markersModel.ts index 561705c5a60..735d45e845b 100644 --- a/src/vs/workbench/parts/markers/common/markersModel.ts +++ b/src/vs/workbench/parts/markers/common/markersModel.ts @@ -58,11 +58,14 @@ export class Marker { } public toString(): string { - return [`file: '${this.marker.resource}'`, - `severity: '${Severity.toString(this.marker.severity)}'`, - `message: '${this.marker.message}'`, - `at: '${this.marker.startLineNumber},${this.marker.startColumn}'`, - `source: '${this.marker.source ? this.marker.source : ''}'`].join('\n'); + return [ + `file: '${this.marker.resource}'`, + `severity: '${Severity.toString(this.marker.severity)}'`, + `message: '${this.marker.message}'`, + `at: '${this.marker.startLineNumber},${this.marker.startColumn}'`, + `source: '${this.marker.source ? this.marker.source : ''}'`, + `code: '${this.marker.code ? this.marker.code : ''}'` + ].join('\n'); } } From c5bf0096b44d7ae8b5220ec1dcf342525850dcf1 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 17 Oct 2017 16:12:11 -0700 Subject: [PATCH 185/394] Allow term workspace selector command to work when no folder is opened Fixes #36392 --- .../parts/terminal/electron-browser/terminalActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 7bb15300f3a..13ad6995359 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -233,7 +233,7 @@ export class CreateNewSelectWorkspaceTerminalAction extends Action { public run(event?: any): TPromise { return this.commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND).then(workspace => { - const instance = this.terminalService.createInstance({ cwd: workspace.uri.fsPath }, true); + const instance = this.terminalService.createInstance(workspace ? { cwd: workspace.uri.fsPath } : undefined, true); if (!instance) { return TPromise.as(void 0); } From 1ff751a12b8a1646ac19375126e106a3df4df8cc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 17 Oct 2017 22:14:53 -0700 Subject: [PATCH 186/394] Fix marker test for toString --- .../parts/markers/test/common/markersModel.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/markers/test/common/markersModel.test.ts b/src/vs/workbench/parts/markers/test/common/markersModel.test.ts index 450eb2d2ff9..eacdf1fcc13 100644 --- a/src/vs/workbench/parts/markers/test/common/markersModel.test.ts +++ b/src/vs/workbench/parts/markers/test/common/markersModel.test.ts @@ -121,10 +121,12 @@ suite('MarkersModel Test', () => { }); test('toString()', function () { - assert.equal(`file: 'file:///a/res1'\nseverity: 'Error'\nmessage: 'some message'\nat: '10,5'\nsource: 'tslint'`, new Marker('', aMarker('a/res1')).toString()); - assert.equal(`file: 'file:///a/res2'\nseverity: 'Warning'\nmessage: 'some message'\nat: '10,5'\nsource: 'tslint'`, new Marker('', aMarker('a/res2', Severity.Warning)).toString()); - assert.equal(`file: 'file:///a/res2'\nseverity: 'Info'\nmessage: 'Info'\nat: '1,2'\nsource: ''`, new Marker('', aMarker('a/res2', Severity.Info, 1, 2, 1, 8, 'Info', '')).toString()); - assert.equal(`file: 'file:///a/res2'\nseverity: ''\nmessage: 'Ignore message'\nat: '1,2'\nsource: 'Ignore'`, new Marker('', aMarker('a/res2', Severity.Ignore, 1, 2, 1, 8, 'Ignore message', 'Ignore')).toString()); + const res1Marker = aMarker('a/res1'); + res1Marker.code = '1234'; + assert.equal(`file: 'file:///a/res1'\nseverity: 'Error'\nmessage: 'some message'\nat: '10,5'\nsource: 'tslint'\ncode: '1234'`, new Marker('', res1Marker).toString()); + assert.equal(`file: 'file:///a/res2'\nseverity: 'Warning'\nmessage: 'some message'\nat: '10,5'\nsource: 'tslint'\ncode: ''`, new Marker('', aMarker('a/res2', Severity.Warning)).toString()); + assert.equal(`file: 'file:///a/res2'\nseverity: 'Info'\nmessage: 'Info'\nat: '1,2'\nsource: ''\ncode: ''`, new Marker('', aMarker('a/res2', Severity.Info, 1, 2, 1, 8, 'Info', '')).toString()); + assert.equal(`file: 'file:///a/res2'\nseverity: ''\nmessage: 'Ignore message'\nat: '1,2'\nsource: 'Ignore'\ncode: ''`, new Marker('', aMarker('a/res2', Severity.Ignore, 1, 2, 1, 8, 'Ignore message', 'Ignore')).toString()); }); function hasMarker(markers: Marker[], marker: IMarker): boolean { From 2cbaa8c7d5a0e808362b5a1cd6b8f0919b5d49cd Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 17 Oct 2017 22:32:27 -0700 Subject: [PATCH 187/394] Pick up TS 2.6.1-insiders.20171016 --- extensions/npm-shrinkwrap.json | 6 +++--- extensions/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/npm-shrinkwrap.json b/extensions/npm-shrinkwrap.json index 3a586ecad98..6241de07cd9 100644 --- a/extensions/npm-shrinkwrap.json +++ b/extensions/npm-shrinkwrap.json @@ -3,9 +3,9 @@ "version": "0.0.1", "dependencies": { "typescript": { - "version": "2.6.0-insiders.20171013", - "from": "typescript@2.6.0-insiders.20171013", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.0-insiders.20171013.tgz" + "version": "2.6.1-insiders.20171016", + "from": "typescript@2.6.1-insiders.20171016", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1-insiders.20171016.tgz" } } } diff --git a/extensions/package.json b/extensions/package.json index ce960b5b23b..bcf3e8b0dc8 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "2.6.0-insiders.20171013" + "typescript": "2.6.1-insiders.20171016" }, "scripts": { "postinstall": "node ./postinstall" From 64992dee5cfd22c2533c04f24ccea2f3906b15bc Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 17 Oct 2017 20:44:07 +0200 Subject: [PATCH 188/394] Adopt menus using new configuration change event --- src/vs/code/electron-main/menus.ts | 148 +++++++++++------------------ 1 file changed, 58 insertions(+), 90 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 68af45f2186..df337ac6675 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -11,8 +11,8 @@ import * as arrays from 'vs/base/common/arrays'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ipcMain as ipc, app, shell, dialog, Menu, MenuItem, BrowserWindow } from 'electron'; import { OpenContext, IRunActionInWindowRequest } from 'vs/platform/windows/common/windows'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IFilesConfiguration, AutoSaveConfiguration } from 'vs/platform/files/common/files'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { AutoSaveConfiguration } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService, State as UpdateState } from 'vs/platform/update/common/update'; import product from 'vs/platform/node/product'; @@ -29,27 +29,6 @@ interface IExtensionViewlet { label: string; } -interface IConfiguration extends IFilesConfiguration { - window: { - enableMenuBarMnemonics: boolean; - nativeTabs: boolean; - }; - workbench: { - sideBar: { - location: 'left' | 'right'; - }, - statusBar: { - visible: boolean; - }, - activityBar: { - visible: boolean; - } - }; - editor: { - multiCursorModifier: 'ctrlCmd' | 'alt' - }; -} - interface IMenuItemClickHandler { inDevTools: (contents: Electron.WebContents) => void; inNoWindow: () => void; @@ -61,13 +40,15 @@ export class CodeMenu { private static MAX_MENU_RECENT_ENTRIES = 10; - private currentAutoSaveSetting: string; - private currentMultiCursorModifierSetting: string; - private currentSidebarLocation: 'left' | 'right'; - private currentStatusbarVisible: boolean; - private currentActivityBarVisible: boolean; - private currentEnableMenuBarMnemonics: boolean; - private currentEnableNativeTabs: boolean; + private keys = [ + 'files.autoSave', + 'editor.multiCursorModifier', + 'workbench.sideBar.location', + 'workbench.statusBar.visible', + 'workbench.activityBar.visible', + 'window.enableMenuBarMnemonics', + 'window.nativeTabs' + ]; private isQuitting: boolean; private appMenuInstalled: boolean; @@ -99,8 +80,6 @@ export class CodeMenu { this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0); this.keybindingsResolver = instantiationService.createInstance(KeybindingsResolver); - this.onConfigurationUpdated(this.configurationService.getConfiguration()); - this.install(); this.registerListeners(); @@ -136,7 +115,7 @@ export class CodeMenu { }); // Update when auto save config changes - this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), true /* update menu if changed */)); + this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e)); // Listen to update service this.updateService.onStateChange(() => this.updateMenu()); @@ -145,67 +124,56 @@ export class CodeMenu { this.keybindingsResolver.onKeybindingsChanged(() => this.updateMenu()); } - private onConfigurationUpdated(config: IConfiguration, handleMenu?: boolean): void { - let updateMenu = false; - const newAutoSaveSetting = config && config.files && config.files.autoSave; - if (newAutoSaveSetting !== this.currentAutoSaveSetting) { - this.currentAutoSaveSetting = newAutoSaveSetting; - updateMenu = true; - } - - const newMultiCursorModifierSetting = config && config.editor && config.editor.multiCursorModifier; - if (newMultiCursorModifierSetting !== this.currentMultiCursorModifierSetting) { - this.currentMultiCursorModifierSetting = newMultiCursorModifierSetting; - updateMenu = true; - } - - const newSidebarLocation = config && config.workbench && config.workbench.sideBar && config.workbench.sideBar.location || 'left'; - if (newSidebarLocation !== this.currentSidebarLocation) { - this.currentSidebarLocation = newSidebarLocation; - updateMenu = true; - } - - let newStatusbarVisible = config && config.workbench && config.workbench.statusBar && config.workbench.statusBar.visible; - if (typeof newStatusbarVisible !== 'boolean') { - newStatusbarVisible = true; - } - if (newStatusbarVisible !== this.currentStatusbarVisible) { - this.currentStatusbarVisible = newStatusbarVisible; - updateMenu = true; - } - - let newActivityBarVisible = config && config.workbench && config.workbench.activityBar && config.workbench.activityBar.visible; - if (typeof newActivityBarVisible !== 'boolean') { - newActivityBarVisible = true; - } - if (newActivityBarVisible !== this.currentActivityBarVisible) { - this.currentActivityBarVisible = newActivityBarVisible; - updateMenu = true; - } - - let newEnableMenuBarMnemonics = config && config.window && config.window.enableMenuBarMnemonics; - if (typeof newEnableMenuBarMnemonics !== 'boolean') { - newEnableMenuBarMnemonics = true; - } - if (newEnableMenuBarMnemonics !== this.currentEnableMenuBarMnemonics) { - this.currentEnableMenuBarMnemonics = newEnableMenuBarMnemonics; - updateMenu = true; - } - - let newEnableNativeTabs = config && config.window && config.window.nativeTabs; - if (typeof newEnableNativeTabs !== 'boolean') { - newEnableNativeTabs = false; - } - if (newEnableNativeTabs !== this.currentEnableNativeTabs) { - this.currentEnableNativeTabs = newEnableNativeTabs; - updateMenu = true; - } - - if (handleMenu && updateMenu) { + private onConfigurationUpdated(event: IConfigurationChangeEvent): void { + if (this.keys.some(key => event.affectsConfiguration(key))) { this.updateMenu(); } } + private get currentAutoSaveSetting(): string { + return this.configurationService.getValue('files.autoSave'); + } + + private get currentMultiCursorModifierSetting(): string { + return this.configurationService.getValue('editor.multiCursorModifier'); + } + + private get currentSidebarLocation(): string { + return this.configurationService.getValue('workbench.sideBar.location') || 'left'; + } + + private get currentStatusbarVisible(): boolean { + let statusbarVisible = this.configurationService.getValue('workbench.statusBar.visible'); + if (typeof statusbarVisible !== 'boolean') { + statusbarVisible = true; + } + return statusbarVisible; + } + + private get currentActivityBarVisible(): boolean { + let activityBarVisible = this.configurationService.getValue('workbench.activityBar.visible'); + if (typeof activityBarVisible !== 'boolean') { + activityBarVisible = true; + } + return activityBarVisible; + } + + private get currentEnableMenuBarMnemonics(): boolean { + let enableMenuBarMnemonics = this.configurationService.getValue('window.enableMenuBarMnemonics'); + if (typeof enableMenuBarMnemonics !== 'boolean') { + enableMenuBarMnemonics = true; + } + return enableMenuBarMnemonics; + } + + private get currentEnableNativeTabs(): boolean { + let enableNativeTabs = this.configurationService.getValue('window.nativeTabs'); + if (typeof enableNativeTabs !== 'boolean') { + enableNativeTabs = false; + } + return enableNativeTabs; + } + private updateMenu(): void { this.menuUpdater.schedule(); // buffer multiple attempts to update the menu } From 56a9f4e652440e5f19b8be8d48e5784f81c4eeb7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 17 Oct 2017 21:20:28 +0200 Subject: [PATCH 189/394] Update context key service to listen only on config section changes --- .../platform/contextkey/browser/contextKeyService.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 39d1f8cc654..032b7f49d77 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -8,7 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver'; import { IContextKey, IContext, IContextKeyServiceTarget, IContextKeyService, SET_CONTEXT_COMMAND_ID, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import Event, { Emitter, debounceEvent } from 'vs/base/common/event'; const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context'; @@ -53,12 +53,14 @@ class ConfigAwareContextValuesContainer extends Context { private _emitter: Emitter; private _subscription: IDisposable; + private _configurationService: IConfigurationService; constructor(id: number, configurationService: IConfigurationService, emitter: Emitter) { super(id, null); this._emitter = emitter; - this._subscription = configurationService.onDidChangeConfiguration(e => this._updateConfigurationContext(configurationService.getConfiguration())); + this._configurationService = configurationService; + this._subscription = configurationService.onDidChangeConfiguration(e => this._onConfigurationUpdated(e)); this._updateConfigurationContext(configurationService.getConfiguration()); } @@ -66,6 +68,12 @@ class ConfigAwareContextValuesContainer extends Context { this._subscription.dispose(); } + private _onConfigurationUpdated(event: IConfigurationChangeEvent): void { + if (event.affectsConfiguration('config')) { + this._updateConfigurationContext(this._configurationService.getConfiguration()); + } + } + private _updateConfigurationContext(config: any) { // remove old config.xyz values From b65cb01b3defb19f4403f62a9fdf6ff0f8dc4174 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 08:39:29 +0200 Subject: [PATCH 190/394] Send the configuration change event data to Extension host --- .../configuration/common/configuration.ts | 8 +++ .../common/configurationModels.ts | 52 +++++++++++++++---- .../mainThreadConfiguration.ts | 4 +- src/vs/workbench/api/node/extHost.protocol.ts | 4 +- .../api/node/extHostConfiguration.ts | 12 ++--- .../common/configurationModels.ts | 22 +++++++- 6 files changed, 80 insertions(+), 22 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 5f5145c0ed3..41093f27f8a 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -43,6 +43,9 @@ export interface IConfigurationChangeEvent { // Following data is used for telemetry source: ConfigurationTarget; sourceConfig: any; + + // Following data is used for Extension host configuration event + toJSON(): IConfigurationChangeEventData; } export interface IConfigurationService { @@ -103,6 +106,11 @@ export interface IConfigurationData { folders: { [folder: string]: IConfiguraionModel }; } +export interface IConfigurationChangeEventData { + changedConfiguration: IConfiguraionModel; + changedConfigurationByResource: { [folder: string]: IConfiguraionModel }; +} + export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { added: string[], removed: string[], updated: string[] } { const added = to.keys.filter(key => from.keys.indexOf(key) === -1); const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 7bfc0852a5e..c58669e9dec 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -11,7 +11,7 @@ import * as objects from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree } from 'vs/platform/configuration/common/configuration'; +import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; import { Workspace } from 'vs/platform/workspace/common/workspace'; export class ConfigurationModel implements IConfiguraionModel { @@ -481,29 +481,46 @@ export class AbstractConfigurationChangeEvent { export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChangeEvent implements IConfigurationChangeEvent { - private changedConfiguration: ConfigurationModel = null; + private _changedConfiguration: ConfigurationModel = null; constructor(readonly affectedKeys: string[], readonly source: ConfigurationTarget, readonly sourceConfig: any) { super(); } - affectsConfiguration(config: string, resource?: URI): boolean { - if (!this.changedConfiguration) { - this.changedConfiguration = new ConfigurationModel(); - this.updateKeys(this.changedConfiguration, this.affectedKeys); + get changedConfiguration(): ConfigurationModel { + if (!this._changedConfiguration) { + this._changedConfiguration = new ConfigurationModel(); + this.updateKeys(this._changedConfiguration, this.affectedKeys); } + return this._changedConfiguration; + } + + affectsConfiguration(config: string, resource?: URI): boolean { return this.doesConfigurationContains(this.changedConfiguration, config); } + toJSON(): IConfigurationChangeEventData { + return { + changedConfiguration: { + contents: this.changedConfiguration.contents, + overrides: this.changedConfiguration.overrides, + keys: this.changedConfiguration.keys + }, + changedConfigurationByResource: Object.create({}) + }; + } } export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent implements IConfigurationChangeEvent { - private changedConfiguration: ConfigurationModel = new ConfigurationModel(); - private changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); - private resources: URI[] = []; - private _source: ConfigurationTarget; private _sourceConfig: any; + constructor( + private changedConfiguration: ConfigurationModel = new ConfigurationModel(), + private resources: URI[] = [], + private changedConfigurationByResource: StrictResourceMap = new StrictResourceMap()) { + super(); + } + change(event: ConfigurationChangeEvent): ConfigurationChangeEvent change(keys: string[], resource?: URI): ConfigurationChangeEvent change(arg1: any, arg2?: any): ConfigurationChangeEvent { @@ -574,4 +591,19 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i } return changedConfigurationByResource; } + + toJSON(): IConfigurationChangeEventData { + return { + changedConfiguration: { + contents: this.changedConfiguration.contents, + overrides: this.changedConfiguration.overrides, + keys: this.changedConfiguration.keys + }, + changedConfigurationByResource: this.changedConfigurationByResource.keys().reduce((result, resource) => { + const { contents, overrides, keys } = this.changedConfigurationByResource.get(resource); + result[resource.toString()] = { contents, overrides, keys }; + return result; + }, Object.create({})) + }; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index a8b5cf06253..af38672d4b8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -27,8 +27,8 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { ) { const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); - this._configurationListener = configurationService.onDidChangeConfiguration(() => { - proxy.$acceptConfigurationChanged(configurationService.getConfigurationData()); + this._configurationListener = configurationService.onDidChangeConfiguration(e => { + proxy.$acceptConfigurationChanged(configurationService.getConfigurationData(), e.toJSON()); }); } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 5de663decdf..17980ed5b35 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -28,7 +28,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import { ITextSource } from 'vs/editor/common/model/textSource'; -import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; @@ -418,7 +418,7 @@ export interface ExtHostCommandsShape { } export interface ExtHostConfigurationShape { - $acceptConfigurationChanged(data: IConfigurationData): void; + $acceptConfigurationChanged(data: IConfigurationData, eventData: IConfigurationChangeEventData): void; } export interface ExtHostDiagnosticsShape { diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 55677b2d360..5a8dae4f23a 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -7,11 +7,11 @@ import { mixin } from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import Event, { Emitter } from 'vs/base/common/event'; -import { WorkspaceConfiguration } from 'vscode'; +import * as vscode from 'vscode'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol'; import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes'; -import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; import { Configuration } from 'vs/platform/configuration/common/configurationModels'; function lookUp(tree: any, key: string) { @@ -50,12 +50,12 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event; } - $acceptConfigurationChanged(data: IConfigurationData) { + $acceptConfigurationChanged(data: IConfigurationData, eventData: IConfigurationChangeEventData) { this._configuration = Configuration.parse(data, this._extHostWorkspace.workspace); this._onDidChangeConfiguration.fire(undefined); } - getConfiguration(section?: string, resource?: URI): WorkspaceConfiguration { + getConfiguration(section?: string, resource?: URI): vscode.WorkspaceConfiguration { const config = section ? lookUp(this._configuration.getSection(null, { resource }), section) : this._configuration.getSection(null, { resource }); @@ -75,7 +75,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { } } - const result: WorkspaceConfiguration = { + const result: vscode.WorkspaceConfiguration = { has(key: string): boolean { return typeof lookUp(config, key) !== 'undefined'; }, @@ -115,6 +115,6 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { mixin(result, config, false); } - return Object.freeze(result); + return Object.freeze(result); } } diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 8b9e5aa53fe..3cef3209dfe 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -270,7 +270,7 @@ export class Configuration extends BaseConfiguration { export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent { - constructor(private configurationChangeEvent: ConfigurationChangeEvent, private workspace: Workspace) { + constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace) { } get affectedKeys(): string[] { @@ -299,4 +299,22 @@ export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEv return false; } + + toJSON(): IConfigurationChangeEventData { + return this.configurationChangeEvent.toJSON(); + } + + public static parse(data: IConfigurationChangeEventData, workspace: Workspace): WorkspaceConfigurationChangeEvent { + const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides); + const resources: URI[] = []; + const changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); + for (const key of Object.keys(data.changedConfigurationByResource)) { + const resource = URI.parse(key); + const model = data.changedConfigurationByResource[key]; + resources.push(resource); + changedConfigurationByResource.set(resource, new ConfigurationModel(model.contents, model.keys, model.overrides)); + } + const event = new ConfigurationChangeEvent(changedConfiguration, resources, changedConfigurationByResource); + return new WorkspaceConfigurationChangeEvent(event, workspace); + } } \ No newline at end of file From 5faa72ac39f5f56ec57a6a17ee34f0ee8ff840f3 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 09:03:15 +0200 Subject: [PATCH 191/394] deco - use a color for ignored files --- extensions/git/package.json | 11 ++++++++++- extensions/git/src/decorationProvider.ts | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index abb7f5400ea..a69c16b2429 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -850,6 +850,15 @@ "dark": "#73C991", "highContrast": "#73C991" } + }, + { + "id": "git.color.ignored", + "description": "Color for ignored resources", + "defaults": { + "light": "#8E8E90", + "dark": "#A7A8A9", + "highContrast": "#A7A8A9" + } } ] }, @@ -864,4 +873,4 @@ "@types/node": "7.0.43", "mocha": "^3.2.0" } -} \ No newline at end of file +} diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 7adbb51003d..5ae257473b3 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -5,7 +5,7 @@ 'use strict'; -import { window, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider } from 'vscode'; +import { window, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider, ThemeColor } from 'vscode'; import { Repository, GitResourceGroup } from './repository'; import { Model } from './model'; import { debounce } from './decorators'; @@ -38,7 +38,7 @@ class GitIgnoreDecorationProvider implements DecorationProvider { if (ignored) { return { priority: 3, - opacity: 0.75 + color: new ThemeColor('git.color.ignored') }; } }); From 4b610b1f45b67d3d39a2a0460ea853a94750b80a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 09:17:14 +0200 Subject: [PATCH 192/394] update electron.d.ts (1.7.9) --- src/typings/electron.d.ts | 150 ++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 80 deletions(-) diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index e9530251310..ce604fb1bf0 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -37,91 +37,81 @@ declare namespace Electron { shiftKey?: boolean; altKey?: boolean; } + interface CommonInterface { - clipboard: Electron.Clipboard; - crashReporter: Electron.CrashReporter; - nativeImage: typeof Electron.NativeImage; - screen: Electron.Screen; - shell: Electron.Shell; + clipboard: Clipboard; + crashReporter: CrashReporter; + nativeImage: typeof NativeImage; + screen: Screen; + shell: Shell; } interface MainInterface extends CommonInterface { - app: Electron.App; - autoUpdater: Electron.AutoUpdater; - BrowserView: typeof Electron.BrowserView; - BrowserWindow: typeof Electron.BrowserWindow; - ClientRequest: typeof Electron.ClientRequest; - contentTracing: Electron.ContentTracing; - Cookies: typeof Electron.Cookies; - Debugger: typeof Electron.Debugger; - dialog: Electron.Dialog; - DownloadItem: typeof Electron.DownloadItem; - globalShortcut: Electron.GlobalShortcut; - IncomingMessage: typeof Electron.IncomingMessage; - ipcMain: Electron.IpcMain; - Menu: typeof Electron.Menu; - MenuItem: typeof Electron.MenuItem; - net: Electron.Net; - Notification: typeof Electron.Notification; - powerMonitor: Electron.PowerMonitor; - powerSaveBlocker: Electron.PowerSaveBlocker; - protocol: Electron.Protocol; - session: typeof Electron.Session; - systemPreferences: Electron.SystemPreferences; - TouchBar: typeof Electron.TouchBar; - Tray: typeof Electron.Tray; - webContents: typeof Electron.WebContents; - WebRequest: typeof Electron.WebRequest; + app: App; + autoUpdater: AutoUpdater; + BrowserView: typeof BrowserView; + BrowserWindow: typeof BrowserWindow; + ClientRequest: typeof ClientRequest; + contentTracing: ContentTracing; + Cookies: typeof Cookies; + Debugger: typeof Debugger; + dialog: Dialog; + DownloadItem: typeof DownloadItem; + globalShortcut: GlobalShortcut; + IncomingMessage: typeof IncomingMessage; + ipcMain: IpcMain; + Menu: typeof Menu; + MenuItem: typeof MenuItem; + net: Net; + Notification: typeof Notification; + powerMonitor: PowerMonitor; + powerSaveBlocker: PowerSaveBlocker; + protocol: Protocol; + session: typeof Session; + systemPreferences: SystemPreferences; + TouchBar: typeof TouchBar; + Tray: typeof Tray; + webContents: typeof WebContents; + WebRequest: typeof WebRequest; } interface RendererInterface extends CommonInterface { - BrowserWindowProxy: typeof Electron.BrowserWindowProxy; - desktopCapturer: Electron.DesktopCapturer; - ipcRenderer: Electron.IpcRenderer; - remote: Electron.Remote; - webFrame: Electron.WebFrame; - webviewTag: Electron.WebviewTag; + BrowserWindowProxy: typeof BrowserWindowProxy; + desktopCapturer: DesktopCapturer; + ipcRenderer: IpcRenderer; + remote: Remote; + webFrame: WebFrame; + webviewTag: WebviewTag; } - interface AllElectron { - app: Electron.App; - autoUpdater: Electron.AutoUpdater; - BrowserView: typeof Electron.BrowserView; - BrowserWindow: typeof Electron.BrowserWindow; - BrowserWindowProxy: typeof Electron.BrowserWindowProxy; - ClientRequest: typeof Electron.ClientRequest; - clipboard: Electron.Clipboard; - contentTracing: Electron.ContentTracing; - Cookies: typeof Electron.Cookies; - crashReporter: Electron.CrashReporter; - Debugger: typeof Electron.Debugger; - desktopCapturer: Electron.DesktopCapturer; - dialog: Electron.Dialog; - DownloadItem: typeof Electron.DownloadItem; - globalShortcut: Electron.GlobalShortcut; - IncomingMessage: typeof Electron.IncomingMessage; - ipcMain: Electron.IpcMain; - ipcRenderer: Electron.IpcRenderer; - Menu: typeof Electron.Menu; - MenuItem: typeof Electron.MenuItem; - nativeImage: typeof Electron.NativeImage; - net: Electron.Net; - Notification: typeof Electron.Notification; - powerMonitor: Electron.PowerMonitor; - powerSaveBlocker: Electron.PowerSaveBlocker; - protocol: Electron.Protocol; - remote: Electron.Remote; - screen: Electron.Screen; - session: typeof Electron.Session; - shell: Electron.Shell; - systemPreferences: Electron.SystemPreferences; - TouchBar: typeof Electron.TouchBar; - Tray: typeof Electron.Tray; - webContents: typeof Electron.WebContents; - webFrame: Electron.WebFrame; - WebRequest: typeof Electron.WebRequest; - webviewTag: Electron.WebviewTag; - } + interface AllElectron extends MainInterface, RendererInterface { } + + const app: App; + const autoUpdater: AutoUpdater; + const clipboard: Clipboard; + const contentTracing: ContentTracing; + const crashReporter: CrashReporter; + const desktopCapturer: DesktopCapturer; + const dialog: Dialog; + const globalShortcut: GlobalShortcut; + const ipcMain: IpcMain; + const ipcRenderer: IpcRenderer; + type nativeImage = NativeImage; + const nativeImage: typeof NativeImage; + const net: Net; + const powerMonitor: PowerMonitor; + const powerSaveBlocker: PowerSaveBlocker; + const protocol: Protocol; + const remote: Remote; + const screen: Screen; + type session = Session; + const session: typeof Session; + const shell: Shell; + const systemPreferences: SystemPreferences; + type webContents = WebContents; + const webContents: typeof WebContents; + const webFrame: WebFrame; + const webviewTag: WebviewTag; interface App extends EventEmitter { @@ -6362,7 +6352,8 @@ declare namespace Electron { ignoreSystemCrashHandler?: boolean; /** * An object you can define that will be sent along with the report. Only string - * properties are sent correctly. Nested objects are not supported. + * properties are sent correctly. Nested objects are not supported and the property + * names and values must be less than 64 characters long. */ extra?: any; /** @@ -8089,12 +8080,11 @@ declare namespace Electron { } declare module 'electron' { - const electron: Electron.AllElectron; - export = electron; + export = Electron; } interface NodeRequireFunction { - (moduleName: 'electron'): Electron.AllElectron; + (moduleName: 'electron'): typeof Electron; } interface File { From 47bd309a7bcabaff59d09593eeacb79698e5cf62 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 09:40:33 +0200 Subject: [PATCH 193/394] deco - show file decoration also in open editors sections --- .../parts/files/browser/views/openEditorsView.ts | 11 ++++++++--- .../parts/files/browser/views/openEditorsViewer.ts | 12 +++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts index 541fd1adb78..301fe2a0081 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts @@ -14,7 +14,7 @@ import { IItemCollapseEvent } from 'vs/base/parts/tree/browser/treeModel'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup } from 'vs/workbench/common/editor'; import { SaveAllAction } from 'vs/workbench/parts/files/browser/fileActions'; @@ -183,7 +183,7 @@ export class OpenEditorsView extends ViewsViewletPanel { this.disposables.push(this.model.onModelChanged(e => this.onEditorStacksModelChanged(e))); // Also handle configuration updates - this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), e))); // Handle dirty counter this.disposables.push(this.untitledEditorService.onDidChangeDirty(e => this.updateDirtyIndicator())); @@ -259,7 +259,7 @@ export class OpenEditorsView extends ViewsViewletPanel { } } - private onConfigurationUpdated(configuration: IFilesConfiguration): void { + private onConfigurationUpdated(configuration: IFilesConfiguration, event?: IConfigurationChangeEvent): void { if (this.isDisposed) { return; // guard against possible race condition when config change causes recreate of views } @@ -280,6 +280,11 @@ export class OpenEditorsView extends ViewsViewletPanel { // Adjust expanded body size this.minimumBodySize = this.maximumBodySize = this.getExpandedBodySize(this.model); + + // Trigger a 'repaint' when decoration settings change + if (event && event.affectsConfiguration('explorer.decorations')) { + this.tree.refresh(); + } } private updateDirtyIndicator(): void { diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts b/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts index a67a4d87ea6..c72ae86cbaa 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts @@ -24,13 +24,14 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IEditorGroup, IEditorStacksModel } from 'vs/workbench/common/editor'; import { OpenEditor } from 'vs/workbench/parts/files/common/explorerModel'; import { ContributableActionProvider } from 'vs/workbench/browser/actions'; -import { explorerItemToFileResource } from 'vs/workbench/parts/files/common/files'; +import { explorerItemToFileResource, IFilesConfiguration } from 'vs/workbench/parts/files/common/files'; import { ITextFileService, AutoSaveMode } from 'vs/workbench/services/textfile/common/textfiles'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { EditorStacksModel, EditorGroup } from 'vs/workbench/common/editor/editorStacksModel'; import { SaveFileAction, RevertFileAction, SaveFileAsAction, OpenToSideAction, SelectResourceForCompareAction, CompareResourcesAction, SaveAllInGroupAction, CompareWithSavedAction } from 'vs/workbench/parts/files/browser/fileActions'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { CloseOtherEditorsInGroupAction, CloseEditorAction, CloseEditorsInGroupAction, CloseUnmodifiedEditorsInGroupAction } from 'vs/workbench/browser/parts/editor/editorActions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; const $ = dom.$; @@ -86,7 +87,8 @@ export class Renderer implements IRenderer { constructor( private actionProvider: ActionProvider, @IInstantiationService private instantiationService: IInstantiationService, - @IKeybindingService private keybindingService: IKeybindingService + @IKeybindingService private keybindingService: IKeybindingService, + @IConfigurationService private configurationService: IConfigurationService ) { // noop } @@ -149,7 +151,11 @@ export class Renderer implements IRenderer { private renderOpenEditor(tree: ITree, editor: OpenEditor, templateData: IOpenEditorTemplateData): void { editor.isDirty() ? dom.addClass(templateData.container, 'dirty') : dom.removeClass(templateData.container, 'dirty'); - templateData.root.setEditor(editor.editorInput, { italic: editor.isPreview(), extraClasses: ['open-editor'] }); + templateData.root.setEditor(editor.editorInput, { + italic: editor.isPreview(), + extraClasses: ['open-editor'], + fileDecorations: this.configurationService.getConfiguration().explorer.decorations + }); templateData.actionBar.context = { group: editor.editorGroup, editor: editor.editorInput }; } From b2f4ba4dd79068ef17431685acda8fd31472cd07 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Oct 2017 10:00:06 +0200 Subject: [PATCH 194/394] debug: change start without debugging keybinding --- .../parts/debug/electron-browser/debug.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index a88503d3faf..0b2665666de 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -6,7 +6,7 @@ import 'vs/css!../browser/media/debug.contribution'; import 'vs/css!../browser/media/debugHover'; import * as nls from 'vs/nls'; -import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; +import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -132,7 +132,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(PauseAction, PauseActi registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory); -registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.ID, RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5 }, CONTEXT_NOT_IN_DEBUG_MODE), 'Debug: Start Without Debugging', debugCategory); +registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.ID, RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_X) } }, CONTEXT_NOT_IN_DEBUG_MODE), 'Debug: Start Without Debugging', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveAllBreakpointsAction, RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL), 'Debug: Remove All Breakpoints', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(EnableAllBreakpointsAction, EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL), 'Debug: Enable All Breakpoints', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(DisableAllBreakpointsAction, DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL), 'Debug: Disable All Breakpoints', debugCategory); From ca2c1073246e7fcbdc76f4a665bfd0f76cb460e0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 10:06:02 +0200 Subject: [PATCH 195/394] deco - update decorations when gitignore-file changes --- extensions/git/src/decorationProvider.ts | 8 ++++--- src/vs/vscode.proposed.d.ts | 2 +- .../workbench/api/node/extHostDecorations.ts | 2 +- .../decorations/browser/decorationsService.ts | 22 ++++++++++++++----- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 5ae257473b3..19ef25fb811 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -5,10 +5,11 @@ 'use strict'; -import { window, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider, ThemeColor } from 'vscode'; +import { window, workspace, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider, ThemeColor } from 'vscode'; import { Repository, GitResourceGroup } from './repository'; import { Model } from './model'; import { debounce } from './decorators'; +import { filterEvent } from './util'; class GitIgnoreDecorationProvider implements DecorationProvider { @@ -20,8 +21,9 @@ class GitIgnoreDecorationProvider implements DecorationProvider { constructor(private repository: Repository) { this.disposables.push( - window.registerDecorationProvider(this, '.gitignore') - //todo@joh -> events when the ignore status actually changes, not when the file changes + window.registerDecorationProvider(this, '.gitignore'), + filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore'))(_ => this._onDidChangeDecorations.fire()) + //todo@joh -> events when the ignore status actually changes, not only when the file changes ); } diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index d48b0f9020a..63ebd06f1b4 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -182,7 +182,7 @@ declare module 'vscode' { } export interface DecorationProvider { - onDidChangeDecorations: Event; + onDidChangeDecorations: Event; provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; } diff --git a/src/vs/workbench/api/node/extHostDecorations.ts b/src/vs/workbench/api/node/extHostDecorations.ts index ad428987404..971896c96dd 100644 --- a/src/vs/workbench/api/node/extHostDecorations.ts +++ b/src/vs/workbench/api/node/extHostDecorations.ts @@ -28,7 +28,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape { this._proxy.$registerDecorationProvider(handle, label); const listener = provider.onDidChangeDecorations(e => { - this._proxy.$onDidChange(handle, Array.isArray(e) ? e : [e]); + this._proxy.$onDidChange(handle, !e ? null : Array.isArray(e) ? e : [e]); }); return new Disposable(() => { diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index a6320b0fe65..63992705c3d 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -221,12 +221,21 @@ class DecorationProviderWrapper { constructor( private readonly _provider: IDecorationsProvider, - private readonly _emitter: Emitter + private readonly _uriEmitter: Emitter, + private readonly _flushEmitter: Emitter ) { this._dispoable = this._provider.onDidChange(uris => { - for (const uri of uris) { - this.data.delete(uri.toString()); - this._fetchData(uri); + if (!uris) { + // flush event -> drop all data, can affect everything + this.data.clear(); + this._flushEmitter.fire({ affectsResource() { return true; } }); + + } else { + // selective changes -> drop for resource, fetch again, send event + for (const uri of uris) { + this.data.delete(uri.toString()); + this._fetchData(uri); + } } }); } @@ -293,7 +302,7 @@ class DecorationProviderWrapper { private _keepItem(uri: URI, data: IDecorationData): IDecorationData { let deco = data ? data : null; this.data.set(uri.toString(), deco); - this._emitter.fire(uri); + this._uriEmitter.fire(uri); return deco; } } @@ -345,7 +354,8 @@ export class FileDecorationsService implements IDecorationsService { const wrapper = new DecorationProviderWrapper( provider, - this._onDidChangeDecorationsDelayed + this._onDidChangeDecorationsDelayed, + this._onDidChangeDecorations ); const remove = this._data.push(wrapper); From b98939c0304b828edac1fd2ae446515766352dc8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 10:08:16 +0200 Subject: [PATCH 196/394] fix #36244 --- .../browser/parts/activitybar/activitybarActions.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 2b03a25ffec..04c486ec533 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -121,6 +121,12 @@ export class GlobalActivityActionItem extends ActivityActionItem { public onClick(event?: MouseEvent | KeyboardEvent): void { DOM.EventHelper.stop(event, true); + // Prevent duplicate menu showing because we already handle MOUSE_DOWN + // (refs: // https://github.com/Microsoft/vscode/issues/36244) + if (event.type === DOM.EventType.CLICK) { + return; + } + let location: HTMLElement | { x: number, y: number }; if (event instanceof MouseEvent) { const mouseEvent = new StandardMouseEvent(event); From 01a35abcc72959d5ae1c3c0df22e993387bd221d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 10:15:45 +0200 Subject: [PATCH 197/394] telemetry: do not log fileGet on settings JSON files --- .../textfile/common/textFileEditorModel.ts | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 8076fc12f2a..10cc2553f19 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -366,16 +366,22 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil private loadWithContent(content: IRawTextContent | IContent, backup?: URI): TPromise { return this.doLoadWithContent(content, backup).then(model => { - // We log the fileGet telemetry event after the model has been loaded to ensure a good mimetype - - /* __GDPR__ - "fileGet" : { - "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); + // Telemetry: We log the fileGet telemetry event after the model has been loaded to ensure a good mimetype + if (this.isSettingsFile()) { + /* __GDPR__ + "settingsRead" : {} + */ + this.telemetryService.publicLog('settingsRead'); // Do not log read to user settings.json and .vscode folder as a fileGet event as it ruins our JSON usage data + } else { + /* __GDPR__ + "fileGet" : { + "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); + } return model; }); From 71d332b4645da2c7cf91ea54eaebc4f792ac556d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 10:36:47 +0200 Subject: [PATCH 198/394] deco - remove opacity, use colors only, remove provider label from proposed api --- extensions/git/src/decorationProvider.ts | 4 ++-- extensions/git/src/repository.ts | 2 -- src/vs/vscode.proposed.d.ts | 3 +-- .../api/electron-browser/mainThreadDecorations.ts | 7 +++---- src/vs/workbench/api/node/extHost.api.impl.ts | 4 ++-- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostDecorations.ts | 2 +- .../services/decorations/browser/decorations.ts | 1 - .../decorations/browser/decorationsService.ts | 12 ++++++------ 9 files changed, 16 insertions(+), 21 deletions(-) diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 19ef25fb811..44789b518b5 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -21,7 +21,7 @@ class GitIgnoreDecorationProvider implements DecorationProvider { constructor(private repository: Repository) { this.disposables.push( - window.registerDecorationProvider(this, '.gitignore'), + window.registerDecorationProvider(this), filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore'))(_ => this._onDidChangeDecorations.fire()) //todo@joh -> events when the ignore status actually changes, not only when the file changes ); @@ -72,7 +72,7 @@ class GitDecorationProvider implements DecorationProvider { constructor(private repository: Repository) { this.disposables.push( - window.registerDecorationProvider(this, repository.root), + window.registerDecorationProvider(this), repository.onDidRunOperation(this.onDidRunOperation, this) ); } diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 74cd6c48bfd..ccd92bf005f 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -183,8 +183,6 @@ export class Resource implements SourceControlResourceState { get resourceDecoration(): DecorationData | undefined { const title = this.tooltip; switch (this.type) { - case Status.IGNORED: - return { priority: 3, title, opacity: 0.75 }; case Status.UNTRACKED: return { priority: 1, title, abbreviation: localize('untracked, short', "U"), bubble: true, color: new ThemeColor('git.color.untracked') }; case Status.INDEX_MODIFIED: diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 63ebd06f1b4..3ff70ed91db 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -178,7 +178,6 @@ declare module 'vscode' { bubble?: boolean; abbreviation?: string; color?: ThemeColor; - opacity?: number; } export interface DecorationProvider { @@ -187,7 +186,7 @@ declare module 'vscode' { } export namespace window { - export function registerDecorationProvider(provider: DecorationProvider, label: string): Disposable; + export function registerDecorationProvider(provider: DecorationProvider): Disposable; } //#endregion diff --git a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts index b2ae08b829c..7ac2b8c92ef 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts @@ -29,23 +29,22 @@ export class MainThreadDecorations implements MainThreadDecorationsShape { this._provider.clear(); } - $registerDecorationProvider(handle: number, label: string): void { + $registerDecorationProvider(handle: number): void { let emitter = new Emitter(); let registration = this._decorationsService.registerDecorationsProvider({ - label, + label: 'extension-provider', onDidChange: emitter.event, provideDecorations: (uri) => { return this._proxy.$providerDecorations(handle, uri).then(data => { if (!data) { return undefined; } - const [weight, bubble, title, letter, opacity, themeColor] = data; + const [weight, bubble, title, letter, themeColor] = data; return { weight: weight || 0, bubble: bubble || false, title, letter, - opacity, color: themeColor && themeColor.id }; }); diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 73c966c463e..128eb4a907e 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -378,8 +378,8 @@ export function createApiFactory( sampleFunction: proposedApiFunction(extension, () => { return extHostMessageService.showMessage(extension, Severity.Info, 'Hello Proposed Api!', {}, []); }), - registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider, label: string) => { - return extHostDecorations.registerDecorationProvider(provider, label); + registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => { + return extHostDecorations.registerDecorationProvider(provider, extension.id); }) }; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 17980ed5b35..2071ea617db 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -602,7 +602,7 @@ export interface ExtHostDebugServiceShape { } -export type DecorationData = [number, boolean, string, string, number, ThemeColor]; +export type DecorationData = [number, boolean, string, string, ThemeColor]; export interface ExtHostDecorationsShape { $providerDecorations(handle: number, uri: URI): TPromise; diff --git a/src/vs/workbench/api/node/extHostDecorations.ts b/src/vs/workbench/api/node/extHostDecorations.ts index 971896c96dd..e327dbe4995 100644 --- a/src/vs/workbench/api/node/extHostDecorations.ts +++ b/src/vs/workbench/api/node/extHostDecorations.ts @@ -41,7 +41,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape { $providerDecorations(handle: number, uri: URI): TPromise { const provider = this._provider.get(handle); return asWinJsPromise(token => provider.provideDecoration(uri, token)).then(data => { - return data && [data.priority, data.bubble, data.title, data.abbreviation, data.opacity, data.color]; + return data && [data.priority, data.bubble, data.title, data.abbreviation, data.color]; }); } } diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index 6a5b7993205..6356737cb2d 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -15,7 +15,6 @@ export const IDecorationsService = createDecorator('IFileDe export interface IDecorationData { readonly weight?: number; readonly color?: ColorIdentifier; - readonly opacity?: number; readonly letter?: string; readonly title?: string; readonly bubble?: boolean; diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index 63992705c3d..cd004e68f20 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -23,8 +23,8 @@ class DecorationRule { if (Array.isArray(data)) { return data.map(DecorationRule.keyOf).join(','); } else { - const { color, opacity, letter } = data; - return `${color}/${opacity}/${letter}`; + const { color, letter } = data; + return `${color}/${letter}`; } } @@ -49,9 +49,9 @@ class DecorationRule { } private _appendForOne(data: IDecorationData, element: HTMLStyleElement, theme: ITheme): void { - const { color, opacity, letter } = data; + const { color, letter } = data; // label - createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); + createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'};`, element); createCSSRule(`.focused .selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); // badge if (letter) { @@ -62,8 +62,8 @@ class DecorationRule { private _appendForMany(data: IDecorationData[], element: HTMLStyleElement, theme: ITheme): void { // label - const { color, opacity } = data[0]; - createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'}; opacity: ${opacity || 1};`, element); + const { color } = data[0]; + createCSSRule(`.${this.labelClassName}`, `color: ${theme.getColor(color) || 'inherit'};`, element); createCSSRule(`.focused .selected .${this.labelClassName}`, `color: inherit; opacity: inherit;`, element); // badge From 619e5f93bc8090765343416d7339a4812b8fd944 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 10:49:36 +0200 Subject: [PATCH 199/394] config context fixes --- src/vs/platform/contextkey/browser/contextKeyService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 032b7f49d77..a3109b1e2c8 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -69,9 +69,9 @@ class ConfigAwareContextValuesContainer extends Context { } private _onConfigurationUpdated(event: IConfigurationChangeEvent): void { - if (event.affectsConfiguration('config')) { - this._updateConfigurationContext(this._configurationService.getConfiguration()); - } + // if (event.affectsConfiguration('config')) { + this._updateConfigurationContext(this._configurationService.getConfiguration()); + // } } private _updateConfigurationContext(config: any) { From 993043440d1bbf257d5456e2bf561f728820f26f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 10:53:13 +0200 Subject: [PATCH 200/394] Send workspace configuration change event data to extension host --- .../configuration/common/configuration.ts | 9 +-- .../common/configurationModels.ts | 78 +++++++++---------- .../mainThreadConfiguration.ts | 16 +++- src/vs/workbench/api/node/extHost.protocol.ts | 9 ++- .../api/node/extHostConfiguration.ts | 22 +++++- .../common/configurationModels.ts | 29 +++---- 6 files changed, 85 insertions(+), 78 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 41093f27f8a..9da18eb08a4 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -12,6 +12,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { StrictResourceMap } from 'vs/base/common/map'; export const IConfigurationService = createDecorator('configurationService'); @@ -45,7 +46,8 @@ export interface IConfigurationChangeEvent { sourceConfig: any; // Following data is used for Extension host configuration event - toJSON(): IConfigurationChangeEventData; + changedConfiguration: IConfiguraionModel; + changedConfigurationByResource: StrictResourceMap; } export interface IConfigurationService { @@ -106,11 +108,6 @@ export interface IConfigurationData { folders: { [folder: string]: IConfiguraionModel }; } -export interface IConfigurationChangeEventData { - changedConfiguration: IConfiguraionModel; - changedConfigurationByResource: { [folder: string]: IConfiguraionModel }; -} - export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { added: string[], removed: string[], updated: string[] } { const added = to.keys.filter(key => from.keys.indexOf(key) === -1); const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index c58669e9dec..3ce3d66a3cd 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -11,7 +11,7 @@ import * as objects from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; +import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree } from 'vs/platform/configuration/common/configuration'; import { Workspace } from 'vs/platform/workspace/common/workspace'; export class ConfigurationModel implements IConfiguraionModel { @@ -133,6 +133,14 @@ export class ConfigurationModel implements IConfiguraionModel { } return false; } + + toJSON(): IConfiguraionModel { + return { + contents: this.contents, + overrides: this.overrides, + keys: this.keys + }; + } } export class DefaultConfigurationModel extends ConfigurationModel { @@ -493,19 +501,12 @@ export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChange return this._changedConfiguration; } - affectsConfiguration(config: string, resource?: URI): boolean { - return this.doesConfigurationContains(this.changedConfiguration, config); + get changedConfigurationByResource(): StrictResourceMap { + return new StrictResourceMap(); } - toJSON(): IConfigurationChangeEventData { - return { - changedConfiguration: { - contents: this.changedConfiguration.contents, - overrides: this.changedConfiguration.overrides, - keys: this.changedConfiguration.keys - }, - changedConfigurationByResource: Object.create({}) - }; + affectsConfiguration(config: string, resource?: URI): boolean { + return this.doesConfigurationContains(this.changedConfiguration, config); } } @@ -515,21 +516,28 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i private _sourceConfig: any; constructor( - private changedConfiguration: ConfigurationModel = new ConfigurationModel(), - private resources: URI[] = [], - private changedConfigurationByResource: StrictResourceMap = new StrictResourceMap()) { + private _changedConfiguration: ConfigurationModel = new ConfigurationModel(), + private _changedConfigurationByResource: StrictResourceMap = new StrictResourceMap()) { super(); } + get changedConfiguration(): IConfiguraionModel { + return this._changedConfiguration; + } + + get changedConfigurationByResource(): StrictResourceMap { + return this._changedConfigurationByResource; + } + change(event: ConfigurationChangeEvent): ConfigurationChangeEvent change(keys: string[], resource?: URI): ConfigurationChangeEvent change(arg1: any, arg2?: any): ConfigurationChangeEvent { if (arg1 instanceof ConfigurationChangeEvent) { - this.changedConfiguration = this.changedConfiguration.merge(arg1.changedConfiguration); - for (const resource of arg1.resources) { + this._changedConfiguration = this._changedConfiguration.merge(arg1._changedConfiguration); + for (const resource of this.changedConfigurationByResource.keys()) { let changedConfigurationByResource = this.getOrSetChangedConfigurationForResource(resource); - changedConfigurationByResource = changedConfigurationByResource.merge(arg1.changedConfigurationByResource.get(resource)); - this.changedConfigurationByResource.set(resource, changedConfigurationByResource); + changedConfigurationByResource = changedConfigurationByResource.merge(arg1._changedConfigurationByResource.get(resource)); + this._changedConfigurationByResource.set(resource, changedConfigurationByResource); } } this.changeWithKeys(arg1, arg2); @@ -543,8 +551,8 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i } get affectedKeys(): string[] { - const keys = [...this.changedConfiguration.keys]; - this.changedConfigurationByResource.forEach(model => keys.push(...model.keys)); + const keys = [...this._changedConfiguration.keys]; + this._changedConfigurationByResource.forEach(model => keys.push(...model.keys)); return keys; } @@ -557,15 +565,15 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i } affectsConfiguration(config: string, resource?: URI): boolean { - let configurationModelsToSearch: ConfigurationModel[] = [this.changedConfiguration]; + let configurationModelsToSearch: ConfigurationModel[] = [this._changedConfiguration]; if (resource) { - let model = this.changedConfigurationByResource.get(resource); + let model = this._changedConfigurationByResource.get(resource); if (model) { configurationModelsToSearch.push(model); } } else { - configurationModelsToSearch.push(...this.changedConfigurationByResource.values()); + configurationModelsToSearch.push(...this._changedConfigurationByResource.values()); } for (const configuration of configurationModelsToSearch) { @@ -578,32 +586,16 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i } private changeWithKeys(keys: string[], resource?: URI): void { - let changedConfiguration = resource ? this.getOrSetChangedConfigurationForResource(resource) : this.changedConfiguration; + let changedConfiguration = resource ? this.getOrSetChangedConfigurationForResource(resource) : this._changedConfiguration; this.updateKeys(changedConfiguration, keys); } private getOrSetChangedConfigurationForResource(resource: URI): ConfigurationModel { - let changedConfigurationByResource = this.changedConfigurationByResource.get(resource); + let changedConfigurationByResource = this._changedConfigurationByResource.get(resource); if (!changedConfigurationByResource) { changedConfigurationByResource = new ConfigurationModel(); - this.changedConfigurationByResource.set(resource, changedConfigurationByResource); - this.resources.push(resource); + this._changedConfigurationByResource.set(resource, changedConfigurationByResource); } return changedConfigurationByResource; } - - toJSON(): IConfigurationChangeEventData { - return { - changedConfiguration: { - contents: this.changedConfiguration.contents, - overrides: this.changedConfiguration.overrides, - keys: this.changedConfiguration.keys - }, - changedConfigurationByResource: this.changedConfigurationByResource.keys().reduce((result, resource) => { - const { contents, overrides, keys } = this.changedConfigurationByResource.get(resource); - result[resource.toString()] = { contents, overrides, keys }; - return result; - }, Object.create({})) - }; - } } \ No newline at end of file diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index af38672d4b8..5133d7125a9 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -11,9 +11,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext } from '../node/extHost.protocol'; +import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; @extHostNamedCustomer(MainContext.MainThreadConfiguration) export class MainThreadConfiguration implements MainThreadConfigurationShape { @@ -28,7 +28,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); this._configurationListener = configurationService.onDidChangeConfiguration(e => { - proxy.$acceptConfigurationChanged(configurationService.getConfigurationData(), e.toJSON()); + proxy.$acceptConfigurationChanged(configurationService.getConfigurationData(), this.toConfigurationChangeEventData(e)); }); } @@ -58,4 +58,14 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { } return ConfigurationTarget.WORKSPACE; } + + private toConfigurationChangeEventData(event: IConfigurationChangeEvent): IWorkspaceConfigurationChangeEventData { + return { + changedConfiguration: event.changedConfiguration, + changedConfigurationByResource: event.changedConfigurationByResource.keys().reduce((result, resource) => { + result[resource.toString()] = event.changedConfigurationByResource.get(resource); + return result; + }, Object.create({})) + }; + } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 2071ea617db..4320e059494 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -28,7 +28,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import { ITextSource } from 'vs/editor/common/model/textSource'; -import { IConfigurationData, ConfigurationTarget, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget, IConfiguraionModel } from 'vs/platform/configuration/common/configuration'; import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; @@ -77,6 +77,11 @@ export interface IInitData { telemetryInfo: ITelemetryInfo; } +export interface IWorkspaceConfigurationChangeEventData { + changedConfiguration: IConfiguraionModel; + changedConfigurationByResource: { [folder: string]: IConfiguraionModel }; +} + export interface IExtHostContext { /** * Returns a proxy to an object addressable/named in the extension host process. @@ -418,7 +423,7 @@ export interface ExtHostCommandsShape { } export interface ExtHostConfigurationShape { - $acceptConfigurationChanged(data: IConfigurationData, eventData: IConfigurationChangeEventData): void; + $acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData): void; } export interface ExtHostDiagnosticsShape { diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 5a8dae4f23a..fde9013ed78 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -9,10 +9,12 @@ import URI from 'vs/base/common/uri'; import Event, { Emitter } from 'vs/base/common/event'; import * as vscode from 'vscode'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; -import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol'; +import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData } from './extHost.protocol'; import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes'; -import { IConfigurationData, ConfigurationTarget, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; -import { Configuration } from 'vs/platform/configuration/common/configurationModels'; +import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { Configuration, ConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; +import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; +import { StrictResourceMap } from 'vs/base/common/map'; function lookUp(tree: any, key: string) { if (key) { @@ -50,7 +52,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event; } - $acceptConfigurationChanged(data: IConfigurationData, eventData: IConfigurationChangeEventData) { + $acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) { this._configuration = Configuration.parse(data, this._extHostWorkspace.workspace); this._onDidChangeConfiguration.fire(undefined); } @@ -117,4 +119,16 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return Object.freeze(result); } + + protected toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): WorkspaceConfigurationChangeEvent { + const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides); + const changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); + for (const key of Object.keys(data.changedConfigurationByResource)) { + const resource = URI.parse(key); + const model = data.changedConfigurationByResource[key]; + changedConfigurationByResource.set(resource, new ConfigurationModel(model.contents, model.keys, model.overrides)); + } + const event = new ConfigurationChangeEvent(changedConfiguration, changedConfigurationByResource); + return new WorkspaceConfigurationChangeEvent(event, this._extHostWorkspace.workspace); + } } diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 3cef3209dfe..fb32e490494 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationChangeEventData } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfiguraionModel } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -270,7 +270,14 @@ export class Configuration extends BaseConfiguration { export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent { - constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace) { + constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace) { } + + get changedConfiguration(): IConfiguraionModel { + return this.configurationChangeEvent.changedConfiguration; + } + + get changedConfigurationByResource(): StrictResourceMap { + return this.configurationChangeEvent.changedConfigurationByResource; } get affectedKeys(): string[] { @@ -299,22 +306,4 @@ export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEv return false; } - - toJSON(): IConfigurationChangeEventData { - return this.configurationChangeEvent.toJSON(); - } - - public static parse(data: IConfigurationChangeEventData, workspace: Workspace): WorkspaceConfigurationChangeEvent { - const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides); - const resources: URI[] = []; - const changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); - for (const key of Object.keys(data.changedConfigurationByResource)) { - const resource = URI.parse(key); - const model = data.changedConfigurationByResource[key]; - resources.push(resource); - changedConfigurationByResource.set(resource, new ConfigurationModel(model.contents, model.keys, model.overrides)); - } - const event = new ConfigurationChangeEvent(changedConfiguration, resources, changedConfigurationByResource); - return new WorkspaceConfigurationChangeEvent(event, workspace); - } } \ No newline at end of file From 1fbd298cdc594e772be21ab717b6cd279908e525 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 11:00:16 +0200 Subject: [PATCH 201/394] fix tests --- .../services/textfile/test/textFileService.test.ts | 4 ++-- src/vs/workbench/test/workbenchTestServices.ts | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/textfile/test/textFileService.test.ts b/src/vs/workbench/services/textfile/test/textFileService.test.ts index 777b42a5b71..38b5749c179 100644 --- a/src/vs/workbench/services/textfile/test/textFileService.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileService.test.ts @@ -19,7 +19,7 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel'; import { HotExitConfiguration } from 'vs/platform/files/common/files'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace'; class ServiceAccessor { constructor( @@ -380,7 +380,7 @@ suite('Files - TextFileService', () => { service.onConfigurationChange({ files: { hotExit: setting } }); // Set empty workspace if required if (!workspace) { - accessor.contextService.setWorkspace(null); + accessor.contextService.setWorkspace(new Workspace('empty:1508317022751')); } // Set multiple windows if required if (multipleWindows) { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 8bfdf7f0f46..b4d7d8cf3df 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -102,12 +102,14 @@ export class TestContextService implements IWorkspaceContextService { } public getWorkbenchState(): WorkbenchState { - if (this.workspace) { - if (this.workspace.configuration) { - return WorkbenchState.WORKSPACE; - } + if (this.workspace.configuration) { + return WorkbenchState.WORKSPACE; + } + + if (this.workspace.folders.length) { return WorkbenchState.FOLDER; } + return WorkbenchState.EMPTY; } From 9c97b8002db556b0e8d2cf1b7df362356e8f585e Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Oct 2017 11:05:00 +0200 Subject: [PATCH 202/394] debug: decodeURI before sending it out to adapter fixes #36471 --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 2b5446c6602..d3d1386f87f 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -1119,7 +1119,8 @@ export class DebugService implements debug.IDebugService { const breakpointsToSend = this.model.getBreakpoints().filter(bp => this.model.areBreakpointsActivated() && bp.enabled && bp.uri.toString() === modelUri.toString()); const source = process.sources.get(modelUri.toString()); - const rawSource = source ? source.raw : { path: modelUri.scheme === 'file' || modelUri.scheme === debug.DEBUG_SCHEME ? paths.normalize(modelUri.fsPath, true) : modelUri.toString(), name: resources.basenameOrAuthority(modelUri) }; + const path = modelUri.scheme === 'file' || modelUri.scheme === debug.DEBUG_SCHEME ? paths.normalize(modelUri.fsPath, true) : modelUri.toString(); + const rawSource = source ? source.raw : { path: decodeURIComponent(path), name: resources.basenameOrAuthority(modelUri) }; if (breakpointsToSend.length && !rawSource.adapterData) { rawSource.adapterData = breakpointsToSend[0].adapterData; } From d4b5e8a7cd90112aaa463fb2f4cbba8f05220bf0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 11:25:01 +0200 Subject: [PATCH 203/394] context - more precise config change event listening --- .../contextkey/browser/contextKeyService.ts | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index a3109b1e2c8..f12ad44deeb 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -8,7 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver'; import { IContextKey, IContext, IContextKeyServiceTarget, IContextKeyService, SET_CONTEXT_COMMAND_ID, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import Event, { Emitter, debounceEvent } from 'vs/base/common/event'; const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context'; @@ -51,17 +51,17 @@ export class Context implements IContext { class ConfigAwareContextValuesContainer extends Context { - private _emitter: Emitter; - private _subscription: IDisposable; - private _configurationService: IConfigurationService; + private readonly _emitter: Emitter; + private readonly _subscription: IDisposable; + private readonly _configurationService: IConfigurationService; constructor(id: number, configurationService: IConfigurationService, emitter: Emitter) { super(id, null); this._emitter = emitter; this._configurationService = configurationService; - this._subscription = configurationService.onDidChangeConfiguration(e => this._onConfigurationUpdated(e)); - this._updateConfigurationContext(configurationService.getConfiguration()); + this._subscription = configurationService.onDidChangeConfiguration(this._onConfigurationUpdated, this); + this._initFromConfiguration(); } public dispose() { @@ -69,12 +69,24 @@ class ConfigAwareContextValuesContainer extends Context { } private _onConfigurationUpdated(event: IConfigurationChangeEvent): void { - // if (event.affectsConfiguration('config')) { - this._updateConfigurationContext(this._configurationService.getConfiguration()); - // } + if (event.source === ConfigurationTarget.DEFAULT) { + // new setting, rebuild everything + this._initFromConfiguration(); + } else { + // update those that we know + for (const configKey of event.affectedKeys) { + const contextKey = `config.${configKey}`; + if (contextKey in this._value) { + this._value[contextKey] = this._configurationService.getValue(configKey); + this._emitter.fire(configKey); + } + } + } } - private _updateConfigurationContext(config: any) { + private _initFromConfiguration() { + + const config = this._configurationService.getConfiguration(); // remove old config.xyz values for (let key in this._value) { From e6e9092fb67a4540fa7c3bf7a29807f14c2c0023 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 11:28:42 +0200 Subject: [PATCH 204/394] fix layering rules in workbench services --- src/vs/workbench/electron-browser/shell.ts | 2 +- .../{common => node}/workspaceStats.ts | 0 .../telemetry/test/workspaceStats.test.ts | 2 +- tslint.json | 47 +++++++++++++++++-- 4 files changed, 44 insertions(+), 7 deletions(-) rename src/vs/workbench/services/telemetry/{common => node}/workspaceStats.ts (100%) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 0430727fa3e..44543f77bd1 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -31,7 +31,7 @@ import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; import { ElectronWindow } from 'vs/workbench/electron-browser/window'; import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties'; import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties'; -import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats'; +import { WorkspaceStats } from 'vs/workbench/services/telemetry/node/workspaceStats'; import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { WindowService } from 'vs/platform/windows/electron-browser/windowService'; import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService'; diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/node/workspaceStats.ts similarity index 100% rename from src/vs/workbench/services/telemetry/common/workspaceStats.ts rename to src/vs/workbench/services/telemetry/node/workspaceStats.ts diff --git a/src/vs/workbench/services/telemetry/test/workspaceStats.test.ts b/src/vs/workbench/services/telemetry/test/workspaceStats.test.ts index 5647af87623..7bb6e7d3d8f 100644 --- a/src/vs/workbench/services/telemetry/test/workspaceStats.test.ts +++ b/src/vs/workbench/services/telemetry/test/workspaceStats.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import * as crypto from 'crypto'; -import { getDomainsOfRemotes, getRemotes, getHashedRemotes } from 'vs/workbench/services/telemetry/common/workspaceStats'; +import { getDomainsOfRemotes, getRemotes, getHashedRemotes } from 'vs/workbench/services/telemetry/node/workspaceStats'; function hash(value: string): string { return crypto.createHash('sha1').update(value.toString()).digest('hex'); diff --git a/tslint.json b/tslint.json index d4df6618424..1264f2b5cf0 100644 --- a/tslint.json +++ b/tslint.json @@ -348,15 +348,52 @@ ] }, { - "target": "**/vs/workbench/services/**", + "target": "**/vs/workbench/services/**/common/**", "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/**", - "**/vs/platform/**", - "**/vs/editor/**", + "**/vs/base/**/common/**", + "**/vs/platform/**/common/**", + "**/vs/editor/common/**", + "**/vs/workbench/common/**", + "**/vs/workbench/services/**/common/**" + ] + }, + { + "target": "**/vs/workbench/services/**/browser/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/**/{common,browser}/**", + "**/vs/platform/**/{common,browser}/**", + "**/vs/editor/{common,browser}/**", + "**/vs/workbench/{common,browser}/**", + "**/vs/workbench/services/**/{common,browser}/**" + ] + }, + { + "target": "**/vs/workbench/services/**/node/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/**/{common,node}/**", + "**/vs/platform/**/{common,node}/**", + "**/vs/editor/{common,node}/**", + "**/vs/workbench/{common,node}/**", + "**/vs/workbench/services/**/{common,node}/**", + "*" // node modules + ] + }, + { + "target": "**/vs/workbench/services/**/electron-browser/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/**/{common,browser,node,electron-browser}/**", + "**/vs/platform/**/{common,browser,node,electron-browser}/**", + "**/vs/editor/**/{common,browser,node,electron-browser}/**", "**/vs/workbench/{common,browser,node,electron-browser,api}/**", - "**/vs/workbench/services/**", + "**/vs/workbench/services/**/{common,browser,node,electron-browser}/**", "*" // node modules ] }, From 3b960a89e3699eda006bda226c8805e3add584d1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 11:39:37 +0200 Subject: [PATCH 205/394] telemetry - add a workspace ID tag to workspace stats --- .../services/telemetry/node/workspaceStats.ts | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/telemetry/node/workspaceStats.ts b/src/vs/workbench/services/telemetry/node/workspaceStats.ts index 9275928cd44..e81862ca195 100644 --- a/src/vs/workbench/services/telemetry/node/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/node/workspaceStats.ts @@ -36,7 +36,7 @@ const SecondLevelDomainWhitelist = [ 'google.com' ]; -type Tags = { [index: string]: boolean | number }; +type Tags = { [index: string]: boolean | number | string }; function stripLowLevelDomains(domain: string): string { let match = domain.match(SecondLevelDomainMatcher); @@ -149,6 +149,7 @@ export class WorkspaceStats { "workbench.filesToOpen" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "workbench.filesToCreate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "workbench.filesToDiff" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "workspace.id" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "workspace.roots" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "workspace.empty" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "workspace.grunt" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, @@ -175,13 +176,29 @@ export class WorkspaceStats { private getWorkspaceTags(configuration: IWindowConfiguration): TPromise { const tags: Tags = Object.create(null); + const state = this.contextService.getWorkbenchState(); + const workspace = this.contextService.getWorkspace(); + + let workspaceId: string; + switch (state) { + case WorkbenchState.EMPTY: + workspaceId = void 0; + break; + case WorkbenchState.FOLDER: + workspaceId = crypto.createHash('sha1').update(workspace.folders[0].uri.fsPath).digest('hex'); + break; + case WorkbenchState.WORKSPACE: + workspaceId = crypto.createHash('sha1').update(workspace.configuration.fsPath).digest('hex'); + } + + tags['workspace.id'] = workspaceId; + const { filesToOpen, filesToCreate, filesToDiff } = configuration; tags['workbench.filesToOpen'] = filesToOpen && filesToOpen.length || 0; tags['workbench.filesToCreate'] = filesToCreate && filesToCreate.length || 0; tags['workbench.filesToDiff'] = filesToDiff && filesToDiff.length || 0; - const isEmpty = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; - const workspace = this.contextService.getWorkspace(); + const isEmpty = state === WorkbenchState.EMPTY; tags['workspace.roots'] = isEmpty ? 0 : workspace.folders.length; tags['workspace.empty'] = isEmpty; From 44bd7e3176fa9b9f1572429812a7c64d938d9136 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 11:44:45 +0200 Subject: [PATCH 206/394] deco - don't check for ignored files outside the repo --- extensions/git/src/decorationProvider.ts | 1 + extensions/git/src/repository.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 44789b518b5..813a035b519 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -55,6 +55,7 @@ class GitIgnoreDecorationProvider implements DecorationProvider { value.resolve(ignoreSet.has(key)); } }, err => { + console.error(err); for (const [, value] of queue.entries()) { value.reject(err); } diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index ccd92bf005f..6e16bf9d44c 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -6,7 +6,7 @@ 'use strict'; import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData } from 'vscode'; -import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType } from './git'; +import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError } from './git'; import { anyEvent, filterEvent, eventToPromise, dispose, find } from './util'; import { memoize, throttle, debounce } from './decorators'; import { toGitUri } from './uri'; @@ -648,6 +648,8 @@ export class Repository implements Disposable { return this.run(Operation.Ignore, () => { return new Promise>((resolve, reject) => { + filePaths = filePaths.filter(filePath => !path.relative(this.root, filePath).startsWith('..')); + const child = this.repository.stream(['check-ignore', ...filePaths]); const onExit = exitCode => { @@ -658,7 +660,7 @@ export class Repository implements Disposable { // each line is something ignored resolve(new Set(data.split('\n'))); } else { - reject(); + reject(new GitError({ stdout: data, stderr, exitCode })); } }; @@ -670,9 +672,9 @@ export class Repository implements Disposable { child.stdout.setEncoding('utf8'); child.stdout.on('data', onStdoutData); - // const stderrData: string[] = []; - // child.stderr.setEncoding('utf8'); - // child.stderr.on('data', raw => stderrData.push(raw as string)); + let stderr: string = ''; + child.stderr.setEncoding('utf8'); + child.stderr.on('data', raw => stderr += raw); child.on('error', reject); child.on('exit', onExit); From 104a4d1bb64111c0a6a56d06f987372829beb089 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 11:56:59 +0200 Subject: [PATCH 207/394] :lipstick: --- .../telemetry/common/telemetryUtils.ts | 31 ++----------------- .../common/editor/resourceEditorInput.ts | 6 ++-- .../common/editor/untitledEditorInput.ts | 6 ++-- src/vs/workbench/electron-browser/shell.ts | 5 +++ .../files/common/editors/fileEditorInput.ts | 6 ++-- .../workbench/parts/html/common/htmlInput.ts | 6 ++-- .../preferences/browser/preferencesEditor.ts | 6 ++-- .../walkThrough/node/walkThroughInput.ts | 6 ++-- .../services/hash/common/hashService.ts | 19 ++++++++++++ .../services/hash/node/hashService.ts | 18 +++++++++++ .../test/node/keybindingEditing.test.ts | 4 ++- .../textfile/common/textFileEditorModel.ts | 5 +-- .../workbench/test/workbenchTestServices.ts | 10 ++++++ 13 files changed, 84 insertions(+), 44 deletions(-) create mode 100644 src/vs/workbench/services/hash/common/hashService.ts create mode 100644 src/vs/workbench/services/hash/node/hashService.ts diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 4f177bbb2e2..904d9602127 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -39,33 +39,6 @@ export function combinedAppender(...appenders: ITelemetryAppender[]): ITelemetry export const NullAppender: ITelemetryAppender = { log: () => null }; -// --- util - -export function anonymize(input: string): string { - if (!input) { - return input; - } - - let r = ''; - for (let i = 0; i < input.length; i++) { - let ch = input[i]; - if (ch >= '0' && ch <= '9') { - r += '0'; - continue; - } - if (ch >= 'a' && ch <= 'z') { - r += 'a'; - continue; - } - if (ch >= 'A' && ch <= 'Z') { - r += 'A'; - continue; - } - r += ch; - } - return r; -} - /* __GDPR__FRAGMENT__ "URIDescriptor" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, @@ -79,9 +52,9 @@ export interface URIDescriptor { path?: string; } -export function telemetryURIDescriptor(uri: URI): URIDescriptor { +export function telemetryURIDescriptor(uri: URI, hashPath: (path: string) => string): URIDescriptor { const fsPath = uri && uri.fsPath; - return fsPath ? { mimeType: guessMimeTypes(fsPath).join(', '), ext: paths.extname(fsPath), path: anonymize(fsPath) } : {}; + return fsPath ? { mimeType: guessMimeTypes(fsPath).join(', '), ext: paths.extname(fsPath), path: hashPath(fsPath) } : {}; } /** diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index ea19725e484..4f9a57314ec 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -11,6 +11,7 @@ import { IReference } from 'vs/base/common/lifecycle'; import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * A read-only text editor input whos contents are made of the provided resource that points to an existing @@ -29,7 +30,8 @@ export class ResourceEditorInput extends EditorInput { name: string, description: string, resource: URI, - @ITextModelService private textModelResolverService: ITextModelService + @ITextModelService private textModelResolverService: ITextModelService, + @IHashService private hashService: IHashService ) { super(); @@ -70,7 +72,7 @@ export class ResourceEditorInput extends EditorInput { public getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); - descriptor['resource'] = telemetryURIDescriptor(this.resource); + descriptor['resource'] = telemetryURIDescriptor(this.resource, path => this.hashService.createSHA1(path)); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 8057bef0160..45092f33e98 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -22,6 +22,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { Verbosity } from 'vs/platform/editor/common/editor'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * An editor input to be used for untitled text buffers. @@ -48,7 +49,8 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport @IInstantiationService private instantiationService: IInstantiationService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextFileService private textFileService: ITextFileService, - @IEnvironmentService private environmentService: IEnvironmentService + @IEnvironmentService private environmentService: IEnvironmentService, + @IHashService private hashService: IHashService ) { super(); @@ -252,7 +254,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport public getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); - descriptor['resource'] = telemetryURIDescriptor(this.getResource()); + descriptor['resource'] = telemetryURIDescriptor(this.getResource(), path => this.hashService.createSHA1(path)); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 44543f77bd1..b0a9dff094c 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -91,6 +91,8 @@ import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollba import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax'; import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService'; import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService'; +import { HashService } from 'vs/workbench/services/hash/node/hashService'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * Services that we require for the Shell @@ -293,6 +295,9 @@ export class WorkbenchShell { restoreFontInfo(this.storageService); readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel())); + // Hash + serviceCollection.set(IHashService, new SyncDescriptor(HashService)); + // Experiments this.experimentService = instantiationService.createInstance(ExperimentService); serviceCollection.set(IExperimentService, this.experimentService); diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts index f84e67a1176..c6ac6973969 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts @@ -24,6 +24,7 @@ import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUt import { Verbosity } from 'vs/platform/editor/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * A file editor input is the input type for the file editor of file system resources. @@ -47,7 +48,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextFileService private textFileService: ITextFileService, @IEnvironmentService private environmentService: IEnvironmentService, - @ITextModelService private textModelResolverService: ITextModelService + @ITextModelService private textModelResolverService: ITextModelService, + @IHashService private hashService: IHashService ) { super(); @@ -274,7 +276,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { public getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); - descriptor['resource'] = telemetryURIDescriptor(this.getResource()); + descriptor['resource'] = telemetryURIDescriptor(this.getResource(), path => this.hashService.createSHA1(path)); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { diff --git a/src/vs/workbench/parts/html/common/htmlInput.ts b/src/vs/workbench/parts/html/common/htmlInput.ts index fe8955dc0c7..8338d4fd5b6 100644 --- a/src/vs/workbench/parts/html/common/htmlInput.ts +++ b/src/vs/workbench/parts/html/common/htmlInput.ts @@ -7,6 +7,7 @@ import URI from 'vs/base/common/uri'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export interface HtmlInputOptions { @@ -25,8 +26,9 @@ export class HtmlInput extends ResourceEditorInput { description: string, resource: URI, public readonly options: HtmlInputOptions, - @ITextModelService textModelResolverService: ITextModelService + @ITextModelService textModelResolverService: ITextModelService, + @IHashService hashService: IHashService ) { - super(name, description, resource, textModelResolverService); + super(name, description, resource, textModelResolverService, hashService); } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 44875020629..910dcb09831 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -59,6 +59,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { MessageController } from 'vs/editor/contrib/message/messageController'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export class PreferencesEditorInput extends SideBySideEditorInput { public static ID: string = 'workbench.editorinputs.preferencesEditorInput'; @@ -75,9 +76,10 @@ export class PreferencesEditorInput extends SideBySideEditorInput { export class DefaultPreferencesEditorInput extends ResourceEditorInput { public static ID = 'workbench.editorinputs.defaultpreferences'; constructor(defaultSettingsResource: URI, - @ITextModelService textModelResolverService: ITextModelService + @ITextModelService textModelResolverService: ITextModelService, + @IHashService hashService: IHashService ) { - super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService); + super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService, hashService); } getTypeId(): string { diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts index 98a5ffc7c8d..a534a77b13b 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts @@ -15,6 +15,7 @@ import { marked } from 'vs/base/common/marked/marked'; import { Schemas } from 'vs/base/common/network'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export class WalkThroughModel extends EditorModel { @@ -63,7 +64,8 @@ export class WalkThroughInput extends EditorInput { private options: WalkThroughInputOptions, @ITelemetryService private telemetryService: ITelemetryService, @ILifecycleService lifecycleService: ILifecycleService, - @ITextModelService private textModelResolverService: ITextModelService + @ITextModelService private textModelResolverService: ITextModelService, + @IHashService private hashService: IHashService ) { super(); this.disposables.push(lifecycleService.onShutdown(e => this.disposeTelemetry(e))); @@ -92,7 +94,7 @@ export class WalkThroughInput extends EditorInput { getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); descriptor['target'] = this.getTelemetryFrom(); - descriptor['resource'] = telemetryURIDescriptor(this.options.resource); + descriptor['resource'] = telemetryURIDescriptor(this.options.resource, path => this.hashService.createSHA1(path)); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { "target" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, diff --git a/src/vs/workbench/services/hash/common/hashService.ts b/src/vs/workbench/services/hash/common/hashService.ts new file mode 100644 index 00000000000..e8e2ee18d9d --- /dev/null +++ b/src/vs/workbench/services/hash/common/hashService.ts @@ -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. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const IHashService = createDecorator('hashService'); + +export interface IHashService { + _serviceBrand: any; + + /** + * Produce a SHA1 hash of the provided content. + */ + createSHA1(content: string): string; +} \ No newline at end of file diff --git a/src/vs/workbench/services/hash/node/hashService.ts b/src/vs/workbench/services/hash/node/hashService.ts new file mode 100644 index 00000000000..fec0cab111f --- /dev/null +++ b/src/vs/workbench/services/hash/node/hashService.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { createHash } from 'crypto'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; + +export class HashService implements IHashService { + + _serviceBrand: any; + + public createSHA1(content: string): string { + return createHash('sha1').update(content).digest('hex'); + } +} \ No newline at end of file diff --git a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts index 6f003bde491..a3f9d2f1c0f 100644 --- a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts @@ -16,7 +16,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { KeyCode, SimpleKeybinding, ChordKeybinding } from 'vs/base/common/keyCodes'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import extfs = require('vs/base/node/extfs'); -import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices'; +import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService, TestHashService } from 'vs/workbench/test/workbenchTestServices'; import { IWorkspaceContextService, Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import uuid = require('vs/base/common/uuid'); import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; @@ -42,6 +42,7 @@ import { KeybindingsEditingService } from 'vs/workbench/services/keybinding/comm import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; interface Modifiers { metaKey?: boolean; @@ -70,6 +71,7 @@ suite('Keybindings Editing', () => { instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', () => { }); instantiationService.stub(IWorkspaceContextService, new TestContextService()); instantiationService.stub(ILifecycleService, new TestLifecycleService()); + instantiationService.stub(IHashService, new TestHashService()); instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(IModeService, ModeServiceImpl); diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 10cc2553f19..6c3cd249763 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -31,9 +31,9 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { anonymize } from 'vs/platform/telemetry/common/telemetryUtils'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IRawTextSource } from 'vs/editor/common/model/textSource'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * The text file editor model listens to changes to its underlying code editor model and saves these changes through the file service back to the disk. @@ -87,6 +87,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil @IBackupFileService private backupFileService: IBackupFileService, @IEnvironmentService private environmentService: IEnvironmentService, @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IHashService private hashService: IHashService ) { super(modelService, modeService); @@ -380,7 +381,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); + this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) }); } return model; diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index b4d7d8cf3df..5a105e010f7 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -59,6 +59,7 @@ import { IRecentlyOpened } from 'vs/platform/history/common/history'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IPosition } from 'vs/editor/common/core/position'; import { ICommandAction } from 'vs/platform/actions/common/actions'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, void 0); @@ -259,6 +260,7 @@ export function workbenchInstantiationService(): IInstantiationService { instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); instantiationService.stub(IEnvironmentService, TestEnvironmentService); instantiationService.stub(IThemeService, new TestThemeService()); + instantiationService.stub(IHashService, new TestHashService()); return instantiationService; } @@ -1223,4 +1225,12 @@ export class TestTextResourceConfigurationService implements ITextResourceConfig public getConfiguration(resource: any, position?: any, section?: any): any { return this.configurationService.getConfiguration(section, { resource }); } +} + +export class TestHashService implements IHashService { + _serviceBrand: any; + + createSHA1(content: string): string { + return content; + } } \ No newline at end of file From 91b9b413074d5b0d8fda330ba5c1ffb26e9d53d5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 11:57:32 +0200 Subject: [PATCH 208/394] Check for workspace existence - Extension host will not contain workspace object in empty workspace scenario --- .../services/configuration/common/configurationModels.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index fb32e490494..27c03b4821d 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -297,7 +297,7 @@ export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEv return true; } - if (resource) { + if (resource && this.workspace) { let workspaceFolder = this.workspace.getFolder(resource); if (workspaceFolder) { return this.configurationChangeEvent.affectsConfiguration(config, workspaceFolder.uri); From fd42d99117ad42239c90eb24ccf057e258926778 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 11:58:50 +0200 Subject: [PATCH 209/394] :lipstick: --- .../configuration/common/configuration.ts | 20 +++++++++---------- .../common/configurationModels.ts | 14 ++++++------- src/vs/workbench/api/node/extHost.protocol.ts | 6 +++--- .../common/configurationModels.ts | 6 +++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 9da18eb08a4..0fb11cd76f5 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -37,17 +37,17 @@ export enum ConfigurationTarget { } export interface IConfigurationChangeEvent { - affectedKeys: string[]; + source: ConfigurationTarget; + affectedKeys: string[]; affectsConfiguration(configuration: string, resource?: URI): boolean; // Following data is used for telemetry - source: ConfigurationTarget; sourceConfig: any; // Following data is used for Extension host configuration event - changedConfiguration: IConfiguraionModel; - changedConfigurationByResource: StrictResourceMap; + changedConfiguration: IConfigurationModel; + changedConfigurationByResource: StrictResourceMap; } export interface IConfigurationService { @@ -90,7 +90,7 @@ export interface IConfigurationService { }; } -export interface IConfiguraionModel { +export interface IConfigurationModel { contents: any; keys: string[]; overrides: IOverrides[]; @@ -102,13 +102,13 @@ export interface IOverrides { } export interface IConfigurationData { - defaults: IConfiguraionModel; - user: IConfiguraionModel; - workspace: IConfiguraionModel; - folders: { [folder: string]: IConfiguraionModel }; + defaults: IConfigurationModel; + user: IConfigurationModel; + workspace: IConfigurationModel; + folders: { [folder: string]: IConfigurationModel }; } -export function compare(from: IConfiguraionModel, to: IConfiguraionModel): { added: string[], removed: string[], updated: string[] } { +export function compare(from: IConfigurationModel, to: IConfigurationModel): { added: string[], removed: string[], updated: string[] } { const added = to.keys.filter(key => from.keys.indexOf(key) === -1); const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); const updated = []; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 3ce3d66a3cd..56ec4b29832 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -11,10 +11,10 @@ import * as objects from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfiguraionModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree } from 'vs/platform/configuration/common/configuration'; +import { IOverrides, overrideIdentifierFromKey, addToValueTree, toValuesTree, IConfigurationModel, merge, getConfigurationValue, IConfigurationOverrides, IConfigurationData, getDefaultValues, getConfigurationKeys, IConfigurationChangeEvent, ConfigurationTarget, removeFromValueTree } from 'vs/platform/configuration/common/configuration'; import { Workspace } from 'vs/platform/workspace/common/workspace'; -export class ConfigurationModel implements IConfiguraionModel { +export class ConfigurationModel implements IConfigurationModel { constructor(protected _contents: any = {}, protected _keys: string[] = [], protected _overrides: IOverrides[] = []) { } @@ -134,7 +134,7 @@ export class ConfigurationModel implements IConfiguraionModel { return false; } - toJSON(): IConfiguraionModel { + toJSON(): IConfigurationModel { return { contents: this.contents, overrides: this.overrides, @@ -458,7 +458,7 @@ export class Configuration { return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap(), workspace); } - private static parseConfigurationModel(model: IConfiguraionModel): ConfigurationModel { + private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel { return new ConfigurationModel(model.contents, model.keys, model.overrides); } } @@ -501,7 +501,7 @@ export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChange return this._changedConfiguration; } - get changedConfigurationByResource(): StrictResourceMap { + get changedConfigurationByResource(): StrictResourceMap { return new StrictResourceMap(); } @@ -521,11 +521,11 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i super(); } - get changedConfiguration(): IConfiguraionModel { + get changedConfiguration(): IConfigurationModel { return this._changedConfiguration; } - get changedConfigurationByResource(): StrictResourceMap { + get changedConfigurationByResource(): StrictResourceMap { return this._changedConfigurationByResource; } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 4320e059494..a6c002ae30f 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -28,7 +28,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import { ITextSource } from 'vs/editor/common/model/textSource'; -import { IConfigurationData, ConfigurationTarget, IConfiguraionModel } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; @@ -78,8 +78,8 @@ export interface IInitData { } export interface IWorkspaceConfigurationChangeEventData { - changedConfiguration: IConfiguraionModel; - changedConfigurationByResource: { [folder: string]: IConfiguraionModel }; + changedConfiguration: IConfigurationModel; + changedConfigurationByResource: { [folder: string]: IConfigurationModel }; } export interface IExtHostContext { diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 27c03b4821d..69fd5bd628a 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfiguraionModel } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -272,11 +272,11 @@ export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEv constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace) { } - get changedConfiguration(): IConfiguraionModel { + get changedConfiguration(): IConfigurationModel { return this.configurationChangeEvent.changedConfiguration; } - get changedConfigurationByResource(): StrictResourceMap { + get changedConfigurationByResource(): StrictResourceMap { return this.configurationChangeEvent.changedConfigurationByResource; } From e988aa800b5467f940359140a33e67031ee808c6 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 12:02:55 +0200 Subject: [PATCH 210/394] fix #36336 --- src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts index 2b76c9e2540..3ab3d31ffe2 100644 --- a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts @@ -35,6 +35,8 @@ export class LightBulbWidget implements IDisposable, IContentWidget { this._editor = editor; this._editor.addContentWidget(this); + this._disposables.push(this._editor.onDidChangeModel(_ => this._futureFixes.cancel())); + this._disposables.push(this._editor.onDidChangeModelLanguage(_ => this._futureFixes.cancel())); this._disposables.push(dom.addStandardDisposableListener(this._domNode, 'click', e => { // a bit of extra work to make sure the menu // doesn't cover the line-text From 5f2427593099ade39c2aeec4c91038165a022ee2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 12:11:55 +0200 Subject: [PATCH 211/394] easy checks, #36427 --- .../workbench/parts/snippets/electron-browser/tabCompletion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts b/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts index dc7ac48b9b7..5784ed551bb 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts @@ -55,7 +55,7 @@ export class TabCompletionController implements editorCommon.IEditorContribution const prefix = getNonWhitespacePrefix(editor.getModel(), editor.getPosition()); selectFn = prefix && (snippet => endsWith(prefix, snippet.prefix)); - } else { + } else if (e.selection.startLineNumber === e.selection.endLineNumber && editor.getModel().getValueLengthInRange(e.selection) <= 100) { // actual selection -> snippet must be a full match const selected = editor.getModel().getValueInRange(e.selection); selectFn = snippet => selected === snippet.prefix; From ab6d82271b4daa3331b7719677b3381a1ac34cf5 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 12:12:48 +0200 Subject: [PATCH 212/394] smoke: comment out folding --- test/smoke/src/areas/editor/editor.test.ts | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index 3ceb7d6f0a4..72a537c4e23 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -34,21 +34,21 @@ describe('Editor', () => { await app.screenCapturer.capture('Rename result'); }); - it('folds/unfolds the code correctly', async function () { - await app.workbench.quickopen.openFile('www'); + // it('folds/unfolds the code correctly', async function () { + // await app.workbench.quickopen.openFile('www'); - // Fold - await app.workbench.editor.foldAtLine(3); - await app.workbench.editor.waitUntilShown(3); - await app.workbench.editor.waitUntilHidden(4); - await app.workbench.editor.waitUntilHidden(5); + // // Fold + // await app.workbench.editor.foldAtLine(3); + // await app.workbench.editor.waitUntilShown(3); + // await app.workbench.editor.waitUntilHidden(4); + // await app.workbench.editor.waitUntilHidden(5); - // Unfold - await app.workbench.editor.unfoldAtLine(3); - await app.workbench.editor.waitUntilShown(3); - await app.workbench.editor.waitUntilShown(4); - await app.workbench.editor.waitUntilShown(5); - }); + // // Unfold + // await app.workbench.editor.unfoldAtLine(3); + // await app.workbench.editor.waitUntilShown(3); + // await app.workbench.editor.waitUntilShown(4); + // await app.workbench.editor.waitUntilShown(5); + // }); it(`verifies that 'Go To Definition' works`, async function () { await app.workbench.quickopen.openFile('app.js'); From c9c409cb7b2487a3c97c95cc6302193785e8b640 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 12:15:18 +0200 Subject: [PATCH 213/394] deco - don't call check-ignore without files --- extensions/git/src/repository.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 6e16bf9d44c..8e8740f7b31 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -650,6 +650,11 @@ export class Repository implements Disposable { filePaths = filePaths.filter(filePath => !path.relative(this.root, filePath).startsWith('..')); + if (filePaths.length === 0) { + // nothing left + return Promise.resolve(new Set()); + } + const child = this.repository.stream(['check-ignore', ...filePaths]); const onExit = exitCode => { From a1fef89922a8a5d1b33f847f4533252c474c1eef Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 12:21:24 +0200 Subject: [PATCH 214/394] smoke: use pasteboard to edit editor --- test/smoke/src/areas/editor/editor.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 0a9a238c6f8..b69cfbacc4b 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -109,12 +109,8 @@ export class Editor { await this.spectron.client.waitForActiveElement(textarea); // https://github.com/Microsoft/vscode/issues/34203#issuecomment-334441786 - for (let i = 0; i < text.length; i++) { - this.spectron.client.spectron.client.keys([text[i], 'NULL']); - await new Promise(c => setTimeout(c, 50)); - } - - // this.spectron.client.spectron.client.keys([text, 'NULL']); + this.spectron.app.electron.clipboard.writeText(text); + this.spectron.app.webContents.paste(); await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } From 32d813e42e7972ff9df652b0e108f50731f4df79 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 12:28:42 +0200 Subject: [PATCH 215/394] Adopt to new configuration change event --- .../browser/parts/titlebar/titlebarPart.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 62741f2adfc..fd748603dc6 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -18,7 +18,7 @@ import * as errors from 'vs/base/common/errors'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { IAction, Action } from 'vs/base/common/actions'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IIntegrityService } from 'vs/platform/integrity/common/integrity'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; @@ -51,7 +51,6 @@ export class TitlebarPart extends Part implements ITitleService { private isInactive: boolean; - private titleTemplate: string; private isPure: boolean; private activeEditorListeners: IDisposable[]; @@ -81,9 +80,6 @@ export class TitlebarPart extends Part implements ITitleService { private init(): void { - // Read initial config - this.onConfigurationChanged(); - // Initial window title when loading is done this.partService.joinCreation().done(() => this.setTitle(this.getWindowTitle())); @@ -99,7 +95,7 @@ export class TitlebarPart extends Part implements ITitleService { private registerListeners(): void { this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.BLUR, () => this.onBlur())); this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.FOCUS, () => this.onFocus())); - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.onConfigurationChanged(true))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChanged(e))); this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.setTitle(this.getWindowTitle()))); this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(() => this.setTitle(this.getWindowTitle()))); @@ -116,11 +112,8 @@ export class TitlebarPart extends Part implements ITitleService { this.updateStyles(); } - private onConfigurationChanged(update?: boolean): void { - const currentTitleTemplate = this.titleTemplate; - this.titleTemplate = this.configurationService.getValue('window.title'); - - if (update && currentTitleTemplate !== this.titleTemplate) { + private onConfigurationChanged(event: IConfigurationChangeEvent): void { + if (event.affectsConfiguration('window.title')) { this.setTitle(this.getWindowTitle()); } } @@ -208,8 +201,9 @@ export class TitlebarPart extends Part implements ITitleService { const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; const appName = this.environmentService.appNameLong; const separator = TitlebarPart.TITLE_SEPARATOR; + const titleTemplate = this.configurationService.getValue('window.title'); - return labels.template(this.titleTemplate, { + return labels.template(titleTemplate, { activeEditorShort, activeEditorLong, activeEditorMedium, From 2a575a440778a0c094f1e2cb2f0db13ab0c039cb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 12:35:31 +0200 Subject: [PATCH 216/394] Adopt to new configuration change event --- .../browser/parts/editor/editorPart.ts | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 0899f3bd851..fead4e1c3b3 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -25,7 +25,7 @@ import { EditorInput, EditorOptions, ConfirmResult, IWorkbenchEditorConfiguratio import { EditorGroupsControl, Rochade, IEditorGroupsControl, ProgressState } from 'vs/workbench/browser/parts/editor/editorGroupsControl'; import { WorkbenchProgressService } from 'vs/workbench/services/progress/browser/progressService'; import { IEditorGroupService, GroupOrientation, GroupArrangement, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IEditorPart } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { Position, POSITIONS, Direction, IEditor } from 'vs/platform/editor/common/editor'; @@ -205,41 +205,45 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.toUnbind.push(this.stacks.onEditorClosed(event => this.onEditorClosed(event))); this.toUnbind.push(this.stacks.onGroupOpened(event => this.onEditorGroupOpenedOrClosed())); this.toUnbind.push(this.stacks.onGroupClosed(event => this.onEditorGroupOpenedOrClosed())); - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e))); } private onEditorGroupOpenedOrClosed(): void { this.updateStyles(); } - private onConfigurationUpdated(configuration: IWorkbenchEditorConfiguration): void { - if (configuration && configuration.workbench && configuration.workbench.editor) { - const editorConfig = configuration.workbench.editor; + private onConfigurationUpdated(event: IConfigurationChangeEvent): void { + if (event.affectsConfiguration('workbench.editor')) { + const configuration = this.configurationService.getConfiguration(); + if (configuration && configuration.workbench && configuration.workbench.editor) { + const editorConfig = configuration.workbench.editor; - // Pin all preview editors of the user chose to disable preview - const newPreviewEditors = editorConfig.enablePreview; - if (this.tabOptions.previewEditors !== newPreviewEditors && !newPreviewEditors) { - this.stacks.groups.forEach(group => { - if (group.previewEditor) { - this.pinEditor(group, group.previewEditor); - } - }); + + // Pin all preview editors of the user chose to disable preview + const newPreviewEditors = editorConfig.enablePreview; + if (this.tabOptions.previewEditors !== newPreviewEditors && !newPreviewEditors) { + this.stacks.groups.forEach(group => { + if (group.previewEditor) { + this.pinEditor(group, group.previewEditor); + } + }); + } + + const oldTabOptions = objects.clone(this.tabOptions); + this.tabOptions = { + previewEditors: newPreviewEditors, + showIcons: editorConfig.showIcons, + tabCloseButton: editorConfig.tabCloseButton, + showTabs: this.forceHideTabs ? false : editorConfig.showTabs, + labelFormat: editorConfig.labelFormat, + }; + + if (!this.doNotFireTabOptionsChanged && !objects.equals(oldTabOptions, this.tabOptions)) { + this._onTabOptionsChanged.fire(this.tabOptions); + } + + this.revealIfOpen = editorConfig.revealIfOpen; } - - const oldTabOptions = objects.clone(this.tabOptions); - this.tabOptions = { - previewEditors: newPreviewEditors, - showIcons: editorConfig.showIcons, - tabCloseButton: editorConfig.tabCloseButton, - showTabs: this.forceHideTabs ? false : editorConfig.showTabs, - labelFormat: editorConfig.labelFormat, - }; - - if (!this.doNotFireTabOptionsChanged && !objects.equals(oldTabOptions, this.tabOptions)) { - this._onTabOptionsChanged.fire(this.tabOptions); - } - - this.revealIfOpen = editorConfig.revealIfOpen; } } From 9d450132ff23ef07f315c9d4f8bdba65005b0c53 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 15:12:10 +0200 Subject: [PATCH 217/394] warn if windows-mutex can't be loaded fixes #36358 --- src/vs/code/electron-main/app.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index b2af39492b6..bb651dccb41 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -5,7 +5,7 @@ 'use strict'; -import { app, ipcMain as ipc, BrowserWindow } from 'electron'; +import { app, ipcMain as ipc, BrowserWindow, dialog } from 'electron'; import * as platform from 'vs/base/common/platform'; import { WindowsManager } from 'vs/code/electron-main/windows'; import { IWindowsService, OpenContext } from 'vs/platform/windows/common/windows'; @@ -379,7 +379,12 @@ export class CodeApplication { windowsMutex = new Mutex(product.win32MutexName); this.toDispose.push({ dispose: () => windowsMutex.release() }); } catch (e) { - // noop + if (!this.environmentService.isBuilt) { + dialog.showMessageBox({ + message: 'Module loading error', + detail: 'Could not load `windows-mutex`. Make sure you have it installed as a Code dependency.' + }); + } } } From bcfc11acc0f37a7f0552666441183e5ed2626f3d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 18 Oct 2017 15:14:37 +0200 Subject: [PATCH 218/394] uri - export UriComponents --- build/monaco/monaco.d.ts.recipe | 2 +- src/vs/base/common/uri.ts | 50 +++++++++++++++++++++------------ src/vs/monaco.d.ts | 14 +++++++-- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe index cdaee801a9c..da006b6bce4 100644 --- a/build/monaco/monaco.d.ts.recipe +++ b/build/monaco/monaco.d.ts.recipe @@ -34,7 +34,7 @@ declare module monaco { #include(vs/base/common/winjs.base.d.ts): TValueCallback, ProgressCallback, Promise #include(vs/base/common/cancellation): CancellationTokenSource, CancellationToken -#include(vs/base/common/uri): URI +#include(vs/base/common/uri): URI, UriComponents #include(vs/editor/common/standalone/standaloneBase): KeyCode, KeyMod #include(vs/base/common/htmlContent): IMarkdownString #include(vs/base/browser/keyboardEvent): IKeyboardEvent diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 921e34f3813..f6dcab7e786 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -73,7 +73,7 @@ const _driveLetter = /^[a-zA-Z]:/; * * */ -export default class URI { +export default class URI implements UriComponents { static isUri(thing: any): thing is URI { if (thing instanceof URI) { @@ -119,15 +119,35 @@ export default class URI { /** * @internal */ - protected constructor(scheme: string, authority: string, path: string, query: string, fragment: string) { + protected constructor(scheme: string, authority: string, path: string, query: string, fragment: string); - this.scheme = scheme || _empty; - this.authority = authority || _empty; - this.path = path || _empty; - this.query = query || _empty; - this.fragment = fragment || _empty; + /** + * @internal + */ + protected constructor(components: UriComponents); - _validateUri(this); + /** + * @internal + */ + protected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string) { + + if (typeof schemeOrData === 'object') { + this.scheme = schemeOrData.scheme || _empty; + this.authority = schemeOrData.authority || _empty; + this.path = schemeOrData.path || _empty; + this.query = schemeOrData.query || _empty; + this.fragment = schemeOrData.fragment || _empty; + // no validation because it's this URI + // that creates uri components. + // _validateUri(this); + } else { + this.scheme = schemeOrData || _empty; + this.authority = authority || _empty; + this.path = path || _empty; + this.query = query || _empty; + this.fragment = fragment || _empty; + _validateUri(this); + } } // ---- filesystem path ----------------------- @@ -264,7 +284,7 @@ export default class URI { return _asFormatted(this, skipEncoding); } - public toJSON(): any { + public toJSON(): object { const res = { $mid: 1, fsPath: this.fsPath, @@ -294,21 +314,15 @@ export default class URI { return res; } - static revive(data: any): URI { - let result = new _URI( - (data).scheme, - (data).authority, - (data).path, - (data).query, - (data).fragment - ); + static revive(data: UriComponents | any): URI { + let result = new _URI(data); result._fsPath = (data).fsPath; result._formatted = (data).external; return result; } } -interface UriComponents { +export interface UriComponents { scheme: string; authority: string; path: string; diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index c43c2f05b34..8470c6ce841 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -109,7 +109,7 @@ declare module monaco { * * */ - export class Uri { + export class Uri implements UriComponents { static isUri(thing: any): thing is Uri; /** * scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'. @@ -161,8 +161,16 @@ declare module monaco { * @param skipEncoding Do not encode the result, default is `false` */ toString(skipEncoding?: boolean): string; - toJSON(): any; - static revive(data: any): Uri; + toJSON(): object; + static revive(data: UriComponents | any): Uri; + } + + export interface UriComponents { + scheme: string; + authority: string; + path: string; + query: string; + fragment: string; } /** From 6e6b2520cb10a5f64c5708ce503edf65cf2e3e70 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 15:21:19 +0200 Subject: [PATCH 219/394] windows: alert if windows-foreground-love is missing related to #36358 --- src/vs/code/electron-main/app.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index bb651dccb41..f5d452e9178 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -386,6 +386,17 @@ export class CodeApplication { }); } } + + try { + require.__$__nodeRequire('windows-foreground-love'); + } catch (e) { + if (!this.environmentService.isBuilt) { + dialog.showMessageBox({ + message: 'Module loading error', + detail: 'Could not load `windows-foreground-love`. Make sure you have it installed as a Code dependency.' + }); + } + } } // Install Menu From e4aa43c31d32317c320c3f45cf0b8db853f5e14b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 18 Oct 2017 15:43:54 +0200 Subject: [PATCH 220/394] fix tests --- .../test/node/configurationEditingService.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index bc24a60429e..42fe3290875 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -18,7 +18,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import extfs = require('vs/base/node/extfs'); -import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices'; +import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestTextResourceConfigurationService, TestHashService } from 'vs/workbench/test/workbenchTestServices'; import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; @@ -45,6 +45,7 @@ import { IChoiceService, IMessageService } from 'vs/platform/message/common/mess import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -122,6 +123,7 @@ suite('ConfigurationEditingService', () => { return workspaceService.initialize(noWorkspace ? {} : workspaceDir).then(() => { instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(ILifecycleService, new TestLifecycleService()); + instantiationService.stub(IHashService, new TestHashService()); instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(IModeService, ModeServiceImpl); From 1eb2dcb12b30f4f818bf050574c382093fb81286 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 15:52:54 +0200 Subject: [PATCH 221/394] fix bad shrinwrap for windows-mutex --- npm-shrinkwrap.json | 14 +++++++++++++- src/vs/code/electron-main/app.ts | 8 ++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a801e584465..ac4d08222c9 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,19 @@ "windows-mutex": { "version": "0.2.0", "from": "windows-mutex@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz", + "dependencies": { + "bindings": { + "version": "1.3.0", + "from": "bindings@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz" + }, + "nan": { + "version": "2.7.0", + "from": "nan@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz" + } + } }, "windows-process-tree": { "version": "0.1.6", diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index f5d452e9178..57788640abe 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -381,8 +381,8 @@ export class CodeApplication { } catch (e) { if (!this.environmentService.isBuilt) { dialog.showMessageBox({ - message: 'Module loading error', - detail: 'Could not load `windows-mutex`. Make sure you have it installed as a Code dependency.' + message: 'Failed to load windows-mutex', + detail: e.toString() }); } } @@ -392,8 +392,8 @@ export class CodeApplication { } catch (e) { if (!this.environmentService.isBuilt) { dialog.showMessageBox({ - message: 'Module loading error', - detail: 'Could not load `windows-foreground-love`. Make sure you have it installed as a Code dependency.' + message: 'Failed to load windows-foreground-love', + detail: e.toString() }); } } From 3f54087c5669262b21fea43b897633e8c554c112 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 15:58:33 +0200 Subject: [PATCH 222/394] Adopt debug to config change event --- .../parts/debug/browser/debugActionsWidget.ts | 10 ++++++++-- .../electron-browser/debugConfigurationManager.ts | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts index 3c68f376e9c..3513a9f08ac 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts @@ -21,7 +21,7 @@ import { IDebugConfiguration, IDebugService, State } from 'vs/workbench/parts/de import { AbstractDebugAction, PauseAction, ContinueAction, StepBackAction, ReverseContinueAction, StopAction, DisconnectAction, StepOverAction, StepIntoAction, StepOutAction, RestartAction, FocusProcessAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { FocusProcessActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IMessageService } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -93,7 +93,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi private registerListeners(): void { this.toUnbind.push(this.debugService.onDidChangeState(state => this.update(state))); - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.update(this.debugService.state))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onDidConfigurationChange(e))); this.toUnbind.push(this.actionBar.actionRunner.addListener(EventType.RUN, (e: any) => { // check for error if (e.error && !errors.isPromiseCanceledError(e.error)) { @@ -195,6 +195,12 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi return DebugActionsWidget.ID; } + private onDidConfigurationChange(event: IConfigurationChangeEvent): void { + if (event.affectsConfiguration('debug.hideActionBar')) { + this.update(this.debugService.state); + } + } + private update(state: State): void { if (state === State.Inactive || state === State.Initializing || this.configurationService.getConfiguration('debug').hideActionBar) { return this.hide(); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 78cecbd98bf..3a1bc568bd4 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -323,8 +323,10 @@ export class ConfigurationManager implements IConfigurationManager { this.initLaunches(); this.selectConfiguration(); })); - this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => { - this.selectConfiguration(); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('launch')) { + this.selectConfiguration(); + } })); this.toDispose.push(lifecycleService.onShutdown(this.store, this)); From eb8622b53a3a8a78e5480173949873583667d9f8 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 16:17:28 +0200 Subject: [PATCH 223/394] Adopt new configuration change event in extensions land --- .../extensions/browser/extensionsActions.ts | 19 ++++++------- .../parts/extensions/common/extensions.ts | 3 +- .../electron-browser/extensionsViewlet.ts | 13 +++------ .../node/extensionsWorkbenchService.ts | 28 ++++++------------- 4 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index e32066bcf7a..9fe32c36539 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -15,7 +15,7 @@ import * as json from 'vs/base/common/json'; import { ActionItem, IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, AutoUpdateConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; import { ExtensionsConfigurationInitialContent } from 'vs/workbench/parts/extensions/common/extensionsFileTemplate'; import { LocalExtensionType, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -704,8 +704,7 @@ export class ToggleAutoUpdateAction extends Action { id: string, label: string, private autoUpdateValue: boolean, - @IConfigurationService configurationService: IConfigurationService, - @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService + @IConfigurationService private configurationService: IConfigurationService ) { super(id, label, '', true); this.updateEnablement(); @@ -713,11 +712,11 @@ export class ToggleAutoUpdateAction extends Action { } private updateEnablement(): void { - this.enabled = this.extensionsWorkbenchService.isAutoUpdateEnabled !== this.autoUpdateValue; + this.enabled = this.configurationService.getValue(AutoUpdateConfigurationKey) !== this.autoUpdateValue; } run(): TPromise { - return this.extensionsWorkbenchService.setAutoUpdate(this.autoUpdateValue); + return this.configurationService.updateValue(AutoUpdateConfigurationKey, this.autoUpdateValue); } } @@ -729,10 +728,9 @@ export class EnableAutoUpdateAction extends ToggleAutoUpdateAction { constructor( id = EnableAutoUpdateAction.ID, label = EnableAutoUpdateAction.LABEL, - @IConfigurationService configurationService: IConfigurationService, - @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService + @IConfigurationService configurationService: IConfigurationService ) { - super(id, label, true, configurationService, extensionsWorkbenchService); + super(id, label, true, configurationService); } } @@ -744,10 +742,9 @@ export class DisableAutoUpdateAction extends ToggleAutoUpdateAction { constructor( id = EnableAutoUpdateAction.ID, label = EnableAutoUpdateAction.LABEL, - @IConfigurationService configurationService: IConfigurationService, - @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService + @IConfigurationService configurationService: IConfigurationService ) { - super(id, label, false, configurationService, extensionsWorkbenchService); + super(id, label, false, configurationService); } } diff --git a/src/vs/workbench/parts/extensions/common/extensions.ts b/src/vs/workbench/parts/extensions/common/extensions.ts index 788e1135a2a..c19f4aba5be 100644 --- a/src/vs/workbench/parts/extensions/common/extensions.ts +++ b/src/vs/workbench/parts/extensions/common/extensions.ts @@ -67,7 +67,6 @@ export interface IExtensionsWorkbenchService { _serviceBrand: any; onChange: Event; local: IExtension[]; - isAutoUpdateEnabled: boolean; queryLocal(): TPromise; queryGallery(options?: IQueryOptions): TPromise>; canInstall(extension: IExtension): boolean; @@ -78,11 +77,11 @@ export interface IExtensionsWorkbenchService { loadDependencies(extension: IExtension): TPromise; open(extension: IExtension, sideByside?: boolean): TPromise; checkForUpdates(): TPromise; - setAutoUpdate(autoUpdate: boolean): TPromise; allowedBadgeProviders: string[]; } export const ConfigurationKey = 'extensions'; +export const AutoUpdateConfigurationKey = 'extensions.autoUpdate'; export interface IExtensionsConfiguration { autoUpdate: boolean; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts index 6a9c5ce9481..317a82c415b 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts @@ -25,7 +25,7 @@ import { append, $, addStandardDisposableListener, EventType, addClass, removeCl import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; -import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, ExtensionState } from '../common/extensions'; +import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, ExtensionState, AutoUpdateConfigurationKey } from '../common/extensions'; import { ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction, ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction, @@ -79,8 +79,6 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens private secondaryActions: IAction[]; private disposables: IDisposable[] = []; - private isAutoUpdateEnabled: boolean; - constructor( @ITelemetryService telemetryService: ITelemetryService, @IProgressService private progressService: IProgressService, @@ -109,12 +107,9 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens this.searchRecommendedExtensionsContextKey = SearchRecommendedExtensionsContext.bindTo(contextKeyService); this.disposables.push(viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables)); - this.isAutoUpdateEnabled = this.extensionsWorkbenchService.isAutoUpdateEnabled; - this.configurationService.onDidChangeConfiguration(() => { - const isAutoUpdateEnabled = this.extensionsWorkbenchService.isAutoUpdateEnabled; - if (this.isAutoUpdateEnabled !== isAutoUpdateEnabled) { - this.isAutoUpdateEnabled = isAutoUpdateEnabled; + this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(AutoUpdateConfigurationKey)) { this.secondaryActions = null; this.updateTitleArea(); } @@ -277,7 +272,7 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.name', localize('sort by name', "Sort By: Name"), this.onSearchChange, 'name'), new Separator(), this.instantiationService.createInstance(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL), - ...(this.isAutoUpdateEnabled ? [this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)] : [this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)]), + ...(this.configurationService.getValue(AutoUpdateConfigurationKey) ? [this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)] : [this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)]), this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL), new Separator(), this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL), diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 7808d2d4c4c..b21a040cde0 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -24,12 +24,12 @@ import { } from 'vs/platform/extensionManagement/common/extensionManagement'; import { getGalleryExtensionIdFromLocal, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IChoiceService, IMessageService } from 'vs/platform/message/common/message'; import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; -import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenchService, IExtensionsConfiguration, ConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IURLService } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; @@ -312,8 +312,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { private _onChange: Emitter = new Emitter(); get onChange(): Event { return this._onChange.event; } - private _isAutoUpdateEnabled: boolean; - private _extensionAllowedBadgeProviders: string[]; constructor( @@ -346,12 +344,9 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { .filter(uri => /^extension/.test(uri.path)) .on(this.onOpenExtensionUrl, this, this.disposables); - this._isAutoUpdateEnabled = this.configurationService.getConfiguration(ConfigurationKey).autoUpdate; - this.configurationService.onDidChangeConfiguration(() => { - const isAutoUpdateEnabled = this.configurationService.getConfiguration(ConfigurationKey).autoUpdate; - if (this._isAutoUpdateEnabled !== isAutoUpdateEnabled) { - this._isAutoUpdateEnabled = isAutoUpdateEnabled; - if (this._isAutoUpdateEnabled) { + this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(AutoUpdateConfigurationKey)) { + if (this.isAutoUpdateEnabled()) { this.checkForUpdates(); } } @@ -454,15 +449,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return this.syncDelayer.trigger(() => this.syncWithGallery(), 0); } - get isAutoUpdateEnabled(): boolean { - return this._isAutoUpdateEnabled; - } - - setAutoUpdate(autoUpdate: boolean): TPromise { - if (this.isAutoUpdateEnabled === autoUpdate) { - return TPromise.as(null); - } - return this.configurationService.updateValue('extensions.autoUpdate', autoUpdate, ConfigurationTarget.USER); + private isAutoUpdateEnabled(): boolean { + return this.configurationService.getValue(AutoUpdateConfigurationKey); } private eventuallySyncWithGallery(immediate = false): void { @@ -491,7 +479,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } private autoUpdateExtensions(): TPromise { - if (!this.isAutoUpdateEnabled) { + if (!this.isAutoUpdateEnabled()) { return TPromise.as(null); } From 8b4d883d18ec77cbcbd87a9ec11e19b8f48d6c43 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 16:38:06 +0200 Subject: [PATCH 224/394] Add ModelDecorationOverviewRulerOptions._resolvedColor --- src/vs/editor/common/model/textModelWithDecorations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 5a500265f8d..37be2b0ea14 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -406,12 +406,14 @@ export class ModelDecorationOverviewRulerOptions implements editorCommon.IModelD readonly darkColor: string | ThemeColor; readonly hcColor: string | ThemeColor; readonly position: editorCommon.OverviewRulerLane; + _resolvedColor: string; constructor(options: editorCommon.IModelDecorationOverviewRulerOptions) { this.color = strings.empty; this.darkColor = strings.empty; this.hcColor = strings.empty; this.position = editorCommon.OverviewRulerLane.Center; + this._resolvedColor = null; if (options && options.color) { this.color = options.color; From fe2841c4312358798a579a6380dd5dfb7d260080 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 16:39:46 +0200 Subject: [PATCH 225/394] Remove ClassName duplication --- src/vs/editor/common/model/intervalTree.ts | 1 - src/vs/editor/common/model/textModelWithDecorations.ts | 6 ------ src/vs/editor/common/services/modelServiceImpl.ts | 2 +- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 9b6970da508..b279da4b813 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -12,7 +12,6 @@ import { IModelDecoration } from 'vs/editor/common/editorCommon'; // The red-black tree is based on the "Introduction to Algorithms" by Cormen, Leiserson and Rivest. // -// TODO@interval!!! export const ClassName = { EditorInfoDecoration: 'infosquiggly', EditorWarningDecoration: 'warningsquiggly', diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 37be2b0ea14..80c7529764c 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -17,12 +17,6 @@ import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; -export const ClassName = { - EditorInfoDecoration: 'infosquiggly', - EditorWarningDecoration: 'warningsquiggly', - EditorErrorDecoration: 'errorsquiggly' -}; - let _INSTANCE_COUNT = 0; /** * Produces 'a'-'z', followed by 'A'-'Z'... followed by 'a'-'z', etc. diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 7eb325a6761..8b535b818f5 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -26,7 +26,7 @@ import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry'; import { IRawTextSource, TextSource, RawTextSource, ITextSource } from 'vs/editor/common/model/textSource'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; -import { ClassName } from 'vs/editor/common/model/textModelWithDecorations'; +import { ClassName } from 'vs/editor/common/model/intervalTree'; import { ISequence, LcsDiff } from 'vs/base/common/diff/diff'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService'; From e3cafbfb382e7d36e01420fcb9e709ed9732f649 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 16:42:24 +0200 Subject: [PATCH 226/394] Adopt to new configuration change event in explorer --- .../parts/files/browser/explorerViewlet.ts | 17 +++++-- .../files/browser/views/explorerViewer.ts | 16 +++---- .../files/browser/views/openEditorsView.ts | 47 +++++++++---------- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/explorerViewlet.ts b/src/vs/workbench/parts/files/browser/explorerViewlet.ts index 8855798cefa..ccf0c46e326 100644 --- a/src/vs/workbench/parts/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/browser/explorerViewlet.ts @@ -13,7 +13,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Builder } from 'vs/base/browser/builder'; import { VIEWLET_ID, ExplorerViewletVisibleContext, IFilesConfiguration, OpenEditorsVisibleContext, OpenEditorsVisibleCondition } from 'vs/workbench/parts/files/common/files'; import { PersistentViewsViewlet, ViewsViewletPanel, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ActionRunner, FileViewletState } from 'vs/workbench/parts/files/browser/views/explorerViewer'; import { ExplorerView, IExplorerViewOptions } from 'vs/workbench/parts/files/browser/views/explorerView'; import { EmptyView } from 'vs/workbench/parts/files/browser/views/emptyView'; @@ -61,8 +61,9 @@ export class ExplorerViewlet extends PersistentViewsViewlet { this.openEditorsVisibleContextKey = OpenEditorsVisibleContext.bindTo(contextKeyService); this.registerViews(); - this.onConfigurationUpdated(); - this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated())); + this.updateOpenEditorsVisibility(); + + this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e))); this._register(this.contextService.onDidChangeWorkspaceName(e => this.updateTitleArea())); this._register(this.contextService.onDidChangeWorkbenchState(() => this.registerViews())); this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.registerViews())); @@ -149,8 +150,14 @@ export class ExplorerViewlet extends PersistentViewsViewlet { }; } - private onConfigurationUpdated(): void { - this.openEditorsVisibleContextKey.set(this.contextService.getWorkbenchState() === WorkbenchState.EMPTY || (this.configurationService.getConfiguration()).explorer.openEditors.visible !== 0); + private onConfigurationUpdated(e: IConfigurationChangeEvent): void { + if (e.affectsConfiguration('explorer.openEditors.visible')) { + this.updateOpenEditorsVisibility(); + } + } + + private updateOpenEditorsVisibility(): void { + this.openEditorsVisibleContextKey.set(this.contextService.getWorkbenchState() === WorkbenchState.EMPTY || this.configurationService.getValue('explorer.openEditors.visible') !== 0); } protected createView(viewDescriptor: IViewDescriptor, options: IViewletViewOptions): ViewsViewletPanel { diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 0328d3ef7ea..21617036d53 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -562,17 +562,17 @@ export class FileSorter implements ISorter { ) { this.toDispose = []; - this.onConfigurationUpdated(configurationService.getConfiguration()); + this.updateSortOrder(); this.registerListeners(); } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.updateSortOrder())); } - private onConfigurationUpdated(configuration: IFilesConfiguration): void { - this.sortOrder = configuration && configuration.explorer && configuration.explorer.sortOrder || 'default'; + private updateSortOrder(): void { + this.sortOrder = this.configurationService.getValue('explorer.sortOrder') || 'default'; } public compare(tree: ITree, statA: FileStat, statB: FileStat): number { @@ -751,7 +751,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { this.toDispose = []; - this.onConfigurationUpdated(configurationService.getConfiguration()); + this.updateDropEnablement(); this.registerListeners(); } @@ -769,11 +769,11 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.updateDropEnablement())); } - private onConfigurationUpdated(config: IFilesConfiguration): void { - this.dropEnabled = config && config.explorer && config.explorer.enableDragAndDrop; + private updateDropEnablement(): void { + this.dropEnabled = this.configurationService.getValue('explorer.enableDragAndDrop'); } public onDragStart(tree: ITree, data: IDragAndDropData, originalEvent: DragMouseEvent): void { diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts index 301fe2a0081..e248d36c195 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts @@ -19,7 +19,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup } from 'vs/workbench/common/editor'; import { SaveAllAction } from 'vs/workbench/parts/files/browser/fileActions'; import { ViewsViewletPanel, IViewletViewOptions, IViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { IFilesConfiguration, VIEWLET_ID, OpenEditorsFocusedContext, ExplorerFocusedContext } from 'vs/workbench/parts/files/common/files'; +import { VIEWLET_ID, OpenEditorsFocusedContext, ExplorerFocusedContext } from 'vs/workbench/parts/files/common/files'; import { ITextFileService, AutoSaveMode } from 'vs/workbench/services/textfile/common/textfiles'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { OpenEditor } from 'vs/workbench/parts/files/common/explorerModel'; @@ -43,9 +43,6 @@ export class OpenEditorsView extends ViewsViewletPanel { static ID = 'workbench.explorer.openEditorsView'; static NAME = nls.localize({ key: 'openEditors', comment: ['Open is an adjective'] }, "Open Editors"); - private visibleOpenEditors: number; - private dynamicHeight: boolean; - private model: IEditorStacksModel; private dirtyCountElement: HTMLElement; private structuralTreeRefreshScheduler: RunOnceScheduler; @@ -168,8 +165,7 @@ export class OpenEditorsView extends ViewsViewletPanel { public create(): TPromise { // Load Config - const configuration = this.configurationService.getConfiguration(); - this.onConfigurationUpdated(configuration); + this.updateSize(); // listeners this.registerListeners(); @@ -183,7 +179,7 @@ export class OpenEditorsView extends ViewsViewletPanel { this.disposables.push(this.model.onModelChanged(e => this.onEditorStacksModelChanged(e))); // Also handle configuration updates - this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration(), e))); + this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(e))); // Handle dirty counter this.disposables.push(this.untitledEditorService.onDidChangeDirty(e => this.updateDirtyIndicator())); @@ -259,34 +255,26 @@ export class OpenEditorsView extends ViewsViewletPanel { } } - private onConfigurationUpdated(configuration: IFilesConfiguration, event?: IConfigurationChangeEvent): void { + private onConfigurationChange(event: IConfigurationChangeEvent): void { if (this.isDisposed) { return; // guard against possible race condition when config change causes recreate of views } - let visibleOpenEditors = configuration && configuration.explorer && configuration.explorer.openEditors && configuration.explorer.openEditors.visible; - if (typeof visibleOpenEditors === 'number') { - this.visibleOpenEditors = visibleOpenEditors; - } else { - this.visibleOpenEditors = OpenEditorsView.DEFAULT_VISIBLE_OPEN_EDITORS; + if (event.affectsConfiguration('explorer.openEditors')) { + this.updateSize(); } - let dynamicHeight = configuration && configuration.explorer && configuration.explorer.openEditors && configuration.explorer.openEditors.dynamicHeight; - if (typeof dynamicHeight === 'boolean') { - this.dynamicHeight = dynamicHeight; - } else { - this.dynamicHeight = OpenEditorsView.DEFAULT_DYNAMIC_HEIGHT; - } - - // Adjust expanded body size - this.minimumBodySize = this.maximumBodySize = this.getExpandedBodySize(this.model); - // Trigger a 'repaint' when decoration settings change - if (event && event.affectsConfiguration('explorer.decorations')) { + if (event.affectsConfiguration('explorer.decorations')) { this.tree.refresh(); } } + private updateSize(): void { + // Adjust expanded body size + this.minimumBodySize = this.maximumBodySize = this.getExpandedBodySize(this.model); + } + private updateDirtyIndicator(): void { let dirty = this.textFileService.getAutoSaveMode() !== AutoSaveMode.AFTER_SHORT_DELAY ? this.textFileService.getDirty().length : this.untitledEditorService.getDirty().length; @@ -299,7 +287,16 @@ export class OpenEditorsView extends ViewsViewletPanel { } private getExpandedBodySize(model: IEditorStacksModel): number { - return OpenEditorsView.computeExpandedBodySize(model, this.visibleOpenEditors, this.dynamicHeight); + let visibleOpenEditors = this.configurationService.getValue('explorer.openEditors.visible'); + if (typeof visibleOpenEditors !== 'number') { + visibleOpenEditors = OpenEditorsView.DEFAULT_VISIBLE_OPEN_EDITORS; + } + + let dynamicHeight = this.configurationService.getValue('explorer.openEditors.dynamicHeight'); + if (typeof dynamicHeight !== 'boolean') { + dynamicHeight = OpenEditorsView.DEFAULT_DYNAMIC_HEIGHT; + } + return OpenEditorsView.computeExpandedBodySize(model, visibleOpenEditors, dynamicHeight); } private static computeExpandedBodySize(model: IEditorStacksModel, visibleOpenEditors = OpenEditorsView.DEFAULT_VISIBLE_OPEN_EDITORS, dynamicHeight = OpenEditorsView.DEFAULT_DYNAMIC_HEIGHT): number { From 8d1828314c4d9661c2fd894e466ff33e19027913 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 16:46:24 +0200 Subject: [PATCH 227/394] fixes #36237 --- .../editor/browser/controller/mouseTarget.ts | 21 +++++++++++++++---- .../editor/contrib/folding/browser/folding.ts | 9 ++++++++ .../debugEditorContribution.ts | 8 ++++--- .../preferences/browser/preferencesWidgets.ts | 4 +++- .../electron-browser/dirtydiffDecorator.ts | 17 ++++++++------- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 4290a200487..bc8982232d3 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -25,6 +25,13 @@ export interface IViewZoneData { afterLineNumber: number; } +export interface IMarginData { + isAfterLines: boolean; + glyphMarginWidth: number; + lineNumbersWidth: number; + offsetX: number; +} + interface IETextRange { boundingHeight: number; boundingLeft: number; @@ -565,22 +572,28 @@ export class MouseTargetFactory { if (request.isInMarginArea) { let res = ctx.getFullLineRangeAtCoord(request.mouseVerticalOffset); let pos = res.range.getStartPosition(); - let offset = Math.abs(request.pos.x - request.editorPos.x); + const detail: IMarginData = { + isAfterLines: res.isAfterLines, + glyphMarginWidth: ctx.layoutInfo.glyphMarginWidth, + lineNumbersWidth: ctx.layoutInfo.lineNumbersWidth, + offsetX: offset + }; + if (offset <= ctx.layoutInfo.glyphMarginWidth) { // On the glyph margin - return request.fulfill(MouseTargetType.GUTTER_GLYPH_MARGIN, pos, res.range, res.isAfterLines); + return request.fulfill(MouseTargetType.GUTTER_GLYPH_MARGIN, pos, res.range, detail); } offset -= ctx.layoutInfo.glyphMarginWidth; if (offset <= ctx.layoutInfo.lineNumbersWidth) { // On the line numbers - return request.fulfill(MouseTargetType.GUTTER_LINE_NUMBERS, pos, res.range, res.isAfterLines); + return request.fulfill(MouseTargetType.GUTTER_LINE_NUMBERS, pos, res.range, detail); } offset -= ctx.layoutInfo.lineNumbersWidth; // On the line decorations - return request.fulfill(MouseTargetType.GUTTER_LINE_DECORATIONS, pos, res.range, res.isAfterLines); + return request.fulfill(MouseTargetType.GUTTER_LINE_DECORATIONS, pos, res.range, detail); } return null; } diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 5cac2cdf29d..c7f40ef849c 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -24,6 +24,7 @@ import { IFoldingController, ID } from 'vs/editor/contrib/folding/common/folding import { Selection } from 'vs/editor/common/core/selection'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions'; +import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; @editorContribution export class FoldingController implements IFoldingController { @@ -322,6 +323,14 @@ export class FoldingController implements IFoldingController { let iconClicked = false; switch (e.target.type) { case MouseTargetType.GUTTER_LINE_DECORATIONS: + const data = e.target.detail as IMarginData; + const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth; + + // TODO@joao TODO@alex TODO@martin this is such that we don't collide with dirty diff + if (gutterOffsetX <= 12) { + return; + } + iconClicked = true; break; case MouseTargetType.CONTENT_EMPTY: diff --git a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts index 0660d442cfa..b4c56b11b18 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts @@ -39,6 +39,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Position } from 'vs/editor/common/core/position'; import { CoreEditingCommands } from 'vs/editor/common/controller/coreCommands'; import { first } from 'vs/base/common/arrays'; +import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; const HOVER_DELAY = 300; const LAUNCH_JSON_REGEX = /launch\.json$/; @@ -146,7 +147,8 @@ export class DebugEditorContribution implements IDebugEditorContribution { private registerListeners(): void { this.toDispose.push(this.editor.onMouseDown((e: IEditorMouseEvent) => { - if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail || !this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)) { + const data = e.target.detail as IMarginData; + if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || data.isAfterLines || !this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)) { return; } const canSetBreakpoints = this.debugService.getConfigurationManager().canSetBreakpointsIn(this.editor.getModel()); @@ -182,8 +184,8 @@ export class DebugEditorContribution implements IDebugEditorContribution { let showBreakpointHintAtLineNumber = -1; if (e.target.type === MouseTargetType.GUTTER_GLYPH_MARGIN && this.debugService.getConfigurationManager().canSetBreakpointsIn(this.editor.getModel()) && this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)) { - if (!e.target.detail) { - // is not after last line + const data = e.target.detail as IMarginData; + if (!data.isAfterLines) { showBreakpointHintAtLineNumber = e.target.position.lineNumber; } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index 81cc7dbdf4f..0eeeadfeb47 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -35,6 +35,7 @@ import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { MarkdownString } from 'vs/base/common/htmlContent'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; export class SettingsHeaderWidget extends Widget implements IViewZone { @@ -585,7 +586,8 @@ export class EditPreferenceWidget extends Disposable { super(); this._editPreferenceDecoration = []; this._register(this.editor.onMouseDown((e: IEditorMouseEvent) => { - if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail || !this.isVisible()) { + const data = e.target.detail as IMarginData; + if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || data.isAfterLines || !this.isVisible()) { return; } this._onClick.fire(e); diff --git a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts index 7096a5a7c00..ec011aa71c6 100644 --- a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts @@ -50,6 +50,7 @@ import { MenuId, IMenuService, IMenu, MenuItemAction } from 'vs/platform/actions import { fillInActions, MenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem'; import { IChange, ICommonCodeEditor, IEditorModel, ScrollType, IEditorContribution, OverviewRulerLane, IModel } from 'vs/editor/common/editorCommon'; import { sortedDiff, Splice } from 'vs/base/common/arrays'; +import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; // TODO@Joao // Need to subclass MenuItemActionItem in order to respect @@ -531,14 +532,6 @@ export class DirtyDiffController implements IEditorContribution { private onEditorMouseDown(e: IEditorMouseEvent): void { this.mouseDownInfo = null; - // if (!this.model) { - // return; - // } - - // if (this.model.changes.length === 0) { - // return; - // } - const range = e.target.range; if (!range) { @@ -553,6 +546,14 @@ export class DirtyDiffController implements IEditorContribution { return; } + const data = e.target.detail as IMarginData; + const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth; + + // TODO@joao TODO@alex TODO@martin this is such that we don't collide with folding + if (gutterOffsetX > 12) { + return; + } + this.mouseDownInfo = { lineNumber: range.startLineNumber }; } From 93393b305d648f75c62acc7fefe1fde393eb2082 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 17:09:18 +0200 Subject: [PATCH 228/394] Binary encode node color --- src/vs/editor/common/model/intervalTree.ts | 145 +++++++++++++-------- 1 file changed, 89 insertions(+), 56 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index b279da4b813..1002ccfa35f 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -29,17 +29,48 @@ export const enum TrackedRangeStickiness { GrowsOnlyWhenTypingAfter = 3, } -export const enum NodeColor { - Red, - Black +const enum NodeColor { + Black = 0, + Red = 1, +} + +const enum Constants { + ColorMask = 0b00000001, + ColorMaskInverse = 0b11111110, + ColorOffset = 0, + + IsForValidationMask = 0b00000010, + IsForValidationMaskInverse = 0b11111101, + IsForValidationOffset = 1, + + IsVisitedMask = 0b00000100, + IsVisitedMaskInverse = 0b11111011, + IsVisitedOffset = 2, + + StickinessMask = 0b00011000, + StickinessMaskInverse = 0b11100111, + StickinessOffset = 3 +} + +function getNodeColor(node: IntervalNode): NodeColor { + return ((node.metadata & Constants.ColorMask) >>> Constants.ColorOffset); +} +function setNodeColor(node: IntervalNode, color: NodeColor): void { + node.metadata = ( + (node.metadata & Constants.ColorMaskInverse) | (color << Constants.ColorOffset) + ); } export class IntervalNode implements IModelDecoration { + /** + * contains binary encoded information for color, isForValidation, visited, and stickiness. + */ + public metadata: number; + public parent: IntervalNode; public left: IntervalNode; public right: IntervalNode; - public color: NodeColor; public start: number; public end: number; @@ -60,10 +91,12 @@ export class IntervalNode implements IModelDecoration { public visited: boolean; constructor(id: string, start: number, end: number) { + this.metadata = 0; + this.parent = null; this.left = null; this.right = null; - this.color = NodeColor.Red; + setNodeColor(this, NodeColor.Red); this.start = start; this.end = end; @@ -125,7 +158,7 @@ const SENTINEL: IntervalNode = new IntervalNode(null, 0, 0); SENTINEL.parent = SENTINEL; SENTINEL.left = SENTINEL; SENTINEL.right = SENTINEL; -SENTINEL.color = NodeColor.Black; +setNodeColor(SENTINEL, NodeColor.Black); export class IntervalTree { @@ -213,7 +246,7 @@ export class IntervalTree { } public assertInvariants(): void { - assert(SENTINEL.color === NodeColor.Black); + assert(getNodeColor(SENTINEL) === NodeColor.Black); assert(SENTINEL.parent === SENTINEL); assert(SENTINEL.left === SENTINEL); assert(SENTINEL.right === SENTINEL); @@ -239,7 +272,7 @@ export class IntervalTree { } private _print(n: IntervalNode, indent: string, delta: number, out: string[]): void { - out.push(`${indent}[${n.color === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.start}->${n.end}, ${n.maxEnd}] : {${delta + n.start}->${delta + n.end}}, maxEnd: ${n.maxEnd + delta}\n`); + out.push(`${indent}[${getNodeColor(n) === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.start}->${n.end}, ${n.maxEnd}] : {${delta + n.start}->${delta + n.end}}, maxEnd: ${n.maxEnd + delta}\n`); if (n.left !== SENTINEL) { this._print(n.left, indent + ' ', delta, out); } else { @@ -731,7 +764,7 @@ function rbTreeInsert(T: IntervalTree, newNode: IntervalNode): IntervalNode { newNode.parent = SENTINEL; newNode.left = SENTINEL; newNode.right = SENTINEL; - newNode.color = NodeColor.Black; + setNodeColor(newNode, NodeColor.Black); T.root = newNode; return T.root; } @@ -742,45 +775,45 @@ function rbTreeInsert(T: IntervalTree, newNode: IntervalNode): IntervalNode { // repair tree let x = newNode; - while (x !== T.root && x.parent.color === NodeColor.Red) { + while (x !== T.root && getNodeColor(x.parent) === NodeColor.Red) { if (x.parent === x.parent.parent.left) { const y = x.parent.parent.right; - if (y.color === NodeColor.Red) { - x.parent.color = NodeColor.Black; - y.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; + if (getNodeColor(y) === NodeColor.Red) { + setNodeColor(x.parent, NodeColor.Black); + setNodeColor(y, NodeColor.Black); + setNodeColor(x.parent.parent, NodeColor.Red); x = x.parent.parent; } else { if (x === x.parent.right) { x = x.parent; leftRotate(T, x); } - x.parent.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; + setNodeColor(x.parent, NodeColor.Black); + setNodeColor(x.parent.parent, NodeColor.Red); rightRotate(T, x.parent.parent); } } else { const y = x.parent.parent.left; - if (y.color === NodeColor.Red) { - x.parent.color = NodeColor.Black; - y.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; + if (getNodeColor(y) === NodeColor.Red) { + setNodeColor(x.parent, NodeColor.Black); + setNodeColor(y, NodeColor.Black); + setNodeColor(x.parent.parent, NodeColor.Red); x = x.parent.parent; } else { if (x === x.parent.left) { x = x.parent; rightRotate(T, x); } - x.parent.color = NodeColor.Black; - x.parent.parent.color = NodeColor.Red; + setNodeColor(x.parent, NodeColor.Black); + setNodeColor(x.parent.parent, NodeColor.Red); leftRotate(T, x.parent.parent); } } } - T.root.color = NodeColor.Black; + setNodeColor(T.root, NodeColor.Black); return newNode; } @@ -823,7 +856,7 @@ function treeInsert(T: IntervalTree, z: IntervalNode): void { z.parent = x; z.left = SENTINEL; z.right = SENTINEL; - z.color = NodeColor.Red; + setNodeColor(z, NodeColor.Red); } //#endregion @@ -867,7 +900,7 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { if (y === T.root) { T.root = x; - x.color = NodeColor.Black; + setNodeColor(x, NodeColor.Black); z.detach(); resetSentinel(); @@ -876,7 +909,7 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { return; } - let yWasRed = (y.color === NodeColor.Red); + let yWasRed = (getNodeColor(y) === NodeColor.Red); if (y === y.parent.left) { y.parent.left = x; @@ -897,7 +930,7 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { y.left = z.left; y.right = z.right; y.parent = z.parent; - y.color = z.color; + setNodeColor(y, getNodeColor(z)); if (z === T.root) { T.root = y; @@ -938,32 +971,32 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { // RB-DELETE-FIXUP let w: IntervalNode; - while (x !== T.root && x.color === NodeColor.Black) { + while (x !== T.root && getNodeColor(x) === NodeColor.Black) { if (x === x.parent.left) { w = x.parent.right; - if (w.color === NodeColor.Red) { - w.color = NodeColor.Black; - x.parent.color = NodeColor.Red; + if (getNodeColor(w) === NodeColor.Red) { + setNodeColor(w, NodeColor.Black); + setNodeColor(x.parent, NodeColor.Red); leftRotate(T, x.parent); w = x.parent.right; } - if (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) { - w.color = NodeColor.Red; + if (getNodeColor(w.left) === NodeColor.Black && getNodeColor(w.right) === NodeColor.Black) { + setNodeColor(w, NodeColor.Red); x = x.parent; } else { - if (w.right.color === NodeColor.Black) { - w.left.color = NodeColor.Black; - w.color = NodeColor.Red; + if (getNodeColor(w.right) === NodeColor.Black) { + setNodeColor(w.left, NodeColor.Black); + setNodeColor(w, NodeColor.Red); rightRotate(T, w); w = x.parent.right; } - w.color = x.parent.color; - x.parent.color = NodeColor.Black; - w.right.color = NodeColor.Black; + setNodeColor(w, getNodeColor(x.parent)); + setNodeColor(x.parent, NodeColor.Black); + setNodeColor(w.right, NodeColor.Black); leftRotate(T, x.parent); x = T.root; } @@ -971,35 +1004,35 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { } else { w = x.parent.left; - if (w.color === NodeColor.Red) { - w.color = NodeColor.Black; - x.parent.color = NodeColor.Red; + if (getNodeColor(w) === NodeColor.Red) { + setNodeColor(w, NodeColor.Black); + setNodeColor(x.parent, NodeColor.Red); rightRotate(T, x.parent); w = x.parent.left; } - if (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) { - w.color = NodeColor.Red; + if (getNodeColor(w.left) === NodeColor.Black && getNodeColor(w.right) === NodeColor.Black) { + setNodeColor(w, NodeColor.Red); x = x.parent; } else { - if (w.left.color === NodeColor.Black) { - w.right.color = NodeColor.Black; - w.color = NodeColor.Red; + if (getNodeColor(w.left) === NodeColor.Black) { + setNodeColor(w.right, NodeColor.Black); + setNodeColor(w, NodeColor.Red); leftRotate(T, w); w = x.parent.left; } - w.color = x.parent.color; - x.parent.color = NodeColor.Black; - w.left.color = NodeColor.Black; + setNodeColor(w, getNodeColor(x.parent)); + setNodeColor(x.parent, NodeColor.Black); + setNodeColor(w.left, NodeColor.Black); rightRotate(T, x.parent); x = T.root; } } } - x.color = NodeColor.Black; + setNodeColor(x, NodeColor.Black); resetSentinel(); } @@ -1131,7 +1164,7 @@ function depth(n: IntervalNode): number { return 1; } assert(depth(n.left) === depth(n.right)); - return (n.color === NodeColor.Black ? 1 : 0) + depth(n.left); + return (getNodeColor(n) === NodeColor.Black ? 1 : 0) + depth(n.left); } function assertValidNode(n: IntervalNode, delta): void { @@ -1142,9 +1175,9 @@ function assertValidNode(n: IntervalNode, delta): void { let l = n.left; let r = n.right; - if (n.color === NodeColor.Red) { - assert(l.color === NodeColor.Black); - assert(r.color === NodeColor.Black); + if (getNodeColor(n) === NodeColor.Red) { + assert(getNodeColor(l) === NodeColor.Black); + assert(getNodeColor(r) === NodeColor.Black); } let expectedMaxEnd = n.end; @@ -1166,7 +1199,7 @@ function assertValidTree(tree: IntervalTree): void { if (tree.root === SENTINEL) { return; } - assert(tree.root.color === NodeColor.Black); + assert(getNodeColor(tree.root) === NodeColor.Black); assert(depth(tree.root.left) === depth(tree.root.right)); assertValidNode(tree.root, 0); } From c7ba0dc4bac922f566c3517ac3d13f2d76bde06d Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Oct 2017 12:44:15 +0200 Subject: [PATCH 229/394] panel: adopt CompositeBar --- .../parts/activitybar/activitybarPart.ts | 3 +- .../activitybar/media/activityaction.css | 4 - .../workbench/browser/parts/compositePart.ts | 4 +- .../parts/compositebar/compositeBar.ts | 19 ++- .../parts/compositebar/compositeBarActions.ts | 25 ++-- .../parts/compositebar/media/compositeBar.css | 8 ++ .../media/ellipsis-global.svg | 0 .../browser/parts/panel/media/panelpart.css | 9 +- .../browser/parts/panel/panelActions.ts | 16 +++ .../browser/parts/panel/panelPart.ts | 114 +++++++++++------- .../terminal/electron-browser/media/xterm.css | 2 +- .../services/panel/common/panelService.ts | 1 + 12 files changed, 133 insertions(+), 72 deletions(-) create mode 100644 src/vs/workbench/browser/parts/compositebar/media/compositeBar.css rename src/vs/workbench/browser/parts/{activitybar => compositebar}/media/ellipsis-global.svg (100%) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 49b1cb6a684..b5f0207be59 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -60,7 +60,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.globalActivityIdToActions = Object.create(null); this.compositeBar = this.instantiationService.createInstance(CompositeBar, { - label: 'icon', + icon: true, storageId: ActivitybarPart.PINNED_VIEWLETS, orientation: ActionsOrientation.VERTICAL, composites: this.viewletService.getViewlets(), @@ -213,7 +213,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { } public shutdown(): void { - // Persist Hidden State this.compositeBar.store(); diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index f9bb260bdbe..3f07bfcb0d0 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -41,10 +41,6 @@ right: 1px; } -.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label.toggle-more { - -webkit-mask: url('ellipsis-global.svg') no-repeat 50% 50%; -} - .monaco-workbench > .activitybar > .content .monaco-action-bar .badge { position: absolute; top: 5px; diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index 2c4ee35d07c..7906d1d0da7 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -62,7 +62,7 @@ export abstract class CompositePart extends Part { private lastActiveCompositeId: string; private instantiatedComposites: Composite[]; private titleLabel: ICompositeTitleLabel; - private toolBar: ToolBar; + protected toolBar: ToolBar; private progressBar: ProgressBar; private contentAreaSize: Dimension; private telemetryActionsListener: IDisposable; @@ -74,7 +74,7 @@ export abstract class CompositePart extends Part { private messageService: IMessageService, private storageService: IStorageService, private telemetryService: ITelemetryService, - private contextMenuService: IContextMenuService, + protected contextMenuService: IContextMenuService, protected partService: IPartService, private keybindingService: IKeybindingService, protected instantiationService: IInstantiationService, diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 74ea9884843..acdd4011e88 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -5,6 +5,7 @@ 'use strict'; +import 'vs/css!./media/compositeBar'; import nls = require('vs/nls'); import { Action } from 'vs/base/common/actions'; import { illegalArgument } from 'vs/base/common/errors'; @@ -21,7 +22,7 @@ import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivit import { TPromise } from 'vs/base/common/winjs.base'; export interface ICompositeBarOptions { - label: 'icon' | 'name'; + icon: boolean; storageId: string; orientation: ActionsOrientation; composites: { id: string, name: string }[]; @@ -152,13 +153,13 @@ export class CompositeBar implements ICompositeBar { } } - public create(parent: HTMLElement): void { - const actionBarDiv = parent.appendChild(dom.$('composite-bar')); + public create(parent: HTMLElement): HTMLElement { + const actionBarDiv = parent.appendChild(dom.$('.composite-bar')); this.compositeSwitcherBar = new ActionBar(actionBarDiv, { actionItemProvider: (action: Action) => action instanceof CompositeOverflowActivityAction ? this.compositeOverflowActionItem : this.compositeIdToActionItems[action.id], orientation: this.options.orientation, ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher"), - animated: false + animated: false, }); this.updateCompositeSwitcher(); @@ -181,6 +182,12 @@ export class CompositeBar implements ICompositeBar { } } })); + + return actionBarDiv; + } + + public getAction(compositeId): ActivityAction { + return this.compositeIdToActions[compositeId]; } private updateCompositeSwitcher(): void { @@ -247,7 +254,7 @@ export class CompositeBar implements ICompositeBar { if (newCompositesToShow.length) { // Add to composite switcher - this.compositeSwitcherBar.push(newCompositesToShow, { label: true, icon: true }); + this.compositeSwitcherBar.push(newCompositesToShow, { label: true, icon: this.options.icon }); // Make sure to activate the active one if (this.activeCompositeId) { @@ -275,7 +282,7 @@ export class CompositeBar implements ICompositeBar { this.options.getOnCompositeClickAction ); - this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: true, icon: true }); + this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true }); } } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 617c17f714d..fd2713584fc 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -31,24 +31,24 @@ export interface ICompositeActivity { export interface ICompositeBar { /** - * Unpins a viewlet from the activitybar. + * Unpins a composite from the activitybar. */ - unpin(viewletId: string): void; + unpin(compositeId: string): void; /** - * Pin a viewlet inside the activity bar. + * Pin a composite inside the activity bar. */ - pin(viewletId: string): void; + pin(compositeId: string): void; /** - * Find out if a viewlet is pinned in the activity bar. + * Find out if a composite is pinned in the activity bar. */ - isPinned(viewletId: string): boolean; + isPinned(compositeId: string): boolean; /** - * Reorder viewlet ordering by moving a viewlet to the location of another viewlet. + * Reorder composite ordering by moving a composite to the location of another composite. */ - move(viewletId: string, toViewletId: string): void; + move(compositeId: string, tocompositeId: string): void; } export class ActivityAction extends Action { @@ -169,6 +169,7 @@ export class ActivityActionItem extends BaseActionItem { if (this.activity.cssClass) { this.$label.addClass(this.activity.cssClass); } + this.$label.text(this.getAction().label); this.$badge = this.builder.clone().div({ 'class': 'badge' }, (badge: Builder) => { this.$badgeContent = badge.div({ 'class': 'badge-content' }); @@ -262,7 +263,7 @@ export class CompositeOverflowActivityAction extends ActivityAction { private showMenu: () => void ) { super({ - id: 'activitybar.additionalComposites.action', + id: 'additionalComposites.action', name: nls.localize('additionalViews', "Additional Views"), cssClass: 'toggle-more' }); @@ -512,10 +513,10 @@ export class CompositeActionItem extends ActivityActionItem { const isPinned = this.compositeBar.isPinned(this.activity.id); if (isPinned) { - this.toggleCompositePinnedAction.label = nls.localize('removeFromActivityBar', "Hide from Activity Bar"); + this.toggleCompositePinnedAction.label = nls.localize('hide', "Hide"); this.toggleCompositePinnedAction.checked = false; } else { - this.toggleCompositePinnedAction.label = nls.localize('keepInActivityBar', "Keep in Activity Bar"); + this.toggleCompositePinnedAction.label = nls.localize('keep', "Keep"); } this.contextMenuService.showContextMenu({ @@ -569,7 +570,7 @@ export class ToggleCompositePinnedAction extends Action { private activity: IActivity, private compositeBar: ICompositeBar ) { - super('activitybar.show.toggleViewletPinned', activity ? activity.name : nls.localize('toggle', "Toggle View Pinned")); + super('show.toggleCompositePinned', activity ? activity.name : nls.localize('toggle', "Toggle View Pinned")); this.checked = this.activity && this.compositeBar.isPinned(this.activity.id); } diff --git a/src/vs/workbench/browser/parts/compositebar/media/compositeBar.css b/src/vs/workbench/browser/parts/compositebar/media/compositeBar.css new file mode 100644 index 00000000000..93601334bbe --- /dev/null +++ b/src/vs/workbench/browser/parts/compositebar/media/compositeBar.css @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-workbench .composite-bar > .monaco-action-bar .action-label.toggle-more { + -webkit-mask: url('ellipsis-global.svg') no-repeat 50% 50%; +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg b/src/vs/workbench/browser/parts/compositebar/media/ellipsis-global.svg similarity index 100% rename from src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg rename to src/vs/workbench/browser/parts/compositebar/media/ellipsis-global.svg diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index 10ffa06b7eb..ee9b5c62162 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -17,6 +17,13 @@ border-top-style: solid; padding-right: 0px; height: 35px; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.monaco-workbench > .part.panel > .composite.title > .title-actions { + flex: 0; } .monaco-workbench > .part.panel > .title > .title-actions .monaco-action-bar .action-item .action-label { @@ -41,7 +48,7 @@ padding-bottom: 4px; /* puts the bottom border down */ } -.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label.checked { +.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label { border-bottom: 1px solid; } diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 238b3b33b11..759cb22cbf6 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -15,6 +15,8 @@ import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions } from 'vs/ import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { ActivityAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { IActivity } from 'vs/workbench/common/activity'; export class OpenPanelAction extends Action { @@ -149,6 +151,20 @@ export class ToggleMaximizedPanelAction extends Action { } } +export class PanelActivityAction extends ActivityAction { + + constructor( + activity: IActivity, + @IPanelService private panelService: IPanelService + ) { + super(activity); + } + + public run(event: any): TPromise { + return this.panelService.openPanel(this.activity.id, true).then(() => this.activate()); + } +} + const actionRegistry = Registry.as(WorkbenchExtensions.WorkbenchActions); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_J }), 'View: Toggle Panel', nls.localize('view', "View")); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPanelAction, FocusPanelAction.ID, FocusPanelAction.LABEL), 'View: Focus into Panel', nls.localize('view', "View")); diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 1608bfe44d2..0ae3291cdb1 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/panelpart'; -import nls = require('vs/nls'); import { TPromise } from 'vs/base/common/winjs.base'; -import { IAction } from 'vs/base/common/actions'; +import { IAction, Action } from 'vs/base/common/actions'; import Event from 'vs/base/common/event'; -import { Builder, $ } from 'vs/base/browser/builder'; +import { Builder, Dimension } from 'vs/base/browser/builder'; import { Registry } from 'vs/platform/registry/common/platform'; +import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { Scope } from 'vs/workbench/browser/actions'; import { IPanel } from 'vs/workbench/common/panel'; import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/compositePart'; @@ -22,22 +22,24 @@ import { IMessageService } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { ClosePanelAction, OpenPanelAction, ToggleMaximizedPanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; +import { ClosePanelAction, ToggleMaximizedPanelAction, PanelActivityAction, OpenPanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER } from 'vs/workbench/common/theme'; import { activeContrastBorder, focusBorder, contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry'; +import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; +import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { dispose } from 'vs/base/common/lifecycle'; export class PanelPart extends CompositePart implements IPanelService { public static activePanelSettingsKey = 'workbench.panelpart.activepanelid'; + private static readonly PINNED_PANELS = 'workbench.panel.pinnedPanels'; public _serviceBrand: any; private blockOpeningPanel: boolean; - private panelSwitcherBar: ActionBar; - - private panelIdToActions: { [panelId: string]: OpenPanelAction; }; + private compositeBar: CompositeBar; constructor( id: string, @@ -48,7 +50,7 @@ export class PanelPart extends CompositePart implements IPanelService { @IPartService partService: IPartService, @IKeybindingService keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, ) { super( messageService, @@ -70,7 +72,23 @@ export class PanelPart extends CompositePart implements IPanelService { { hasTitle: true } ); - this.panelIdToActions = Object.create(null); + this.compositeBar = this.instantiationService.createInstance(CompositeBar, { + icon: false, + storageId: PanelPart.PINNED_PANELS, + orientation: ActionsOrientation.HORIZONTAL, + composites: this.getPanels(), + getCompositeSize: (compositeId: string) => { + const panel = this.getPanel(compositeId); + return 10 * panel.name.length; + }, + openComposite: (compositeId: string) => this.openPanel(compositeId, true), + getActivityAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, this.getPanel(compositeId)), + getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar), + getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(OpenPanelAction, this.getPanel(compositeId)), + getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), + hidePart: () => this.partService.setPanelHidden(true) + }); + this.toUnbind.push(this.compositeBar); this.registerListeners(); } @@ -78,16 +96,11 @@ export class PanelPart extends CompositePart implements IPanelService { private registerListeners(): void { // Activate panel action on opening of a panel - this.toUnbind.push(this.onDidPanelOpen(panel => this.updatePanelActions(panel.getId(), true))); + this.toUnbind.push(this.onDidPanelOpen(panel => this.compositeBar.activateComposite(panel.getId()))); // Deactivate panel action on close - this.toUnbind.push(this.onDidPanelClose(panel => this.updatePanelActions(panel.getId(), false))); - } - - private updatePanelActions(id: string, didOpen: boolean): void { - if (this.panelIdToActions[id]) { - didOpen ? this.panelIdToActions[id].activate() : this.panelIdToActions[id].deactivate(); - } + this.toUnbind.push(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId()))); + this.toUnbind.push(this.compositeBar.onDidContextMenu(e => this.showContextMenu(e))); } public get onDidPanelOpen(): Event { @@ -127,6 +140,21 @@ export class PanelPart extends CompositePart implements IPanelService { return promise.then(() => this.openComposite(id, focus)); } + private getPanel(panelId: string): IPanelIdentifier { + return Registry.as(PanelExtensions.Panels).getPanels().filter(p => p.id === panelId).pop(); + } + + private showContextMenu(e: MouseEvent): void { + const event = new StandardMouseEvent(e); + const actions: Action[] = this.getPanels().map(panel => this.instantiationService.createInstance(ToggleCompositePinnedAction, panel, this.compositeBar)); + + this.contextMenuService.showContextMenu({ + getAnchor: () => { return { x: event.posx, y: event.posy }; }, + getActions: () => TPromise.as(actions), + onHide: () => dispose(actions) + }); + } + public getPanels(): IPanelIdentifier[] { return Registry.as(PanelExtensions.Panels).getPanels() .sort((v1, v2) => v1.order - v2.order); @@ -152,23 +180,12 @@ export class PanelPart extends CompositePart implements IPanelService { } protected createTitleLabel(parent: Builder): ICompositeTitleLabel { - let titleArea = $(parent).div({ - 'class': ['panel-switcher-container'] - }); - - // Show a panel switcher - this.panelSwitcherBar = new ActionBar(titleArea, { - orientation: ActionsOrientation.HORIZONTAL, - ariaLabel: nls.localize('panelSwitcherBarAriaLabel', "Active Panel Switcher"), - animated: false - }); - this.toUnbind.push(this.panelSwitcherBar); - - this.fillPanelSwitcher(); + const titleArea = this.compositeBar.create(parent.getHTMLElement()); + titleArea.classList.add('panel-switcher-container'); return { updateTitle: (id, title, keybinding) => { - const action = this.panelIdToActions[id]; + const action = this.compositeBar.getAction(id); if (action) { action.label = title; } @@ -179,17 +196,26 @@ export class PanelPart extends CompositePart implements IPanelService { }; } - private fillPanelSwitcher(): void { - const panels = this.getPanels(); + public layout(dimension: Dimension): Dimension[] { - this.panelSwitcherBar.push(panels.map(panel => { - const action = this.instantiationService.createInstance(OpenPanelAction, panel); + // Pass to super + const sizes = super.layout(dimension); + let availableWidth = dimension.width; + if (this.toolBar) { + // adjust height for global actions showing + availableWidth -= this.toolBar.getContainer().getHTMLElement().offsetWidth; + } + this.compositeBar.layout(new Dimension(availableWidth, dimension.height)); - this.panelIdToActions[panel.id] = action; - this.toUnbind.push(action); + return sizes; + } - return action; - })); + public shutdown(): void { + // Persist Hidden State + this.compositeBar.store(); + + // Pass to super + super.shutdown(); } } @@ -215,7 +241,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (titleActive || titleActiveBorder) { collector.addRule(` .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:hover .action-label, - .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label.checked { + .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label { color: ${titleActive}; border-bottom-color: ${titleActiveBorder}; } @@ -236,7 +262,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const focusBorderColor = theme.getColor(focusBorder); if (focusBorderColor) { collector.addRule(` - .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:focus { + .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus { color: ${titleActive}; border-bottom-color: ${focusBorderColor} !important; border-bottom: 1px solid; @@ -251,7 +277,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const outline = theme.getColor(activeContrastBorder); collector.addRule(` - .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label.checked, + .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label, .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:hover { outline-color: ${outline}; outline-width: 1px; @@ -261,7 +287,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { outline-offset: 3px; } - .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:hover:not(.checked) { + .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:not(.checked) .action-label:hover { outline-style: dashed; } `); diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css index 0e554c525ba..4eb09d1fb3d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css @@ -39,7 +39,7 @@ * Default styles for xterm.js */ -.terminal { +.terminal:not(.action-label) { font-family: courier-new, courier, monospace; font-feature-settings: "liga" 0; position: relative; diff --git a/src/vs/workbench/services/panel/common/panelService.ts b/src/vs/workbench/services/panel/common/panelService.ts index 5de4a2d9e18..f490edbda68 100644 --- a/src/vs/workbench/services/panel/common/panelService.ts +++ b/src/vs/workbench/services/panel/common/panelService.ts @@ -14,6 +14,7 @@ export interface IPanelIdentifier { id: string; name: string; commandId: string; + cssClass: string; } export interface IPanelService { From d87815b8383b43c0e4e7685fa6505b8be7861b02 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Oct 2017 16:38:56 +0200 Subject: [PATCH 230/394] compositeBar: compute sizes by initialiy filling out the action bar and get the size from css --- src/vs/base/browser/ui/actionbar/actionbar.ts | 16 ++++++++++++++ .../parts/activitybar/activitybarPart.ts | 4 +--- .../parts/compositebar/compositeBar.ts | 21 ++++++++++++++++--- .../browser/parts/panel/panelPart.ts | 4 ---- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index de30d225bc9..ab24a7d3995 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -595,6 +595,22 @@ export class ActionBar extends EventEmitter implements IActionRunner { }); } + public getWidth(index: number): number { + if (index >= 0 && index < this.actionsList.children.length) { + return this.actionsList.children.item(index).clientWidth; + } + + return 0; + } + + public getHeight(index: number): number { + if (index >= 0 && index < this.actionsList.children.length) { + return this.actionsList.children.item(index).clientHeight; + } + + return 0; + } + public pull(index: number): void { if (index >= 0 && index < this.items.length) { this.items.splice(index, 1); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index b5f0207be59..56d4fa0d7ef 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -34,7 +34,6 @@ import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/composit export class ActivitybarPart extends Part implements IActivityBarService { - private static readonly ACTIVITY_ACTION_HEIGHT = 50; private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets'; public _serviceBrand: any; @@ -64,7 +63,6 @@ export class ActivitybarPart extends Part implements IActivityBarService { storageId: ActivitybarPart.PINNED_VIEWLETS, orientation: ActionsOrientation.VERTICAL, composites: this.viewletService.getViewlets(), - getCompositeSize: (compositeId: string) => ActivitybarPart.ACTIVITY_ACTION_HEIGHT, openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true), getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)), getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.viewletService.getViewlet(compositeId), this.compositeBar), @@ -191,7 +189,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { let availableHeight = this.dimension.height; if (this.globalActionBar) { // adjust height for global actions showing - availableHeight -= (this.globalActionBar.items.length * ActivitybarPart.ACTIVITY_ACTION_HEIGHT); + availableHeight -= (this.globalActionBar.items.length * this.globalActionBar.domNode.clientHeight); } this.compositeBar.layout(new Dimension(dimension.width, availableHeight)); diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index acdd4011e88..eeb504452c4 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -31,7 +31,6 @@ export interface ICompositeBarOptions { getOnCompositeClickAction: (compositeId: string) => Action; openComposite: (compositeId: string) => TPromise; getDefaultCompositeId: () => string; - getCompositeSize: (compositeId: string) => number; hidePart: () => TPromise; } @@ -49,6 +48,7 @@ export class CompositeBar implements ICompositeBar { private compositeIdToActions: { [compositeId: string]: ActivityAction; }; private compositeIdToActionItems: { [compositeId: string]: IActionItem; }; private compositeIdToActivityStack: { [compositeId: string]: ICompositeActivity[]; }; + private compositeSizeInBar: Map; private pinnedComposites: string[]; private activeCompositeId: string; @@ -63,6 +63,7 @@ export class CompositeBar implements ICompositeBar { this.compositeIdToActionItems = Object.create(null); this.compositeIdToActions = Object.create(null); this.compositeIdToActivityStack = Object.create(null); + this.compositeSizeInBar = new Map(); this._onDidContextMenu = new Emitter(); @@ -161,7 +162,6 @@ export class CompositeBar implements ICompositeBar { ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher"), animated: false, }); - this.updateCompositeSwitcher(); // Contextmenu for composites this.toDispose.push(dom.addDisposableListener(parent, dom.EventType.CONTEXT_MENU, (e: MouseEvent) => { @@ -212,7 +212,7 @@ export class CompositeBar implements ICompositeBar { let size = 0; const limit = this.options.orientation === ActionsOrientation.VERTICAL ? this.dimension.height : this.dimension.width; for (let i = 0; i < compositesToShow.length && size <= limit; i++) { - size += this.options.getCompositeSize(compositesToShow[i]); + size += this.compositeSizeInBar.get(compositesToShow[i]); if (size > limit) { maxVisible = i; } @@ -317,6 +317,10 @@ export class CompositeBar implements ICompositeBar { } private toAction(compositeId: string): ActivityAction { + if (this.compositeIdToActions[compositeId]) { + return this.compositeIdToActions[compositeId]; + } + const compositeActivityAction = this.options.getActivityAction(compositeId); const pinnedAction = this.options.getCompositePinnedAction(compositeId); this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this); @@ -413,6 +417,17 @@ export class CompositeBar implements ICompositeBar { public layout(dimension: Dimension): void { this.dimension = dimension; + if (this.compositeSizeInBar.size === 0) { + // Compute size of each composite by getting the size from the css renderer + // Size is later used for overflow computation + this.compositeSwitcherBar.clear(); + this.compositeSwitcherBar.push(this.options.composites.map(c => this.options.getActivityAction(c.id))); + this.options.composites.map((c, index) => this.compositeSizeInBar.set(c.id, this.options.orientation === ActionsOrientation.VERTICAL + ? this.compositeSwitcherBar.getHeight(index) + : this.compositeSwitcherBar.getWidth(index) + )); + this.compositeSwitcherBar.clear(); + } this.updateCompositeSwitcher(); } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 0ae3291cdb1..4956648ba12 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -77,10 +77,6 @@ export class PanelPart extends CompositePart implements IPanelService { storageId: PanelPart.PINNED_PANELS, orientation: ActionsOrientation.HORIZONTAL, composites: this.getPanels(), - getCompositeSize: (compositeId: string) => { - const panel = this.getPanel(compositeId); - return 10 * panel.name.length; - }, openComposite: (compositeId: string) => this.openPanel(compositeId, true), getActivityAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, this.getPanel(compositeId)), getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar), From 637a2e3baa0e6308829950468f88b622a7541505 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Oct 2017 17:18:22 +0200 Subject: [PATCH 231/394] composite bar fix rendering issue with the overflow --- .../parts/activitybar/media/activitybarpart.css | 4 ++++ .../media/ellipsis-global.svg | 0 .../parts/compositebar/compositeBarActions.ts | 13 ++++++++++--- .../parts/compositebar/media/compositeBar.css | 8 -------- .../browser/parts/panel/media/ellipsis-inverse.svg | 1 + .../browser/parts/panel/media/ellipsis.svg | 1 + .../browser/parts/panel/media/panelpart.css | 7 +++++++ 7 files changed, 23 insertions(+), 11 deletions(-) rename src/vs/workbench/browser/parts/{compositebar => activitybar}/media/ellipsis-global.svg (100%) delete mode 100644 src/vs/workbench/browser/parts/compositebar/media/compositeBar.css create mode 100644 src/vs/workbench/browser/parts/panel/media/ellipsis-inverse.svg create mode 100644 src/vs/workbench/browser/parts/panel/media/ellipsis.svg diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css index 50061325e7e..2e8ceb738cc 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css @@ -21,4 +21,8 @@ .monaco-workbench > .activitybar [tabindex="0"]:focus { outline: 0 !important; /* activity bar indicates focus custom */ +} + +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-label.toggle-more { + -webkit-mask: url('ellipsis-global.svg') no-repeat 50% 50%; } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/compositebar/media/ellipsis-global.svg b/src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg similarity index 100% rename from src/vs/workbench/browser/parts/compositebar/media/ellipsis-global.svg rename to src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index fd2713584fc..11449e79342 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -91,17 +91,22 @@ export class ActivityAction extends Action { } } +export interface IActivityActionItemOptions extends IBaseActionItemOptions { + icon?: boolean; +} + export class ActivityActionItem extends BaseActionItem { protected $container: Builder; protected $label: Builder; protected $badge: Builder; + protected options: IActivityActionItemOptions; private $badgeContent: Builder; private mouseUpTimeout: number; constructor( action: ActivityAction, - options: IBaseActionItemOptions, + options: IActivityActionItemOptions, @IThemeService protected themeService: IThemeService ) { super(null, action, options); @@ -169,7 +174,9 @@ export class ActivityActionItem extends BaseActionItem { if (this.activity.cssClass) { this.$label.addClass(this.activity.cssClass); } - this.$label.text(this.getAction().label); + if (!this.options.icon) { + this.$label.text(this.getAction().label); + } this.$badge = this.builder.clone().div({ 'class': 'badge' }, (badge: Builder) => { this.$badgeContent = badge.div({ 'class': 'badge-content' }); @@ -291,7 +298,7 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem { @IContextMenuService private contextMenuService: IContextMenuService, @IThemeService themeService: IThemeService ) { - super(action, null, themeService); + super(action, { icon: true }, themeService); this.cssClass = action.class; this.name = action.label; diff --git a/src/vs/workbench/browser/parts/compositebar/media/compositeBar.css b/src/vs/workbench/browser/parts/compositebar/media/compositeBar.css deleted file mode 100644 index 93601334bbe..00000000000 --- a/src/vs/workbench/browser/parts/compositebar/media/compositeBar.css +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.monaco-workbench .composite-bar > .monaco-action-bar .action-label.toggle-more { - -webkit-mask: url('ellipsis-global.svg') no-repeat 50% 50%; -} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/panel/media/ellipsis-inverse.svg b/src/vs/workbench/browser/parts/panel/media/ellipsis-inverse.svg new file mode 100644 index 00000000000..1140c11ecc8 --- /dev/null +++ b/src/vs/workbench/browser/parts/panel/media/ellipsis-inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/panel/media/ellipsis.svg b/src/vs/workbench/browser/parts/panel/media/ellipsis.svg new file mode 100644 index 00000000000..b61e2d0c750 --- /dev/null +++ b/src/vs/workbench/browser/parts/panel/media/ellipsis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index ee9b5c62162..c96afe134ab 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -32,6 +32,13 @@ /** Panel Switcher */ +.monaco-workbench .composite-bar > .monaco-action-bar .action-label.toggle-more { + background: url('ellipsis.svg') center center no-repeat; + display: block; + height: 35px; + min-width: 28px; +} + .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar { line-height: 35px; } From cc3ccb280ae29e28a974caf2b57262c8ceca8b3d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 17:21:41 +0200 Subject: [PATCH 232/394] Binary encode node.visited --- src/vs/editor/common/model/intervalTree.ts | 120 +++++++++++---------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 1002ccfa35f..9a776340644 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -39,13 +39,13 @@ const enum Constants { ColorMaskInverse = 0b11111110, ColorOffset = 0, - IsForValidationMask = 0b00000010, - IsForValidationMaskInverse = 0b11111101, - IsForValidationOffset = 1, + IsVisitedMask = 0b00000010, + IsVisitedMaskInverse = 0b11111101, + IsVisitedOffset = 1, - IsVisitedMask = 0b00000100, - IsVisitedMaskInverse = 0b11111011, - IsVisitedOffset = 2, + IsForValidationMask = 0b00000100, + IsForValidationMaskInverse = 0b11111011, + IsForValidationOffset = 2, StickinessMask = 0b00011000, StickinessMaskInverse = 0b11100111, @@ -60,6 +60,14 @@ function setNodeColor(node: IntervalNode, color: NodeColor): void { (node.metadata & Constants.ColorMaskInverse) | (color << Constants.ColorOffset) ); } +function getNodeIsVisited(node: IntervalNode): boolean { + return ((node.metadata & Constants.IsVisitedMask) >>> Constants.IsVisitedOffset) === 1; +} +function setNodeIsVisited(node: IntervalNode, value: boolean): void { + node.metadata = ( + (node.metadata & Constants.IsVisitedMaskInverse) | ((value ? 1 : 0) << Constants.IsVisitedOffset) + ); +} export class IntervalNode implements IModelDecoration { @@ -88,8 +96,6 @@ export class IntervalNode implements IModelDecoration { public cachedAbsoluteEnd: number; public range: Range; - public visited: boolean; - constructor(id: string, start: number, end: number) { this.metadata = 0; @@ -114,7 +120,7 @@ export class IntervalNode implements IModelDecoration { this.cachedAbsoluteEnd = end; this.range = null; - this.visited = false; + setNodeIsVisited(this, false); } public reset(versionId: number, start: number, end: number, range: Range): void { @@ -398,10 +404,10 @@ function searchForEditing(T: IntervalTree, start: number, end: number): Interval let result: IntervalNode[] = []; let resultLen = 0; while (node !== SENTINEL) { - if (node.visited) { + if (getNodeIsVisited(node)) { // going up from this node - node.left.visited = false; - node.right.visited = false; + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); if (node === node.parent.right) { delta -= node.parent.delta; } @@ -409,13 +415,13 @@ function searchForEditing(T: IntervalTree, start: number, end: number): Interval continue; } - if (!node.left.visited) { + if (!getNodeIsVisited(node.left)) { // first time seeing this node nodeMaxEnd = delta + node.maxEnd; if (nodeMaxEnd < start) { // cover case b) from above // there is no need to search this node or its children - node.visited = true; + setNodeIsVisited(node, true); continue; } @@ -431,7 +437,7 @@ function searchForEditing(T: IntervalTree, start: number, end: number): Interval if (nodeStart > end) { // cover case a) from above // there is no need to search this node or its right subtree - node.visited = true; + setNodeIsVisited(node, true); continue; } @@ -440,9 +446,9 @@ function searchForEditing(T: IntervalTree, start: number, end: number): Interval node.setCachedOffsets(nodeStart, nodeEnd, 0); result[resultLen++] = node; } - node.visited = true; + setNodeIsVisited(node, true); - if (node.right !== SENTINEL && !node.right.visited) { + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { // go right delta += node.delta; node = node.right; @@ -451,7 +457,7 @@ function searchForEditing(T: IntervalTree, start: number, end: number): Interval } if (T.root) { - T.root.visited = false; + setNodeIsVisited(T.root, false); } return result; @@ -469,10 +475,10 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt let nodeMaxEnd = 0; let nodeStart = 0; while (node !== SENTINEL) { - if (node.visited) { + if (getNodeIsVisited(node)) { // going up from this node - node.left.visited = false; - node.right.visited = false; + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); if (node === node.parent.right) { delta -= node.parent.delta; } @@ -481,13 +487,13 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt continue; } - if (!node.left.visited) { + if (!getNodeIsVisited(node.left)) { // first time seeing this node nodeMaxEnd = delta + node.maxEnd; if (nodeMaxEnd < start) { // cover case b) from above // there is no need to search this node or its children - node.visited = true; + setNodeIsVisited(node, true); continue; } @@ -506,13 +512,13 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt node.delta += (textLength - (end - start)); // cover case a) from above // there is no need to search this node or its right subtree - node.visited = true; + setNodeIsVisited(node, true); continue; } - node.visited = true; + setNodeIsVisited(node, true); - if (node.right !== SENTINEL && !node.right.visited) { + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { // go right delta += node.delta; node = node.right; @@ -521,7 +527,7 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt } if (T.root) { - T.root.visited = false; + setNodeIsVisited(T.root, false); } } @@ -533,15 +539,15 @@ function nodeCount(T: IntervalTree): number { let node = T.root; let count = 0; while (node !== SENTINEL) { - if (node.visited) { + if (getNodeIsVisited(node)) { // going up from this node - node.left.visited = false; - node.right.visited = false; + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); node = node.parent; continue; } - if (node.left !== SENTINEL && !node.left.visited) { + if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { // go left node = node.left; continue; @@ -549,9 +555,9 @@ function nodeCount(T: IntervalTree): number { // handle current node count++; - node.visited = true; + setNodeIsVisited(node, true); - if (node.right !== SENTINEL && !node.right.visited) { + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { // go right node = node.right; continue; @@ -559,7 +565,7 @@ function nodeCount(T: IntervalTree): number { } if (T.root) { - T.root.visited = false; + setNodeIsVisited(T.root, false); } return count; @@ -570,15 +576,15 @@ function collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] let result: IntervalNode[] = []; let resultLen = 0; while (node !== SENTINEL) { - if (node.visited) { + if (getNodeIsVisited(node)) { // going up from this node - node.left.visited = false; - node.right.visited = false; + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); node = node.parent; continue; } - if (node.left !== SENTINEL && !node.left.visited) { + if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { // go left node = node.left; continue; @@ -589,9 +595,9 @@ function collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] result[resultLen++] = node; } - node.visited = true; + setNodeIsVisited(node, true); - if (node.right !== SENTINEL && !node.right.visited) { + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { // go right node = node.right; continue; @@ -599,7 +605,7 @@ function collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] } if (T.root) { - T.root.visited = false; + setNodeIsVisited(T.root, false); } return result; @@ -613,10 +619,10 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo let result: IntervalNode[] = []; let resultLen = 0; while (node !== SENTINEL) { - if (node.visited) { + if (getNodeIsVisited(node)) { // going up from this node - node.left.visited = false; - node.right.visited = false; + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); if (node === node.parent.right) { delta -= node.parent.delta; } @@ -624,7 +630,7 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo continue; } - if (node.left !== SENTINEL && !node.left.visited) { + if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { // go left node = node.left; continue; @@ -650,9 +656,9 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo result[resultLen++] = node; } - node.visited = true; + setNodeIsVisited(node, true); - if (node.right !== SENTINEL && !node.right.visited) { + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { // go right delta += node.delta; node = node.right; @@ -661,7 +667,7 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo } if (T.root) { - T.root.visited = false; + setNodeIsVisited(T.root, false); } return result; @@ -683,10 +689,10 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num let result: IntervalNode[] = []; let resultLen = 0; while (node !== SENTINEL) { - if (node.visited) { + if (getNodeIsVisited(node)) { // going up from this node - node.left.visited = false; - node.right.visited = false; + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); if (node === node.parent.right) { delta -= node.parent.delta; } @@ -694,13 +700,13 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num continue; } - if (!node.left.visited) { + if (!getNodeIsVisited(node.left)) { // first time seeing this node nodeMaxEnd = delta + node.maxEnd; if (nodeMaxEnd < intervalStart) { // cover case b) from above // there is no need to search this node or its children - node.visited = true; + setNodeIsVisited(node, true); continue; } @@ -716,7 +722,7 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num if (nodeStart > intervalEnd) { // cover case a) from above // there is no need to search this node or its right subtree - node.visited = true; + setNodeIsVisited(node, true); continue; } @@ -739,9 +745,9 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num } } - node.visited = true; + setNodeIsVisited(node, true); - if (node.right !== SENTINEL && !node.right.visited) { + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { // go right delta += node.delta; node = node.right; @@ -750,7 +756,7 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num } if (T.root) { - T.root.visited = false; + setNodeIsVisited(T.root, false); } return result; From bc2ff777daa54719a6556561446c633a1c4aa088 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 17:27:38 +0200 Subject: [PATCH 233/394] Binary encode node.isForValidation --- src/vs/editor/common/editorCommon.ts | 4 ---- src/vs/editor/common/model/intervalTree.ts | 19 +++++++++++++------ src/vs/monaco.d.ts | 4 ---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index cc577de02dd..a346ca6ea9d 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -157,10 +157,6 @@ export interface IModelDecoration { * Options associated with this decoration. */ readonly options: IModelDecorationOptions; - /** - * A flag describing if this is a problem decoration (e.g. warning/error). - */ - readonly isForValidation: boolean; } /** diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 9a776340644..2d6e1ce9e09 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -68,6 +68,14 @@ function setNodeIsVisited(node: IntervalNode, value: boolean): void { (node.metadata & Constants.IsVisitedMaskInverse) | ((value ? 1 : 0) << Constants.IsVisitedOffset) ); } +function getNodeIsForValidation(node: IntervalNode): boolean { + return ((node.metadata & Constants.IsForValidationMask) >>> Constants.IsForValidationOffset) === 1; +} +function setNodeIsForValidation(node: IntervalNode, value: boolean): void { + node.metadata = ( + (node.metadata & Constants.IsForValidationMaskInverse) | ((value ? 1 : 0) << Constants.IsForValidationOffset) + ); +} export class IntervalNode implements IModelDecoration { @@ -88,7 +96,6 @@ export class IntervalNode implements IModelDecoration { public id: string; public ownerId: number; public options: ModelDecorationOptions; - public isForValidation: boolean; public stickiness: TrackedRangeStickiness; public cachedVersionId: number; @@ -112,7 +119,7 @@ export class IntervalNode implements IModelDecoration { this.id = id; this.ownerId = 0; this.options = null; - this.isForValidation = false; + setNodeIsForValidation(this, false); this.stickiness = TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges; this.cachedVersionId = 0; @@ -135,10 +142,10 @@ export class IntervalNode implements IModelDecoration { public setOptions(options: ModelDecorationOptions) { this.options = options; - this.isForValidation = ( + setNodeIsForValidation(this, ( this.options.className === ClassName.EditorErrorDecoration || this.options.className === ClassName.EditorWarningDecoration - ); + )); this.stickiness = this.options.stickiness; } @@ -646,7 +653,7 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) { include = false; } - if (filterOutValidation && node.isForValidation) { + if (filterOutValidation && getNodeIsForValidation(node)) { include = false; } if (overviewRulerOnly && !node.options.overviewRuler.color) { @@ -736,7 +743,7 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) { include = false; } - if (filterOutValidation && node.isForValidation) { + if (filterOutValidation && getNodeIsForValidation(node)) { include = false; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 7874e3fd4fb..776a314bbc9 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1188,10 +1188,6 @@ declare module monaco.editor { * Options associated with this decoration. */ readonly options: IModelDecorationOptions; - /** - * A flag describing if this is a problem decoration (e.g. warning/error). - */ - readonly isForValidation: boolean; } /** From 1d8e120e1c9ff55cdb34c4fc419999be5b0663ba Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 17:37:47 +0200 Subject: [PATCH 234/394] Binary encode node.stickiness --- src/vs/editor/common/model/intervalTree.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 2d6e1ce9e09..5c6c31fdc07 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -76,6 +76,14 @@ function setNodeIsForValidation(node: IntervalNode, value: boolean): void { (node.metadata & Constants.IsForValidationMaskInverse) | ((value ? 1 : 0) << Constants.IsForValidationOffset) ); } +function getNodeStickiness(node: IntervalNode): TrackedRangeStickiness { + return ((node.metadata & Constants.StickinessMask) >>> Constants.StickinessOffset); +} +function setNodeStickiness(node: IntervalNode, stickiness: TrackedRangeStickiness): void { + node.metadata = ( + (node.metadata & Constants.StickinessMaskInverse) | (stickiness << Constants.StickinessOffset) + ); +} export class IntervalNode implements IModelDecoration { @@ -96,7 +104,6 @@ export class IntervalNode implements IModelDecoration { public id: string; public ownerId: number; public options: ModelDecorationOptions; - public stickiness: TrackedRangeStickiness; public cachedVersionId: number; public cachedAbsoluteStart: number; @@ -120,7 +127,7 @@ export class IntervalNode implements IModelDecoration { this.ownerId = 0; this.options = null; setNodeIsForValidation(this, false); - this.stickiness = TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges; + setNodeStickiness(this, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); this.cachedVersionId = 0; this.cachedAbsoluteStart = start; @@ -146,7 +153,7 @@ export class IntervalNode implements IModelDecoration { this.options.className === ClassName.EditorErrorDecoration || this.options.className === ClassName.EditorWarningDecoration )); - this.stickiness = this.options.stickiness; + setNodeStickiness(this, this.options.stickiness); } public setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void { @@ -329,13 +336,14 @@ function adjustMarkerBeforeColumn(markerOffset: number, markerStickToPreviousCha * as when decorations were implemented using two markers. */ function nodeAcceptEdit(node: IntervalNode, start: number, end: number, textLength: number, forceMoveMarkers: boolean): void { + const nodeStickiness = getNodeStickiness(node); const startStickToPreviousCharacter = ( - node.stickiness === TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges - || node.stickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore + nodeStickiness === TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges + || nodeStickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore ); const endStickToPreviousCharacter = ( - node.stickiness === TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges - || node.stickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore + nodeStickiness === TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges + || nodeStickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore ); const deletingCnt = (end - start); From 08f63f82febd3b8b2e7ce4df6dbaa5069d1e064d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 17:41:06 +0200 Subject: [PATCH 235/394] smoke: more timeouts... --- test/smoke/src/areas/editor/editor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index b69cfbacc4b..001cd9d4cb3 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -110,7 +110,9 @@ export class Editor { // https://github.com/Microsoft/vscode/issues/34203#issuecomment-334441786 this.spectron.app.electron.clipboard.writeText(text); + await new Promise(c => setTimeout(c, 100)); this.spectron.app.webContents.paste(); + await new Promise(c => setTimeout(c, 100)); await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } From b4fdeadbb801663c5631bf156f2475f7bcfeaf9f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 17:59:22 +0200 Subject: [PATCH 236/394] Adopt new configuration change event in markers and preferences areas --- .../parts/markers/browser/markersPanel.ts | 15 +++------------ .../preferences/browser/preferencesRenderers.ts | 10 ++++++++-- .../preferences/common/preferencesContribution.ts | 6 +++++- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/parts/markers/browser/markersPanel.ts b/src/vs/workbench/parts/markers/browser/markersPanel.ts index 13305518c4e..5c811c3b975 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanel.ts @@ -19,7 +19,7 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer import { Panel } from 'vs/workbench/browser/panel'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import Constants from 'vs/workbench/parts/markers/common/constants'; -import { IProblemsConfiguration, MarkersModel, Marker, Resource, FilterOptions } from 'vs/workbench/parts/markers/common/markersModel'; +import { MarkersModel, Marker, Resource, FilterOptions } from 'vs/workbench/parts/markers/common/markersModel'; import { Controller } from 'vs/workbench/parts/markers/browser/markersTreeController'; import Tree = require('vs/base/parts/tree/browser/tree'); import TreeImpl = require('vs/base/parts/tree/browser/treeImpl'); @@ -47,7 +47,6 @@ export class MarkersPanel extends Panel { private lastSelectedRelativeTop: number = 0; private currentActiveResource: URI = null; - private hasToAutoReveal: boolean; private tree: Tree.ITree; private autoExpanded: Set; @@ -90,9 +89,6 @@ export class MarkersPanel extends Panel { dom.addClass(parent.getHTMLElement(), 'markers-panel'); - const conf = this.configurationService.getConfiguration(); - this.onConfigurationsUpdated(conf); - let container = dom.append(parent.getHTMLElement(), dom.$('.markers-panel-container')); this.createMessageBox(container); @@ -253,7 +249,6 @@ export class MarkersPanel extends Panel { } private createListeners(): void { - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationsUpdated(this.configurationService.getConfiguration()))); this.toUnbind.push(this.markerService.onMarkerChanged(this.onMarkerChanged, this)); this.toUnbind.push(this.editorGroupService.onEditorsChanged(this.onEditorsChanged, this)); this.toUnbind.push(this.tree.addListener('selection', () => this.onSelected())); @@ -289,10 +284,6 @@ export class MarkersPanel extends Panel { this.autoReveal(); } - private onConfigurationsUpdated(conf: IProblemsConfiguration): void { - this.hasToAutoReveal = conf && conf.problems && conf.problems.autoReveal; - } - private onSelected(): void { let selection = this.tree.getSelection(); if (selection && selection.length > 0) { @@ -338,8 +329,8 @@ export class MarkersPanel extends Panel { } private autoReveal(focus: boolean = false): void { - let conf = this.configurationService.getConfiguration(); - if (conf && conf.problems && conf.problems.autoReveal) { + let autoReveal = this.configurationService.getValue('problems.autoReveal'); + if (typeof autoReveal === 'boolean' && autoReveal) { this.revealMarkersForCurrentActiveEditor(focus); } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 151446902f8..08edba32488 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -31,7 +31,7 @@ import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorE import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { MarkdownString } from 'vs/base/common/htmlContent'; -import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; export interface IPreferencesRenderer extends IDisposable { preferencesModel: IPreferencesEditorModel; @@ -950,7 +950,7 @@ class UnsupportedWorkspaceSettingsRenderer extends Disposable { @IMarkerService private markerService: IMarkerService ) { super(); - this._register(this.configurationService.onDidChangeConfiguration(() => this.render())); + this._register(this.configurationService.onDidChangeConfiguration(e => this.onDidConfigurationChange(e))); } private getMarkerMessage(settingKey: string): string { @@ -987,6 +987,12 @@ class UnsupportedWorkspaceSettingsRenderer extends Disposable { } } + private onDidConfigurationChange(event: IConfigurationChangeEvent): void { + if (event.source === ConfigurationTarget.DEFAULT || event.source === ConfigurationTarget.WORKSPACE || event.source === ConfigurationTarget.WORKSPACE_FOLDER) { + this.render(); + } + } + public dispose(): void { this.markerService.remove('preferencesEditor', [this.workspaceSettingsEditorModel.uri]); super.dispose(); diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index db5b54b3fb7..f93a4021f38 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -38,7 +38,11 @@ export class PreferencesContribution implements IWorkbenchContribution { @IWorkspaceContextService private workspaceService: IWorkspaceContextService, @IConfigurationService private configurationService: IConfigurationService ) { - this.settingsListener = this.configurationService.onDidChangeConfiguration(() => this.handleSettingsEditorOverride()); + this.settingsListener = this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(DEFAULT_SETTINGS_EDITOR_SETTING)) { + this.handleSettingsEditorOverride(); + } + }); this.handleSettingsEditorOverride(); this.start(); From 5c03b21db4ae5da915d8db9ef1f3e830106e6597 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 18 Oct 2017 18:03:32 +0200 Subject: [PATCH 237/394] smoke: use textarea for typing in editor --- test/smoke/src/areas/editor/editor.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 001cd9d4cb3..499f0fe6196 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -109,10 +109,19 @@ export class Editor { await this.spectron.client.waitForActiveElement(textarea); // https://github.com/Microsoft/vscode/issues/34203#issuecomment-334441786 - this.spectron.app.electron.clipboard.writeText(text); - await new Promise(c => setTimeout(c, 100)); - this.spectron.app.webContents.paste(); - await new Promise(c => setTimeout(c, 100)); + await this.spectron.client.spectron.client.selectorExecute(textarea, (elements, text) => { + const textarea = (Array.isArray(elements) ? elements : [elements])[0] as HTMLTextAreaElement; + const start = textarea.selectionStart; + const newStart = start + text.length; + const value = textarea.value; + const newValue = value.substr(0, start) + text + value.substr(start); + + textarea.value = newValue; + textarea.setSelectionRange(newStart, newStart); + + const event = new Event('input', { 'bubbles': true, 'cancelable': true }); + textarea.dispatchEvent(event); + }, text); await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } From 004ad5cec5b1ffcea2d2740a5ebaaf684fc9ccdc Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Oct 2017 18:21:01 +0200 Subject: [PATCH 238/394] remvoe compositebar.css --- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index eeb504452c4..008593728c4 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -5,7 +5,6 @@ 'use strict'; -import 'vs/css!./media/compositeBar'; import nls = require('vs/nls'); import { Action } from 'vs/base/common/actions'; import { illegalArgument } from 'vs/base/common/errors'; From 6f1b4c9aa82d7be2e5479fcf0b2f3f17f32b7683 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 18:27:42 +0200 Subject: [PATCH 239/394] Adopt to new configuration change event --- .../walkThrough/electron-browser/walkThroughPart.ts | 6 +++++- .../services/files/electron-browser/fileService.ts | 10 ++++++---- .../files/node/watcher/nsfw/watcherService.ts | 6 +++++- .../services/mode/common/workbenchModeService.ts | 13 ++++++++----- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts index 8c3e14e3123..84757bd9881 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts @@ -452,7 +452,11 @@ export class WalkThroughPart extends BaseEditor { }); this.updateSizeClasses(); this.multiCursorModifier(); - this.contentDisposables.push(this.configurationService.onDidChangeConfiguration(() => this.multiCursorModifier())); + this.contentDisposables.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('editor.multiCursorModifier')) { + this.multiCursorModifier(); + } + })); if (input.onReady) { input.onReady(innerContent); } diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 270f2367a64..cf46014fe39 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -13,7 +13,7 @@ import errors = require('vs/base/common/errors'); import uri from 'vs/base/common/uri'; import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent, ICreateFileOptions } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Action } from 'vs/base/common/actions'; import { IMessageService, IMessageWithAction, Severity, CloseAction } from 'vs/platform/message/common/message'; @@ -119,7 +119,7 @@ export class FileService implements IFileService { this.toUnbind.push(this.raw.onAfterOperation(e => this._onAfterOperation.fire(e))); // Config changes - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(e))); // Root changes this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); @@ -142,8 +142,10 @@ export class FileService implements IFileService { return encodingOverride; } - private onConfigurationChange(configuration: IFilesConfiguration): void { - this.updateOptions(configuration.files); + private onConfigurationChange(event: IConfigurationChangeEvent): void { + if (event.affectsConfiguration('files')) { + this.updateOptions(this.configurationService.getConfiguration('files')); + } } public updateOptions(options: object): void { diff --git a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts index 6c54ae8d675..b8c93d184de 100644 --- a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts @@ -83,7 +83,11 @@ export class FileWatcher { // Start watching this.updateFolders(); this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateFolders())); - this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.updateFolders())); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('files.watcherExclude')) { + this.updateFolders(); + } + })); return () => this.dispose(); } diff --git a/src/vs/workbench/services/mode/common/workbenchModeService.ts b/src/vs/workbench/services/mode/common/workbenchModeService.ts index abd67ba5a18..ad3c007b72c 100644 --- a/src/vs/workbench/services/mode/common/workbenchModeService.ts +++ b/src/vs/workbench/services/mode/common/workbenchModeService.ts @@ -123,7 +123,11 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { }); - this._configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this._configurationService.getConfiguration())); + this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('files.associations')) { + this.updateMime(); + } + }); this.onDidCreateMode((mode) => { this._extensionService.activateByEvent(`onLanguage:${mode.getId()}`).done(null, onUnexpectedError); @@ -132,10 +136,8 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { protected _onReady(): TPromise { if (!this._onReadyPromise) { - const configuration = this._configurationService.getConfiguration(); this._onReadyPromise = this._extensionService.onReady().then(() => { - this.onConfigurationChange(configuration); - + this.updateMime(); return true; }); } @@ -143,7 +145,8 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { return this._onReadyPromise; } - private onConfigurationChange(configuration: IFilesConfiguration): void { + private updateMime(): void { + const configuration = this._configurationService.getConfiguration(); // Clear user configured mime associations mime.clearTextMimes(true /* user configured */); From 7424b934292d9a1fb6e4309ff9547660eab27a80 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 18 Oct 2017 20:32:19 +0200 Subject: [PATCH 240/394] Fix #36134 --- src/vs/workbench/api/browser/viewsExtensionPoint.ts | 3 ++- src/vs/workbench/browser/parts/views/viewsRegistry.ts | 2 ++ src/vs/workbench/browser/parts/views/viewsViewlet.ts | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index d23f88532b1..0ebf0e9893d 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -108,7 +108,8 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyV ctor: TreeView, location, when: ContextKeyExpr.deserialize(item.when), - canToggleVisibility: true + canToggleVisibility: true, + collapsed: true }; // validate diff --git a/src/vs/workbench/browser/parts/views/viewsRegistry.ts b/src/vs/workbench/browser/parts/views/viewsRegistry.ts index fbdc2e1c425..e39b999ec43 100644 --- a/src/vs/workbench/browser/parts/views/viewsRegistry.ts +++ b/src/vs/workbench/browser/parts/views/viewsRegistry.ts @@ -48,6 +48,8 @@ export interface IViewDescriptor { readonly size?: number; + readonly collapsed?: boolean; + readonly canToggleVisibility?: boolean; } diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 29e5639eacd..96ef5e0c9de 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -400,7 +400,7 @@ export class ViewsViewlet extends PanelViewlet { id: viewDescriptor.id, name: viewDescriptor.name, actionRunner: this.getActionRunner(), - expanded: !(viewState ? viewState.collapsed : void 0), + expanded: !(viewState ? viewState.collapsed : viewDescriptor.collapsed), viewletSettings: this.viewletSettings }); toCreate.push(view); From 509eecf0b5c2cd66a18479d66dd0ad42cacd3ba3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 21:32:12 +0200 Subject: [PATCH 241/394] Update decorations when there is an EOL change --- src/vs/editor/common/model/intervalTree.ts | 39 ++++++++++++++++++- src/vs/editor/common/model/textModel.ts | 9 ++++- .../common/model/textModelWithDecorations.ts | 34 ++++++++++++++++ .../common/model/modelDecorations.test.ts | 30 +++++++++++++- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 5c6c31fdc07..d342c8eccf7 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -88,7 +88,7 @@ function setNodeStickiness(node: IntervalNode, stickiness: TrackedRangeStickines export class IntervalNode implements IModelDecoration { /** - * contains binary encoded information for color, isForValidation, visited, and stickiness. + * contains binary encoded information for color, visited, isForValidation and stickiness. */ public metadata: number; @@ -265,6 +265,10 @@ export class IntervalTree { } } + public recomputeAllMaxEnds(): void { + recomputeAllMaxEnds(this); + } + public assertInvariants(): void { assert(getNodeColor(SENTINEL) === NodeColor.Black); assert(SENTINEL.parent === SENTINEL); @@ -1130,6 +1134,39 @@ function rightRotate(T: IntervalTree, y: IntervalNode): void { //#region max end computation +function recomputeAllMaxEnds(T: IntervalTree): void { + let node = T.root; + while (node !== SENTINEL) { + if (getNodeIsVisited(node)) { + // going up from this node + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); + node = node.parent; + continue; + } + + if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { + // go left + node = node.left; + continue; + } + + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { + // go right + node = node.right; + continue; + } + + // handle current node + recomputeMaxEnd(node); + setNodeIsVisited(node, true); + } + + if (T.root) { + setNodeIsVisited(T.root, false); + } +} + function computeMaxEnd(node: IntervalNode): number { let maxEnd = node.end; if (node.left !== SENTINEL) { diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index b5eb35f4e52..aa93b0ed106 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -510,8 +510,13 @@ export class TextModel implements editorCommon.ITextModel { return this._EOL; } + protected _onBeforeEOLChange(): void { + } + + protected _onAfterEOLChange(): void { + } + public setEOL(eol: editorCommon.EndOfLineSequence): void { - // TODO@interval!!! this._assertNotDisposed(); const newEOL = (eol === editorCommon.EndOfLineSequence.CRLF ? '\r\n' : '\n'); if (this._EOL === newEOL) { @@ -524,9 +529,11 @@ export class TextModel implements editorCommon.ITextModel { const endLineNumber = this.getLineCount(); const endColumn = this.getLineMaxColumn(endLineNumber); + this._onBeforeEOLChange(); this._EOL = newEOL; this._constructLineStarts(); this._increaseVersionId(); + this._onAfterEOLChange(); this._emitModelRawContentChangedEvent( new textModelEvents.ModelRawContentChangedEvent( diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 80c7529764c..e04cdc485fa 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -100,6 +100,40 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._decorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers); } + protected _onBeforeEOLChange(): void { + super._onBeforeEOLChange(); + + // Ensure all decorations get their `range` set. + const versionId = this.getVersionId(); + const allDecorations = this._decorationsTree.search(0, false, false, versionId); + this._ensureNodesHaveRanges(allDecorations); + } + + protected _onAfterEOLChange(): void { + super._onAfterEOLChange(); + + // Transform back `range` to offsets + const versionId = this.getVersionId(); + const allDecorations = this._decorationsTree.search(0, false, false, versionId); + for (let i = 0, len = allDecorations.length; i < len; i++) { + const node = allDecorations[i]; + + const delta = node.cachedAbsoluteStart - node.start; + + const startOffset = this._lineStarts.getAccumulatedValue(node.range.startLineNumber - 2) + node.range.startColumn - 1; + const endOffset = this._lineStarts.getAccumulatedValue(node.range.endLineNumber - 2) + node.range.endColumn - 1; + + node.cachedAbsoluteStart = startOffset; + node.cachedAbsoluteEnd = endOffset; + node.cachedVersionId = versionId; + + node.start = startOffset - delta; + node.end = endOffset - delta; + } + + this._decorationsTree.recomputeAllMaxEnds(); + } + public changeDecorations(callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T { this._assertNotDisposed(); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 26b004d0a0c..0a7ff4e3d8f 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; -import { IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; +import { IModelDeltaDecoration, TrackedRangeStickiness, EndOfLineSequence } from 'vs/editor/common/editorCommon'; import { Model } from 'vs/editor/common/model/model'; // --------- utils @@ -28,7 +28,7 @@ function modelHasDecorations(model: Model, decorations: ILightWeightDecoration2[ }); } modelDecorations.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range)); - assert.deepEqual(modelDecorations, decorations, 'Model decorations'); + assert.deepEqual(modelDecorations, decorations); } function modelHasDecoration(model: Model, startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, className: string) { @@ -351,6 +351,32 @@ suite('Editor Model - Model Decorations', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 3, 1))]); modelHasDecoration(thisModel, 1, 1, 2, 1, 'myType'); }); + + test('decorations are updated when changing EOL', () => { + addDecoration(thisModel, 1, 2, 4, 1, 'myType1'); + addDecoration(thisModel, 1, 3, 4, 1, 'myType2'); + addDecoration(thisModel, 1, 4, 4, 1, 'myType3'); + addDecoration(thisModel, 1, 5, 4, 1, 'myType4'); + addDecoration(thisModel, 1, 6, 4, 1, 'myType5'); + addDecoration(thisModel, 1, 7, 4, 1, 'myType6'); + addDecoration(thisModel, 1, 8, 4, 1, 'myType7'); + addDecoration(thisModel, 1, 9, 4, 1, 'myType8'); + addDecoration(thisModel, 1, 10, 4, 1, 'myType9'); + thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'x')]); + thisModel.setEOL(EndOfLineSequence.CRLF); + thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'x')]); + modelHasDecorations(thisModel, [ + { range: new Range(1, 4, 4, 1), className: 'myType1' }, + { range: new Range(1, 5, 4, 1), className: 'myType2' }, + { range: new Range(1, 6, 4, 1), className: 'myType3' }, + { range: new Range(1, 7, 4, 1), className: 'myType4' }, + { range: new Range(1, 8, 4, 1), className: 'myType5' }, + { range: new Range(1, 9, 4, 1), className: 'myType6' }, + { range: new Range(1, 10, 4, 1), className: 'myType7' }, + { range: new Range(1, 11, 4, 1), className: 'myType8' }, + { range: new Range(1, 12, 4, 1), className: 'myType9' }, + ]); + }); }); suite('Decorations and editing', () => { From ba81d4affc7a189a7c32c59d7306c04f250251e8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 18 Oct 2017 22:27:48 +0200 Subject: [PATCH 242/394] Fix range caching logic in decorations --- src/vs/editor/common/model/intervalTree.ts | 84 ++++++++++--------- .../common/model/textModelWithDecorations.ts | 8 +- .../test/common/sortLinesCommand.test.ts | 4 +- .../common/model/modelDecorations.test.ts | 8 ++ 4 files changed, 57 insertions(+), 47 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index d342c8eccf7..d45aeef43b6 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -157,14 +157,12 @@ export class IntervalNode implements IModelDecoration { } public setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void { - this.cachedVersionId = cachedVersionId; - if (this.cachedAbsoluteStart === absoluteStart && this.cachedAbsoluteEnd === absoluteEnd) { - // no change - return; + if (this.cachedVersionId !== cachedVersionId) { + this.range = null; } + this.cachedVersionId = cachedVersionId; this.cachedAbsoluteStart = absoluteStart; this.cachedAbsoluteEnd = absoluteEnd; - this.range = null; } public detach(): void { @@ -265,8 +263,8 @@ export class IntervalTree { } } - public recomputeAllMaxEnds(): void { - recomputeAllMaxEnds(this); + public collectNodesPostOrder(): IntervalNode[] { + return collectNodesPostOrder(this); } public assertInvariants(): void { @@ -630,6 +628,43 @@ function collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] return result; } +function collectNodesPostOrder(T: IntervalTree): IntervalNode[] { + let node = T.root; + let result: IntervalNode[] = []; + let resultLen = 0; + while (node !== SENTINEL) { + if (getNodeIsVisited(node)) { + // going up from this node + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); + node = node.parent; + continue; + } + + if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { + // go left + node = node.left; + continue; + } + + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { + // go right + node = node.right; + continue; + } + + // handle current node + result[resultLen++] = node; + setNodeIsVisited(node, true); + } + + if (T.root) { + setNodeIsVisited(T.root, false); + } + + return result; +} + function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { let node = T.root; let delta = 0; @@ -1134,39 +1169,6 @@ function rightRotate(T: IntervalTree, y: IntervalNode): void { //#region max end computation -function recomputeAllMaxEnds(T: IntervalTree): void { - let node = T.root; - while (node !== SENTINEL) { - if (getNodeIsVisited(node)) { - // going up from this node - setNodeIsVisited(node.left, false); - setNodeIsVisited(node.right, false); - node = node.parent; - continue; - } - - if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { - // go left - node = node.left; - continue; - } - - if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { - // go right - node = node.right; - continue; - } - - // handle current node - recomputeMaxEnd(node); - setNodeIsVisited(node, true); - } - - if (T.root) { - setNodeIsVisited(T.root, false); - } -} - function computeMaxEnd(node: IntervalNode): number { let maxEnd = node.end; if (node.left !== SENTINEL) { @@ -1184,7 +1186,7 @@ function computeMaxEnd(node: IntervalNode): number { return maxEnd; } -function recomputeMaxEnd(node: IntervalNode): void { +export function recomputeMaxEnd(node: IntervalNode): void { node.maxEnd = computeMaxEnd(node); } diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index e04cdc485fa..0418026b506 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -15,7 +15,7 @@ import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; -import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; +import { IntervalNode, IntervalTree, recomputeMaxEnd } from 'vs/editor/common/model/intervalTree'; let _INSTANCE_COUNT = 0; /** @@ -114,7 +114,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi // Transform back `range` to offsets const versionId = this.getVersionId(); - const allDecorations = this._decorationsTree.search(0, false, false, versionId); + const allDecorations = this._decorationsTree.collectNodesPostOrder(); for (let i = 0, len = allDecorations.length; i < len; i++) { const node = allDecorations[i]; @@ -129,9 +129,9 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi node.start = startOffset - delta; node.end = endOffset - delta; - } - this._decorationsTree.recomputeAllMaxEnds(); + recomputeMaxEnd(node); + } } public changeDecorations(callback: (changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T { diff --git a/src/vs/editor/contrib/linesOperations/test/common/sortLinesCommand.test.ts b/src/vs/editor/contrib/linesOperations/test/common/sortLinesCommand.test.ts index ec19e7bbe0d..58aa224ff6c 100644 --- a/src/vs/editor/contrib/linesOperations/test/common/sortLinesCommand.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/common/sortLinesCommand.test.ts @@ -77,7 +77,7 @@ suite('Editor Contrib - Sort Lines Command', () => { 'third line', 'fifth' ], - new Selection(3, 3, 4, 2) + new Selection(3, 3, 4, 1) ); }); @@ -119,7 +119,7 @@ suite('Editor Contrib - Sort Lines Command', () => { 'second line', 'third line', ], - new Selection(1, 1, 5, 6) + new Selection(1, 1, 5, 11) ); }); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 0a7ff4e3d8f..b4485b014de 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -377,6 +377,14 @@ suite('Editor Model - Model Decorations', () => { { range: new Range(1, 12, 4, 1), className: 'myType9' }, ]); }); + + test('an apparently simple edit', () => { + addDecoration(thisModel, 1, 2, 4, 1, 'myType1'); + thisModel.applyEdits([EditOperation.replace(new Range(1, 14, 2, 1), 'x')]); + modelHasDecorations(thisModel, [ + { range: new Range(1, 2, 3, 1), className: 'myType1' }, + ]); + }); }); suite('Decorations and editing', () => { From 4b01451cea60f32412098735709fddcac567b33d Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 10:01:54 +0200 Subject: [PATCH 243/394] fixes #36529 --- .../browser/parts/activitybar/activitybarActions.ts | 3 ++- .../browser/parts/activitybar/activitybarPart.ts | 5 +++-- .../browser/parts/compositebar/compositeBar.ts | 6 ++++-- .../browser/parts/compositebar/compositeBarActions.ts | 11 +++++++---- src/vs/workbench/browser/parts/panel/panelPart.ts | 3 ++- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 04c486ec533..b5d0dfb4876 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -20,6 +20,7 @@ import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colo import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; import { ActivityAction, ActivityActionItem } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; export class ViewletActivityAction extends ActivityAction { @@ -97,7 +98,7 @@ export class GlobalActivityActionItem extends ActivityActionItem { @IThemeService themeService: IThemeService, @IContextMenuService protected contextMenuService: IContextMenuService ) { - super(action, { draggable: false }, themeService); + super(action, { draggable: false, backgroundColor: ACTIVITY_BAR_FOREGROUND }, themeService); } public render(container: HTMLElement): void { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 56d4fa0d7ef..842b4f2d76f 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -27,7 +27,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER } from 'vs/workbench/common/theme'; +import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; @@ -68,7 +68,8 @@ export class ActivitybarPart extends Part implements IActivityBarService { getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.viewletService.getViewlet(compositeId), this.compositeBar), getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), - hidePart: () => this.partService.setSideBarHidden(true) + hidePart: () => this.partService.setSideBarHidden(true), + backgroundColor: ACTIVITY_BAR_FOREGROUND }); this.registerListeners(); } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 008593728c4..37d2ba36ed9 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -25,6 +25,7 @@ export interface ICompositeBarOptions { storageId: string; orientation: ActionsOrientation; composites: { id: string, name: string }[]; + backgroundColor: string; getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; getOnCompositeClickAction: (compositeId: string) => Action; @@ -278,7 +279,8 @@ export class CompositeBar implements ICompositeBar { () => this.getOverflowingComposites(), () => this.activeCompositeId, (compositeId: string) => this.compositeIdToActivityStack[compositeId] && this.compositeIdToActivityStack[compositeId][0].badge, - this.options.getOnCompositeClickAction + this.options.getOnCompositeClickAction, + this.options.backgroundColor ); this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true }); @@ -322,7 +324,7 @@ export class CompositeBar implements ICompositeBar { const compositeActivityAction = this.options.getActivityAction(compositeId); const pinnedAction = this.options.getCompositePinnedAction(compositeId); - this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this); + this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this, this.options.backgroundColor); this.compositeIdToActions[compositeId] = compositeActivityAction; return compositeActivityAction; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 11449e79342..914b4a935c0 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -18,7 +18,7 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activityBarService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; +import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_BADGE_BACKGROUND } from 'vs/workbench/common/theme'; import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -93,6 +93,7 @@ export class ActivityAction extends Action { export interface IActivityActionItemOptions extends IBaseActionItemOptions { icon?: boolean; + backgroundColor: string; } export class ActivityActionItem extends BaseActionItem { @@ -124,7 +125,7 @@ export class ActivityActionItem extends BaseActionItem { // Label if (this.$label) { - const background = theme.getColor(ACTIVITY_BAR_FOREGROUND); + const background = theme.getColor(this.options.backgroundColor); this.$label.style('background-color', background ? background.toString() : null); } @@ -294,11 +295,12 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem { private getActiveCompositeId: () => string, private getBadge: (compositeId: string) => IBadge, private getCompositeOpenAction: (compositeId: string) => Action, + backgroundColor: string, @IInstantiationService private instantiationService: IInstantiationService, @IContextMenuService private contextMenuService: IContextMenuService, @IThemeService themeService: IThemeService ) { - super(action, { icon: true }, themeService); + super(action, { icon: true, backgroundColor }, themeService); this.cssClass = action.class; this.name = action.label; @@ -373,12 +375,13 @@ export class CompositeActionItem extends ActivityActionItem { private compositeActivityAction: ActivityAction, private toggleCompositePinnedAction: Action, private compositeBar: ICompositeBar, + backgroundColor: string, @IContextMenuService private contextMenuService: IContextMenuService, @IKeybindingService private keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService ) { - super(compositeActivityAction, { draggable: true }, themeService); + super(compositeActivityAction, { draggable: true, backgroundColor }, themeService); this.cssClass = compositeActivityAction.class; diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 4956648ba12..b64f22d394f 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -82,7 +82,8 @@ export class PanelPart extends CompositePart implements IPanelService { getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar), getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(OpenPanelAction, this.getPanel(compositeId)), getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), - hidePart: () => this.partService.setPanelHidden(true) + hidePart: () => this.partService.setPanelHidden(true), + backgroundColor: PANEL_BACKGROUND }); this.toUnbind.push(this.compositeBar); From a0796457a8759ddb8092060c7ad79ebefbb902ea Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 10:25:02 +0200 Subject: [PATCH 244/394] Revert "debug: decodeURI before sending it out to adapter" This reverts commit 9c97b8002db556b0e8d2cf1b7df362356e8f585e. --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index d3d1386f87f..2b5446c6602 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -1119,8 +1119,7 @@ export class DebugService implements debug.IDebugService { const breakpointsToSend = this.model.getBreakpoints().filter(bp => this.model.areBreakpointsActivated() && bp.enabled && bp.uri.toString() === modelUri.toString()); const source = process.sources.get(modelUri.toString()); - const path = modelUri.scheme === 'file' || modelUri.scheme === debug.DEBUG_SCHEME ? paths.normalize(modelUri.fsPath, true) : modelUri.toString(); - const rawSource = source ? source.raw : { path: decodeURIComponent(path), name: resources.basenameOrAuthority(modelUri) }; + const rawSource = source ? source.raw : { path: modelUri.scheme === 'file' || modelUri.scheme === debug.DEBUG_SCHEME ? paths.normalize(modelUri.fsPath, true) : modelUri.toString(), name: resources.basenameOrAuthority(modelUri) }; if (breakpointsToSend.length && !rawSource.adapterData) { rawSource.adapterData = breakpointsToSend[0].adapterData; } From 16294b41874c5cc12796d033c7824e9c657c0179 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 11:23:20 +0200 Subject: [PATCH 245/394] Do not emit events when deltaDecorations is a no-op --- .../common/model/textModelWithDecorations.ts | 8 ++++++++ .../test/common/model/modelDecorations.test.ts | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 0418026b506..45fa84e9003 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -166,6 +166,10 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._deltaDecorationsImpl(ownerId, [id], []); }, deltaDecorations: (oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] => { + if (oldDecorations.length === 0 && newDecorations.length === 0) { + // nothing to do + return []; + } this._currentDecorationsTrackerDidChange = true; return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations); } @@ -189,6 +193,10 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi if (!oldDecorations) { oldDecorations = []; } + if (oldDecorations.length === 0 && newDecorations.length === 0) { + // nothing to do + return []; + } try { this._eventEmitter.beginDeferredEmit(); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index b4485b014de..23c02e75b09 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -249,6 +249,21 @@ suite('Editor Model - Model Decorations', () => { assert.equal(listenerCalled, 1, 'listener called'); }); + test('decorations do not emit event on no-op deltaDecorations', () => { + let listenerCalled = 0; + + thisModel.onDidChangeDecorations((e) => { + listenerCalled++; + }); + + thisModel.deltaDecorations([], []); + thisModel.changeDecorations((accessor) => { + accessor.deltaDecorations([], []); + }); + + assert.equal(listenerCalled, 0, 'listener not called'); + }); + // --------- editing text & effects on decorations test('decorations are updated when inserting one line text before it', () => { From 23ce20da2138f429563e87d92451900e8d4fb99e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 19 Oct 2017 11:38:46 +0200 Subject: [PATCH 246/394] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 417c30f2a2a..e3b9e1a4bfe 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "code-oss-dev", "version": "1.18.0", "electronVersion": "1.7.9", - "distro": "59a68f7780bb6571a1460ea00ca7b994126baeda", + "distro": "c5f654b74299fd467966e51a217094851a6fc239", "author": { "name": "Microsoft Corporation" }, From 568f81043611a0de3cb5c704a5b3c5e333d161bd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 11:40:43 +0200 Subject: [PATCH 247/394] Fix NPE in decorations changed listener --- .../contrib/referenceSearch/browser/referencesWidget.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index 42aaeb2fce0..ce7638670eb 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -112,6 +112,10 @@ class DecorationsManager implements IDisposable { this._decorations.forEach((reference, decorationId) => { const newRange = this._editor.getModel().getDecorationRange(decorationId); + if (!newRange) { + return; + } + let ignore = false; if (Range.equalsRange(newRange, reference.range)) { From ea948fba1ccb925cede2ff2998a789ecbfc5d6e9 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 11:45:20 +0200 Subject: [PATCH 248/394] Avoid NPE in removeAllDecorationsWithOwnerId --- src/vs/editor/common/model/textModelWithDecorations.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 45fa84e9003..f9ca8d63475 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -244,6 +244,9 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi } public removeAllDecorationsWithOwnerId(ownerId: number): void { + if (this.isDisposed) { + return; + } const nodes = this._decorationsTree.collectNodesFromOwner(ownerId); for (let i = 0, len = nodes.length; i < len; i++) { const node = nodes[i]; From 4b53050d7522ba05c6c395f4861f97eb8152a903 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 12:08:25 +0200 Subject: [PATCH 249/394] Fix typo --- .../editor/common/model/textModelWithDecorations.ts | 2 +- .../test/common/model/modelDecorations.test.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index f9ca8d63475..a024b227d6d 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -244,7 +244,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi } public removeAllDecorationsWithOwnerId(ownerId: number): void { - if (this.isDisposed) { + if (this._isDisposed) { return; } const nodes = this._decorationsTree.collectNodesFromOwner(ownerId); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index 23c02e75b09..ea402ff32c4 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -400,6 +400,18 @@ suite('Editor Model - Model Decorations', () => { { range: new Range(1, 2, 3, 1), className: 'myType1' }, ]); }); + + test('removeAllDecorationsWithOwnerId can be called after model dispose', () => { + let model = Model.createFromString('asd'); + model.dispose(); + model.removeAllDecorationsWithOwnerId(1); + }); + + test('removeAllDecorationsWithOwnerId works', () => { + thisModel.deltaDecorations([], [{ range: new Range(1, 2, 4, 1), options: { className: 'myType1' } }], 1); + thisModel.removeAllDecorationsWithOwnerId(1); + modelHasNoDecorations(thisModel); + }); }); suite('Decorations and editing', () => { From 76f2d8f815ad41b2939b534d76e803650e90f912 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 12:10:22 +0200 Subject: [PATCH 250/394] Track if decoration is in the overview ruler in IntervalNode.metadata --- src/vs/editor/common/model/intervalTree.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index d45aeef43b6..83d15c75a34 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -47,9 +47,13 @@ const enum Constants { IsForValidationMaskInverse = 0b11111011, IsForValidationOffset = 2, - StickinessMask = 0b00011000, - StickinessMaskInverse = 0b11100111, - StickinessOffset = 3 + IsInOverviewRulerMask = 0b00001000, + IsInOverviewRulerMaskInverse = 0b11110111, + IsInOverviewRulerOffset = 3, + + StickinessMask = 0b00110000, + StickinessMaskInverse = 0b11001111, + StickinessOffset = 4 } function getNodeColor(node: IntervalNode): NodeColor { @@ -76,6 +80,14 @@ function setNodeIsForValidation(node: IntervalNode, value: boolean): void { (node.metadata & Constants.IsForValidationMaskInverse) | ((value ? 1 : 0) << Constants.IsForValidationOffset) ); } +function getNodeIsInOverviewRuler(node: IntervalNode): boolean { + return ((node.metadata & Constants.IsInOverviewRulerMask) >>> Constants.IsInOverviewRulerOffset) === 1; +} +function setNodeIsInOverviewRuler(node: IntervalNode, value: boolean): void { + node.metadata = ( + (node.metadata & Constants.IsInOverviewRulerMaskInverse) | ((value ? 1 : 0) << Constants.IsInOverviewRulerOffset) + ); +} function getNodeStickiness(node: IntervalNode): TrackedRangeStickiness { return ((node.metadata & Constants.StickinessMask) >>> Constants.StickinessOffset); } @@ -128,6 +140,7 @@ export class IntervalNode implements IModelDecoration { this.options = null; setNodeIsForValidation(this, false); setNodeStickiness(this, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); + setNodeIsInOverviewRuler(this, false); this.cachedVersionId = 0; this.cachedAbsoluteStart = start; @@ -154,6 +167,7 @@ export class IntervalNode implements IModelDecoration { || this.options.className === ClassName.EditorWarningDecoration )); setNodeStickiness(this, this.options.stickiness); + setNodeIsInOverviewRuler(this, this.options.overviewRuler.color ? true : false); } public setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void { @@ -703,7 +717,7 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo if (filterOutValidation && getNodeIsForValidation(node)) { include = false; } - if (overviewRulerOnly && !node.options.overviewRuler.color) { + if (overviewRulerOnly && !getNodeIsInOverviewRuler(node)) { include = false; } if (include) { From 31b885de3979518e2ba330262154314a7a970af7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 19 Oct 2017 12:21:13 +0200 Subject: [PATCH 251/394] better fix for global action touch --- .../parts/activitybar/activitybarActions.ts | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index b5d0dfb4876..e02a364582f 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -7,6 +7,7 @@ import 'vs/css!./media/activityaction'; import DOM = require('vs/base/browser/dom'); +import { EventType as TouchEventType } from 'vs/base/browser/touch'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -107,36 +108,27 @@ export class GlobalActivityActionItem extends ActivityActionItem { // Context menus are triggered on mouse down so that an item can be picked // and executed with releasing the mouse over it this.$container.on(DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => { - this.onClick(e); + DOM.EventHelper.stop(e, true); + + const event = new StandardMouseEvent(e); + this.showContextMenu({ x: event.posx, y: event.posy }); }); - // Extra listener for keyboard interaction this.$container.on(DOM.EventType.KEY_UP, (e: KeyboardEvent) => { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { - this.onClick(e); + DOM.EventHelper.stop(e, true); + + this.showContextMenu(this.$container.getHTMLElement()); } }); - } - public onClick(event?: MouseEvent | KeyboardEvent): void { - DOM.EventHelper.stop(event, true); + this.$container.on(TouchEventType.Tap, (e: MouseEvent) => { + DOM.EventHelper.stop(e, true); - // Prevent duplicate menu showing because we already handle MOUSE_DOWN - // (refs: // https://github.com/Microsoft/vscode/issues/36244) - if (event.type === DOM.EventType.CLICK) { - return; - } - - let location: HTMLElement | { x: number, y: number }; - if (event instanceof MouseEvent) { - const mouseEvent = new StandardMouseEvent(event); - location = { x: mouseEvent.posx, y: mouseEvent.posy }; - } else { - location = this.$container.getHTMLElement(); - } - - this.showContextMenu(location); + const event = new StandardMouseEvent(e); + this.showContextMenu({ x: event.posx, y: event.posy }); + }); } private showContextMenu(location: HTMLElement | { x: number, y: number }): void { From d67f3079fdd56ac72504d54b6082388793268b10 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Oct 2017 12:45:46 +0200 Subject: [PATCH 252/394] Fix #36448 --- .../test/common/instantiationServiceMock.ts | 12 +- .../node/configurationService.ts | 7 +- .../node/configurationEditingService.test.ts | 36 +-- .../test/node/configurationService.test.ts | 254 ++++++++++++++++-- .../workbench/test/workbenchTestServices.ts | 7 +- 5 files changed, 258 insertions(+), 58 deletions(-) diff --git a/src/vs/platform/instantiation/test/common/instantiationServiceMock.ts b/src/vs/platform/instantiation/test/common/instantiationServiceMock.ts index 68c03f70da4..fc7287a3167 100644 --- a/src/vs/platform/instantiation/test/common/instantiationServiceMock.ts +++ b/src/vs/platform/instantiation/test/common/instantiationServiceMock.ts @@ -50,7 +50,7 @@ export class TestInstantiationService extends InstantiationService { let property = typeof arg2 === 'string' ? arg2 : arg3; let value = typeof arg2 === 'string' ? arg3 : arg4; - let stubObject = this._create(serviceMock, { stub: true }); + let stubObject = this._create(serviceMock, { stub: true }, service && !property); if (property) { if (stubObject[property]) { if (stubObject[property].hasOwnProperty('restore')) { @@ -85,20 +85,20 @@ export class TestInstantiationService extends InstantiationService { return spy; } - private _create(serviceMock: IServiceMock, options: SinonOptions): any + private _create(serviceMock: IServiceMock, options: SinonOptions, reset?: boolean): any private _create(ctor: any, options: SinonOptions): any - private _create(arg1: any, options: SinonOptions): any { + private _create(arg1: any, options: SinonOptions, reset: boolean = false): any { if (this.isServiceMock(arg1)) { - let service = this._getOrCreateService(arg1, options); + let service = this._getOrCreateService(arg1, options, reset); this._serviceCollection.set(arg1.id, service); return service; } return options.mock ? sinon.mock(arg1) : this._createStub(arg1); } - private _getOrCreateService(serviceMock: IServiceMock, opts: SinonOptions): any { + private _getOrCreateService(serviceMock: IServiceMock, opts: SinonOptions, reset?: boolean): any { let service: any = this._serviceCollection.get(serviceMock.id); - if (service) { + if (!reset && service) { if (opts.mock && service['sinonOptions'] && !!service['sinonOptions'].mock) { return service; } diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 262151b6a7b..e0f5321a8f6 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -149,6 +149,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat updateValue(key: string, value: any, overrides: IConfigurationOverrides): TPromise updateValue(key: string, value: any, target: ConfigurationTarget): TPromise updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): TPromise + updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget, donotNotifyError: boolean): TPromise updateValue(key: string, value: any, arg3?: any, arg4?: any, donotNotifyError?: any): TPromise { assert.ok(this.configurationEditingService, 'Workbench is not initialized yet'); const overrides = isConfigurationOverrides(arg3) ? arg3 : void 0; @@ -199,7 +200,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.onWorkspaceFolderConfigurationChanged(this.workspace.folders[0], key); } if (workbenchState === WorkbenchState.WORKSPACE) { - return this.onWorkspaceConfigurationChanged(); + return this.workspaceConfiguration.reload().then(() => this.onWorkspaceConfigurationChanged()); } return TPromise.as(null); } @@ -564,7 +565,7 @@ class WorkspaceConfiguration extends Disposable { load(workspaceConfigPath: URI): TPromise { if (this._workspaceConfigPath && this._workspaceConfigPath.fsPath === workspaceConfigPath.fsPath) { - return this._reload(); + return this.reload(); } this._workspaceConfigPath = workspaceConfigPath; @@ -590,7 +591,7 @@ class WorkspaceConfiguration extends Disposable { return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModel(); } - private _reload(): TPromise { + reload(): TPromise { return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => c(null))); } diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index 42fe3290875..f1847573483 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -18,7 +18,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import extfs = require('vs/base/node/extfs'); -import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestTextResourceConfigurationService, TestHashService } from 'vs/workbench/test/workbenchTestServices'; +import { TestTextFileService, TestTextResourceConfigurationService, workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices'; import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; @@ -27,25 +27,14 @@ import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEd import { IFileService } from 'vs/platform/files/common/files'; import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; -import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; -import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; -import { IModeService } from 'vs/editor/common/services/modeService'; -import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; -import { IModelService } from 'vs/editor/common/services/modelService'; -import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; -import { IChoiceService, IMessageService } from 'vs/platform/message/common/message'; +import { IChoiceService } from 'vs/platform/message/common/message'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -64,7 +53,6 @@ suite('ConfigurationEditingService', () => { let workspaceDir; let globalSettingsFile; let workspaceSettingsDir; - let choiceService; suiteSetup(() => { const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -114,7 +102,7 @@ suite('ConfigurationEditingService', () => { // Clear services if they are already created clearServices(); - instantiationService = new TestInstantiationService(); + instantiationService = workbenchInstantiationService(); const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); instantiationService.stub(IEnvironmentService, environmentService); const workspacesService = instantiationService.stub(IWorkspacesService, {}); @@ -122,28 +110,10 @@ suite('ConfigurationEditingService', () => { instantiationService.stub(IWorkspaceContextService, workspaceService); return workspaceService.initialize(noWorkspace ? {} : workspaceDir).then(() => { instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(ILifecycleService, new TestLifecycleService()); - instantiationService.stub(IHashService, new TestHashService()); - instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); - instantiationService.stub(ITelemetryService, NullTelemetryService); - instantiationService.stub(IModeService, ModeServiceImpl); - instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true })); - instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - instantiationService.stub(IBackupFileService, new TestBackupFileService()); - choiceService = instantiationService.stub(IChoiceService, { - choose: (severity, message, options, cancelId): TPromise => { - return TPromise.as(cancelId); - } - }); - instantiationService.stub(IMessageService, { - show: (severity, message, options, cancelId): void => { } - }); - testObject = instantiationService.createInstance(ConfigurationEditingService); - return workspaceService.initialize(noWorkspace ? {} : workspaceDir); }); } diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index 211e1f66128..0887b2eb530 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -13,15 +13,22 @@ import * as sinon from 'sinon'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ParsedArgs } from 'vs/platform/environment/common/environment'; +import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; import extfs = require('vs/base/node/extfs'); import uuid = require('vs/base/common/uuid'); -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; -import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files'; +import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService } from 'vs/workbench/test/workbenchTestServices'; +import { FileService } from 'vs/workbench/services/files/node/fileService'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -44,22 +51,62 @@ function createWorkspace(callback: (workspaceDir: string, globalSettingsFile: st }); } -function setUpFolder(folderName: string): TPromise<{ parentDir: string, workspaceDir: string, workspaceService: WorkspaceService }> { +function setUpFolderWorkspace(folderName: string): TPromise<{ parentDir: string, folderDir: string, workspaceService: WorkspaceService, environmentService: IEnvironmentService }> { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const workspaceDir = path.join(parentDir, folderName); - const workspaceSettingsDir = path.join(workspaceDir, '.vscode'); - const globalSettingsFile = path.join(workspaceDir, 'config.json'); + const globalSettingsFile = path.join(parentDir, 'settings.json'); + return setUpFolder(folderName, parentDir) + .then(folderDir => { + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); + const workspaceService = new WorkspaceService(environmentService, null); + return workspaceService.initialize(folderDir).then(() => ({ parentDir, folderDir, workspaceService, environmentService })); + }); +} + +function setUpFolder(folderName: string, parentDir: string): TPromise { + const folderDir = path.join(parentDir, folderName); + const workspaceSettingsDir = path.join(folderDir, '.vscode'); return new TPromise((c, e) => { extfs.mkdirp(workspaceSettingsDir, 493, (error) => { if (error) { e(error); return null; } - const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); - const workspaceService = new WorkspaceService(environmentService, null); - workspaceService.initialize(workspaceDir).then(() => c({ parentDir, workspaceDir, workspaceService })); + c(folderDir); + }); + }); +} + +function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, workspaceService: WorkspaceService, environmentService: IEnvironmentService }> { + + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const globalSettingsFile = path.join(parentDir, 'settings.json'); + + return createDir(parentDir) + .then(() => { + const configPath = path.join(parentDir, 'vsctests.code-workspace'); + const workspace = { folders: folders.map(path => ({ path })) }; + fs.writeFileSync(configPath, JSON.stringify(workspace, null, '\t')); + + return TPromise.join(folders.map(folder => setUpFolder(folder, parentDir))) + .then(() => { + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); + const workspaceService = new WorkspaceService(environmentService, null); + return workspaceService.initialize({ id, configPath }).then(() => ({ parentDir, workspaceService, environmentService })); + }); + }); +} + +function createDir(dir: string): TPromise { + return new TPromise((c, e) => { + extfs.mkdirp(dir, 493, (error) => { + if (error) { + e(error); + return null; + } + c(null); }); }); } @@ -76,10 +123,10 @@ suite('WorkspaceContextService - Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceResource: string, workspaceContextService: IWorkspaceContextService; setup(() => { - return setUpFolder(workspaceName) - .then(({ parentDir, workspaceDir, workspaceService }) => { + return setUpFolderWorkspace(workspaceName) + .then(({ parentDir, folderDir, workspaceService }) => { parentResource = parentDir; - workspaceResource = workspaceDir; + workspaceResource = folderDir; workspaceContextService = workspaceService; }); }); @@ -127,7 +174,7 @@ suite('WorkspaceContextService - Folder', () => { suite('WorkspaceContextService - Folder', () => { }); -suite('WorkspaceConfigurationService - Node', () => { +suite('WorkspaceConfigurationService', () => { test('defaults', (done: () => void) => { interface ITestSetting { @@ -493,3 +540,180 @@ suite('WorkspaceConfigurationService - Node', () => { }); }); }); + +suite('WorkspaceConfigurationService - Update', () => { + + let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, testObject: IConfigurationService; + + suiteSetup(() => { + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.testSetting': { + 'type': 'string', + 'default': 'isSet' + }, + } + }); + }); + + setup(() => { + return setUpFolderWorkspace(workspaceName) + .then(({ parentDir, folderDir, workspaceService, environmentService }) => { + + parentResource = parentDir; + testObject = workspaceService; + folderDir = folderDir; + + const instantiationService = workbenchInstantiationService(); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.setInstantiationService(instantiationService); + }); + }); + + teardown(done => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + extfs.del(parentResource, os.tmpdir(), () => { }, done); + } + }); + + test('update user configuration', () => { + return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER) + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'value')); + }); + + test('update workspace configuration', () => { + return testObject.updateValue('tasks.service.testSetting', 'value', ConfigurationTarget.WORKSPACE) + .then(() => assert.equal(testObject.getValue('tasks.service.testSetting'), 'value')); + }); + + test('update tasks configuration', () => { + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE) + .then(() => assert.deepEqual(testObject.getValue('tasks'), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); + }); + + test('update user configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER) + .then(() => assert.ok(target.called)); + }); + + test('update workspace configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.WORKSPACE) + .then(() => assert.ok(target.called)); + }); + + test('update task configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE) + .then(() => assert.ok(target.called)); + }); + +}); + +suite('WorkspaceConfigurationService - Update (Multiroot)', () => { + + let parentResource: string, workspace: IWorkspace, testObject: IConfigurationService; + + suiteSetup(() => { + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testSetting': { + 'type': 'string', + 'default': 'isSet' + }, + 'configurationService.workspace.testResourceSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + } + } + }); + }); + + setup(() => { + return setUpWorkspace(['1', '2']) + .then(({ parentDir, workspaceService, environmentService }) => { + + parentResource = parentDir; + testObject = workspaceService; + workspace = workspaceService.getWorkspace();; + + const instantiationService = workbenchInstantiationService(); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.setInstantiationService(instantiationService); + }); + }); + + teardown(done => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + extfs.del(parentResource, os.tmpdir(), () => { }, done); + } + }); + + test('update user configuration', () => { + return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue')); + }); + + test('update user configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) + .then(() => assert.ok(target.called)); + }); + + test('update workspace configuration', () => { + return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'workspaceValue')); + }); + + test('update workspace configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE) + .then(() => assert.ok(target.called)); + }); + + test('update workspace folder configuration', () => { + return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testResourceSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue')); + }); + + test('update workspace folder configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.ok(target.called)); + }); + + test('update tasks configuration', () => { + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); + }); +}); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 5a105e010f7..0340fff3501 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -26,7 +26,7 @@ import { TextModelResolverService } from 'vs/workbench/services/textmodelResolve import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IEditorInput, IEditorOptions, Position, Direction, IEditor, IResourceInput } from 'vs/platform/editor/common/editor'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import { IMessageService, IConfirmation, IConfirmationResult } from 'vs/platform/message/common/message'; +import { IMessageService, IConfirmation, IConfirmationResult, IChoiceService } from 'vs/platform/message/common/message'; import { IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace, WorkbenchState, IWorkspaceFolder, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; import { ILifecycleService, ShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { EditorStacksModel } from 'vs/workbench/common/editor/editorStacksModel'; @@ -261,6 +261,11 @@ export function workbenchInstantiationService(): IInstantiationService { instantiationService.stub(IEnvironmentService, TestEnvironmentService); instantiationService.stub(IThemeService, new TestThemeService()); instantiationService.stub(IHashService, new TestHashService()); + instantiationService.stub(IChoiceService, { + choose: (severity, message, options, cancelId): TPromise => { + return TPromise.as(cancelId); + } + }); return instantiationService; } From b10df87f56901b6c12bde0f4c579dd5aabc9d50f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 13 Oct 2017 15:09:56 +0200 Subject: [PATCH 253/394] minimal icon theme to use naming icon theme naming convention --- .../{vs_minimal_icons.json => vs_minimal-icon-theme.json} | 0 extensions/theme-defaults/package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename extensions/theme-defaults/fileicons/{vs_minimal_icons.json => vs_minimal-icon-theme.json} (100%) diff --git a/extensions/theme-defaults/fileicons/vs_minimal_icons.json b/extensions/theme-defaults/fileicons/vs_minimal-icon-theme.json similarity index 100% rename from extensions/theme-defaults/fileicons/vs_minimal_icons.json rename to extensions/theme-defaults/fileicons/vs_minimal-icon-theme.json diff --git a/extensions/theme-defaults/package.json b/extensions/theme-defaults/package.json index a73e2654255..7a48ad6ece2 100644 --- a/extensions/theme-defaults/package.json +++ b/extensions/theme-defaults/package.json @@ -43,7 +43,7 @@ { "id": "vs-minimal", "label": "Minimal (Visual Studio Code)", - "path": "./fileicons/vs_minimal_icons.json" + "path": "./fileicons/vs_minimal-icon-theme.json" } ] } From 87f4150b3abe6829e979167cc956aea45af197c4 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Oct 2017 14:19:15 +0200 Subject: [PATCH 254/394] [folding] performance refactoring - first (for #36555) --- .../editor/contrib/folding/browser/folding.ts | 546 +++++------------- .../folding/browser/foldingDecorations.ts | 39 ++ .../editor/contrib/folding/common/folding.ts | 15 - .../contrib/folding/common/foldingModel.ts | 516 +++++++++++------ .../folding/common/hiddenRangeModel.ts | 125 ++++ .../contrib/folding/test/foldingModel.test.ts | 371 ++++++++++++ .../folding/test/hiddenRangeModel.test.ts | 99 ++++ 7 files changed, 1111 insertions(+), 600 deletions(-) create mode 100644 src/vs/editor/contrib/folding/browser/foldingDecorations.ts delete mode 100644 src/vs/editor/contrib/folding/common/folding.ts create mode 100644 src/vs/editor/contrib/folding/common/hiddenRangeModel.ts create mode 100644 src/vs/editor/contrib/folding/test/foldingModel.test.ts create mode 100644 src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index c7f40ef849c..959a8086a84 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -9,68 +9,82 @@ import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import * as dom from 'vs/base/browser/dom'; -import { RunOnceScheduler } from 'vs/base/common/async'; +import { RunOnceScheduler, Delayer } from 'vs/base/common/async'; import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; -import * as editorCommon from 'vs/editor/common/editorCommon'; -import { Range } from 'vs/editor/common/core/range'; +import { ICommonCodeEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; -import { CollapsibleRegion, getCollapsibleRegionsToFoldAtLine, getCollapsibleRegionsToUnfoldAtLine, doesLineBelongsToCollapsibleRegion, IFoldingRange } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingModel, FoldingRegion, setCollapseStateAtLevel, setCollapseStateRecursivly, fold, unfold } from 'vs/editor/contrib/folding/common/foldingModel'; import { computeRanges, limitByIndent } from 'vs/editor/contrib/folding/common/indentFoldStrategy'; -import { IFoldingController, ID } from 'vs/editor/contrib/folding/common/folding'; -import { Selection } from 'vs/editor/common/core/selection'; +import { FoldingDecorationProvider } from './foldingDecorations'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions'; import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; +import { HiddenRangeModel } from 'vs/editor/contrib/folding/common/hiddenRangeModel'; +import { IRange } from 'vs/editor/common/core/range'; + +export const ID = 'editor.contrib.folding'; @editorContribution -export class FoldingController implements IFoldingController { +export class FoldingController { static MAX_FOLDING_REGIONS = 5000; - public static get(editor: editorCommon.ICommonCodeEditor): FoldingController { + + public static get(editor: ICommonCodeEditor): FoldingController { return editor.getContribution(ID); } private editor: ICodeEditor; private _isEnabled: boolean; - private _showFoldingControls: 'always' | 'mouseover'; + private _autoHideFoldingControls: boolean; + + private foldingDecorationProvider: FoldingDecorationProvider; + + private foldingModel: FoldingModel; + private hiddenRangeModel: HiddenRangeModel; + + private foldingModelPromise: TPromise; + private updateScheduler: Delayer; + private globalToDispose: IDisposable[]; - private computeToken: number; private cursorChangedScheduler: RunOnceScheduler; - private contentChangedScheduler: RunOnceScheduler; - private localToDispose: IDisposable[]; - private decorations: CollapsibleRegion[]; + private localToDispose: IDisposable[]; constructor(editor: ICodeEditor) { this.editor = editor; this._isEnabled = this.editor.getConfiguration().contribInfo.folding; - this._showFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls; + this._autoHideFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls === 'mouseover'; this.globalToDispose = []; this.localToDispose = []; - this.decorations = []; - this.computeToken = 0; + + this.foldingDecorationProvider = new FoldingDecorationProvider(); + this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls; this.globalToDispose.push(this.editor.onDidChangeModel(() => this.onModelChanged())); + this.globalToDispose.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => { - let oldIsEnabled = this._isEnabled; - this._isEnabled = this.editor.getConfiguration().contribInfo.folding; - if (oldIsEnabled !== this._isEnabled) { - this.onModelChanged(); - } - let oldShowFoldingControls = this._showFoldingControls; - this._showFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls; - if (oldShowFoldingControls !== this._showFoldingControls) { - this.updateHideFoldIconClass(); + if (e.contribInfo) { + let oldIsEnabled = this._isEnabled; + this._isEnabled = this.editor.getConfiguration().contribInfo.folding; + if (oldIsEnabled !== this._isEnabled) { + this.onModelChanged(); + } + let oldShowFoldingControls = this._autoHideFoldingControls; + this._autoHideFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls === 'mouseover'; + if (oldShowFoldingControls !== this._autoHideFoldingControls) { + this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls; + this.onModelContentChanged(); + } } })); - + this.globalToDispose.push({ dispose: () => dispose(this.localToDispose) }); this.onModelChanged(); } @@ -79,17 +93,9 @@ export class FoldingController implements IFoldingController { } public dispose(): void { - this.cleanState(); this.globalToDispose = dispose(this.globalToDispose); } - private updateHideFoldIconClass(): void { - let domNode = this.editor.getDomNode(); - if (domNode) { - dom.toggleClass(domNode, 'alwaysShowFoldIcons', this._showFoldingControls === 'always'); - } - } - /** * Store view state. */ @@ -98,16 +104,16 @@ export class FoldingController implements IFoldingController { if (!model) { return {}; } - var collapsedRegions: IFoldingRange[] = []; - this.decorations.forEach(d => { - if (d.isCollapsed) { - var range = d.getDecorationRange(model); + let collapsedIndexes: number[] = []; + for (let region of this.foldingModel.regions) { + if (region.isCollapsed && region.editorDecorationId) { + var range = model.getDecorationRange(region.editorDecorationId); if (range) { - collapsedRegions.push({ startLineNumber: range.startLineNumber, endLineNumber: range.endLineNumber, indent: d.indent, isCollapsed: true }); + collapsedIndexes.push(range.startLineNumber); } } - }); - return { collapsedRegions: collapsedRegions, lineCount: model.getLineCount() }; + } + return { collapsedIndexes, lineCount: model.getLineCount() }; } /** @@ -121,184 +127,97 @@ export class FoldingController implements IFoldingController { if (!this._isEnabled) { return; } - if (!state || !Array.isArray(state.collapsedRegions) || state.collapsedRegions.length === 0 || state.lineCount !== model.getLineCount()) { + if (!state || !Array.isArray(state.collapsedIndexes) || state.collapsedIndexes.length === 0 || state.lineCount !== model.getLineCount()) { return; } - let newFolded = state.collapsedRegions; - - if (this.decorations.length > 0) { - let hasChanges = false; - let i = 0; - this.editor.changeDecorations(changeAccessor => { - this.decorations.forEach(d => { - if (i === newFolded.length || d.startLineNumber < newFolded[i].startLineNumber) { - if (d.isCollapsed) { - d.setCollapsed(false, changeAccessor); - hasChanges = true; - } - } else if (d.startLineNumber === newFolded[i].startLineNumber) { - if (!d.isCollapsed) { - d.setCollapsed(true, changeAccessor); - hasChanges = true; - } - i++; - } else { - return; // folding regions doesn't match, don't try to restore - } - }); - }); - if (hasChanges) { - this.updateHiddenAreas(void 0); - } - } - } - - private cleanState(): void { - this.localToDispose = dispose(this.localToDispose); - } - - private applyRegions(regions: IFoldingRange[]) { - let model = this.editor.getModel(); - if (!model) { - return; - } - let updateHiddenRegions = false; - regions = limitByIndent(regions, FoldingController.MAX_FOLDING_REGIONS).sort((r1, r2) => r1.startLineNumber - r2.startLineNumber); - - this.editor.changeDecorations(changeAccessor => { - - let newDecorations: CollapsibleRegion[] = []; - - let k = 0, i = 0; - while (i < this.decorations.length && k < regions.length) { - let dec = this.decorations[i]; - let decRange = dec.getDecorationRange(model); - if (!decRange) { - updateHiddenRegions = updateHiddenRegions || dec.isCollapsed; - dec.dispose(changeAccessor); - i++; - } else { - while (k < regions.length && decRange.startLineNumber > regions[k].startLineNumber) { - let region = regions[k]; - updateHiddenRegions = updateHiddenRegions || region.isCollapsed; - newDecorations.push(new CollapsibleRegion(region, model, changeAccessor)); - k++; - } - if (k < regions.length) { - let currRange = regions[k]; - if (decRange.startLineNumber < currRange.startLineNumber) { - updateHiddenRegions = updateHiddenRegions || dec.isCollapsed; - dec.dispose(changeAccessor); - i++; - } else if (decRange.startLineNumber === currRange.startLineNumber) { - if (dec.isCollapsed && (dec.startLineNumber !== currRange.startLineNumber || dec.endLineNumber !== currRange.endLineNumber)) { - updateHiddenRegions = true; - } - currRange.isCollapsed = dec.isCollapsed; // preserve collapse state - dec.update(currRange, model, changeAccessor); - newDecorations.push(dec); - i++; - k++; - } - } + this.getFoldingModel().then(foldingModel => { + let toToogle: FoldingRegion[] = []; + for (let index of state.collapsedIndexes) { + let region = foldingModel.getRegionAtLine(index); + if (region && !region.isCollapsed) { + toToogle.push(region); } } - while (i < this.decorations.length) { - let dec = this.decorations[i]; - updateHiddenRegions = updateHiddenRegions || dec.isCollapsed; - dec.dispose(changeAccessor); - i++; - } - while (k < regions.length) { - let region = regions[k]; - updateHiddenRegions = updateHiddenRegions || region.isCollapsed; - newDecorations.push(new CollapsibleRegion(region, model, changeAccessor)); - k++; - } - this.decorations = newDecorations; + foldingModel.toggleCollapseState(toToogle); }); - if (updateHiddenRegions) { - this.updateHiddenAreas(); - } - } private onModelChanged(): void { - this.cleanState(); - this.updateHideFoldIconClass(); + this.localToDispose = dispose(this.localToDispose); let model = this.editor.getModel(); if (!this._isEnabled || !model) { return; } - this.computeAndApplyCollapsibleRegions(); - this.contentChangedScheduler = new RunOnceScheduler(() => this.computeAndApplyCollapsibleRegions(), 200); + this.foldingModel = new FoldingModel(model, this.foldingDecorationProvider); + this.localToDispose.push(this.foldingModel); + + this.hiddenRangeModel = new HiddenRangeModel(this.foldingModel); + this.localToDispose.push(this.hiddenRangeModel); + this.localToDispose.push(this.hiddenRangeModel.onDidChange(hr => this.onHiddenRangesChanges(hr))); + + this.updateScheduler = new Delayer(200); + this.localToDispose.push({ dispose: () => this.updateScheduler.cancel() }); + this.cursorChangedScheduler = new RunOnceScheduler(() => this.revealCursor(), 200); - this.localToDispose.push(this.contentChangedScheduler); this.localToDispose.push(this.cursorChangedScheduler); - - this.localToDispose.push(model.onDidChangeLanguageConfiguration(e => { - this.contentChangedScheduler.schedule(); - })); - this.localToDispose.push(this.editor.onDidChangeModelContent(e => this.contentChangedScheduler.schedule())); - this.localToDispose.push(this.editor.onDidChangeCursorPosition((e) => { - - if (!this._isEnabled) { - // Early exit if nothing needs to be done! - // Leave some form of early exit check here if you wish to continue being a cursor position change listener ;) - return; - } - - this.cursorChangedScheduler.schedule(); - })); + this.localToDispose.push(this.editor.onDidChangeModelLanguageConfiguration(e => this.onModelContentChanged())); // also covers model language changes + this.localToDispose.push(this.editor.onDidChangeModelContent(e => this.onModelContentChanged())); + this.localToDispose.push(this.editor.onDidChangeCursorPosition(e => this.onCursorPositionChanged())); this.localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e))); this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e))); - this.localToDispose.push({ dispose: () => this.disposeDecorations() }); + this.onModelContentChanged(); } - private computeAndApplyCollapsibleRegions(): void { - let model = this.editor.getModel(); - this.applyRegions(model ? computeRanges(model) : []); + private computeRanges() { + let editorModel = this.editor.getModel(); + if (editorModel) { + let ranges = computeRanges(editorModel); + ranges = limitByIndent(ranges, FoldingController.MAX_FOLDING_REGIONS).sort((r1, r2) => r1.startLineNumber - r2.startLineNumber); + return ranges; + } + + return []; } - private disposeDecorations() { - this.editor.changeDecorations(changeAccessor => { - this.decorations.forEach(dec => dec.dispose(changeAccessor)); + public getFoldingModel() { + return this.foldingModelPromise; + } + + private onModelContentChanged() { + this.foldingModelPromise = this.updateScheduler.trigger(() => { + this.foldingModel.update(this.computeRanges()); + return this.foldingModel; }); - this.decorations = []; - this.editor.setHiddenAreas([]); + } + + private onHiddenRangesChanges(hiddenRanges: IRange[]) { + let selections = this.editor.getSelections(); + if (this.hiddenRangeModel.adjustSelections(selections)) { + this.editor.setSelections(selections); + } + this.editor.setHiddenAreas(hiddenRanges); + } + + private onCursorPositionChanged() { + if (this.hiddenRangeModel.hasRanges()) { + this.cursorChangedScheduler.schedule(); + } } private revealCursor() { - let model = this.editor.getModel(); - if (!model) { - return; - } - let hasChanges = false; - let selections = this.editor.getSelections(); - - this.editor.changeDecorations(changeAccessor => { - return this.decorations.forEach(dec => { - if (dec.isCollapsed) { - let decRange = dec.getDecorationRange(model); - if (decRange) { - for (let selection of selections) { - // reveal if cursor in in one of the collapsed line (not the first) - if (decRange.startLineNumber < selection.selectionStartLineNumber && selection.selectionStartLineNumber <= decRange.endLineNumber) { - dec.setCollapsed(false, changeAccessor); - hasChanges = true; - break; - } - } - } + this.getFoldingModel().then(foldingModel => { + let selections = this.editor.getSelections(); + for (let selection of selections) { + let lineNumber = selection.selectionStartLineNumber; + if (this.hiddenRangeModel.isHidden(lineNumber)) { + let toToggle = foldingModel.getAllRegionsAtLine(lineNumber, r => r.isCollapsed && lineNumber > r.range.startLineNumber); + foldingModel.toggleCollapseState(toToggle); } - }); + } }); - if (hasChanges) { - this.updateHiddenAreas(this.editor.getPosition().lineNumber); - } } private mouseDownInfo: { lineNumber: number, iconClicked: boolean }; @@ -306,9 +225,6 @@ export class FoldingController implements IFoldingController { private onEditorMouseDown(e: IEditorMouseEvent): void { this.mouseDownInfo = null; - if (this.decorations.length === 0) { - return; - } let range = e.target.range; if (!range) { return; @@ -316,10 +232,6 @@ export class FoldingController implements IFoldingController { if (!e.event.leftButton) { return; } - - let model = this.editor.getModel(); - - let iconClicked = false; switch (e.target.type) { case MouseTargetType.GUTTER_LINE_DECORATIONS: @@ -333,7 +245,8 @@ export class FoldingController implements IFoldingController { iconClicked = true; break; - case MouseTargetType.CONTENT_EMPTY: + case MouseTargetType.CONTENT_EMPTY: { + let model = this.editor.getModel(); if (range.startColumn === model.getLineMaxColumn(range.startLineNumber)) { let editorCoords = dom.getDomNodePagePosition(this.editor.getDomNode()); let pos = this.editor.getScrolledVisiblePosition(range.getEndPosition()); @@ -343,11 +256,14 @@ export class FoldingController implements IFoldingController { break; } return; - case MouseTargetType.CONTENT_TEXT: + } + case MouseTargetType.CONTENT_TEXT: { + let model = this.editor.getModel(); if (range.startColumn === model.getLineMaxColumn(range.startLineNumber)) { break; } return; + } default: return; } @@ -367,213 +283,54 @@ export class FoldingController implements IFoldingController { return; } - let model = this.editor.getModel(); - if (iconClicked) { if (e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS) { return; } } else { + let model = this.editor.getModel(); if (range.startColumn !== model.getLineMaxColumn(lineNumber)) { return; } } - this.editor.changeDecorations(changeAccessor => { - for (let i = 0; i < this.decorations.length; i++) { - let dec = this.decorations[i]; - let decRange = dec.getDecorationRange(model); - if (decRange && decRange.startLineNumber === lineNumber) { - if (iconClicked || dec.isCollapsed) { - dec.setCollapsed(!dec.isCollapsed, changeAccessor); - this.updateHiddenAreas(lineNumber); - } - return; + this.getFoldingModel().then(foldingModel => { + let region = foldingModel.getRegionAtLine(lineNumber); + if (region) { + if (iconClicked || region.isCollapsed) { + foldingModel.toggleCollapseState([region]); + this.reveal(lineNumber); } - } - }); - } - - private updateHiddenAreas(focusLine?: number): void { - let model = this.editor.getModel(); - var selections: Selection[] = this.editor.getSelections(); - var updateSelections = false; - let hiddenAreas: Range[] = []; - this.decorations.filter(dec => dec.isCollapsed).forEach(dec => { - let decRange = dec.getDecorationRange(model); - if (!decRange) { return; } - let isLineHidden = (line: number) => line > decRange.startLineNumber && line <= decRange.endLineNumber; - hiddenAreas.push(new Range(decRange.startLineNumber + 1, 1, decRange.endLineNumber, 1)); - selections.forEach((selection, i) => { - if (isLineHidden(selection.getStartPosition().lineNumber)) { - selections[i] = selection = selection.setStartPosition(decRange.startLineNumber, model.getLineMaxColumn(decRange.startLineNumber)); - updateSelections = true; - } - if (isLineHidden(selection.getEndPosition().lineNumber)) { - selections[i] = selection.setEndPosition(decRange.startLineNumber, model.getLineMaxColumn(decRange.startLineNumber)); - updateSelections = true; - } - }); }); - if (updateSelections) { - this.editor.setSelections(selections); - } - this.editor.setHiddenAreas(hiddenAreas); - if (focusLine) { - this.editor.revealPositionInCenterIfOutsideViewport({ lineNumber: focusLine, column: 1 }, editorCommon.ScrollType.Smooth); - } } - public unfold(levels: number): void { - let model = this.editor.getModel(); - let hasChanges = false; - let selections = this.editor.getSelections(); - let selectionsHasChanged = false; - selections.forEach((selection, index) => { - let toUnfold: CollapsibleRegion[] = getCollapsibleRegionsToUnfoldAtLine(this.decorations, model, selection.startLineNumber, levels); - if (toUnfold.length > 0) { - toUnfold.forEach((collapsibleRegion, index) => { - this.editor.changeDecorations(changeAccessor => { - collapsibleRegion.setCollapsed(false, changeAccessor); - hasChanges = true; - }); - }); - if (!doesLineBelongsToCollapsibleRegion(toUnfold[0].foldingRange, selection.startLineNumber)) { - let lineNumber = toUnfold[0].startLineNumber, column = model.getLineMaxColumn(toUnfold[0].startLineNumber); - selections[index] = selection.setEndPosition(lineNumber, column).setStartPosition(lineNumber, column); - selectionsHasChanged = true; - } - } - }); - if (selectionsHasChanged) { - this.editor.setSelections(selections); - } - if (hasChanges) { - this.updateHiddenAreas(selections[0].startLineNumber); - } - } - - public fold(levels: number, up: boolean): void { - let hasChanges = false; - let selections = this.editor.getSelections(); - selections.forEach(selection => { - let lineNumber = selection.startLineNumber; - let toFold: CollapsibleRegion[] = getCollapsibleRegionsToFoldAtLine(this.decorations, this.editor.getModel(), lineNumber, levels, up); - toFold.forEach(collapsibleRegion => this.editor.changeDecorations(changeAccessor => { - collapsibleRegion.setCollapsed(true, changeAccessor); - hasChanges = true; - })); - }); - if (hasChanges) { - this.updateHiddenAreas(selections[0].startLineNumber); - } - } - - public foldUnfoldRecursively(isFold: boolean): void { - let hasChanges = false; - let model = this.editor.getModel(); - let selections = this.editor.getSelections(); - selections.forEach(selection => { - let lineNumber = selection.startLineNumber; - let endLineNumber: number; - let decToFoldUnfold: CollapsibleRegion[] = []; - for (let i = 0, len = this.decorations.length; i < len; i++) { - let dec = this.decorations[i]; - let decRange = dec.getDecorationRange(model); - if (!decRange) { - continue; - } - if (decRange.startLineNumber >= lineNumber && (decRange.endLineNumber <= endLineNumber || typeof endLineNumber === 'undefined')) { - //Protect against cursor not being in decoration and lower decoration folding/unfolding - if (decRange.startLineNumber !== lineNumber && typeof endLineNumber === 'undefined') { - return; - } - endLineNumber = endLineNumber || decRange.endLineNumber; - decToFoldUnfold.push(dec); - } - }; - if (decToFoldUnfold.length > 0) { - decToFoldUnfold.forEach(dec => { - this.editor.changeDecorations(changeAccessor => { - dec.setCollapsed(isFold, changeAccessor); - hasChanges = true; - }); - }); - } - }); - if (hasChanges) { - this.updateHiddenAreas(selections[0].startLineNumber); - } - } - - public foldAll(): void { - this.changeAll(true); - } - - public unfoldAll(): void { - this.changeAll(false); - } - - private changeAll(collapse: boolean): void { - if (this.decorations.length > 0) { - let hasChanges = true; - this.editor.changeDecorations(changeAccessor => { - this.decorations.forEach(d => { - if (collapse !== d.isCollapsed) { - d.setCollapsed(collapse, changeAccessor); - hasChanges = true; - } - }); - }); - if (hasChanges) { - this.updateHiddenAreas(this.editor.getPosition().lineNumber); - } - } - } - - public foldLevel(foldLevel: number, selectedLineNumbers: number[]): void { - let model = this.editor.getModel(); - let foldingRegionStack: Range[] = [model.getFullModelRange()]; // sentinel - - let hasChanges = false; - this.editor.changeDecorations(changeAccessor => { - this.decorations.forEach(dec => { - let decRange = dec.getDecorationRange(model); - if (decRange) { - while (!Range.containsRange(foldingRegionStack[foldingRegionStack.length - 1], decRange)) { - foldingRegionStack.pop(); - } - foldingRegionStack.push(decRange); - if (foldingRegionStack.length === foldLevel + 1 && !dec.isCollapsed && !selectedLineNumbers.some(lineNumber => decRange.startLineNumber < lineNumber && lineNumber <= decRange.endLineNumber)) { - dec.setCollapsed(true, changeAccessor); - hasChanges = true; - } - } - }); - }); - if (hasChanges) { - this.updateHiddenAreas(selectedLineNumbers[0]); - } + public reveal(focusLine: number): void { + this.editor.revealPositionInCenterIfOutsideViewport({ lineNumber: focusLine, column: 1 }, ScrollType.Smooth); } } abstract class FoldingAction extends EditorAction { - abstract invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor, args: T): void; + abstract invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: T): void; - public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: T): void | TPromise { + public runEditorCommand(accessor: ServicesAccessor, editor: ICommonCodeEditor, args: T): void | TPromise { let foldingController = FoldingController.get(editor); if (!foldingController) { return; } this.reportTelemetry(accessor, editor); - this.invoke(foldingController, editor, args); + return foldingController.getFoldingModel().then(foldingModel => { + this.invoke(foldingController, foldingModel, editor, args); + }); } - public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { + protected getSelectedLines(editor: ICommonCodeEditor) { + return editor.getSelections().map(s => s.startLineNumber); + } + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { } } @@ -629,8 +386,8 @@ class UnfoldAction extends FoldingAction { }); } - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor, args: FoldingArguments): void { - foldingController.unfold(args ? args.levels || 1 : 1); + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: FoldingArguments): void { + unfold(foldingModel, args ? args.levels || 1 : 1, this.getSelectedLines(editor)); } } @@ -650,8 +407,8 @@ class UnFoldRecursivelyAction extends FoldingAction { }); } - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor, args: any): void { - foldingController.foldUnfoldRecursively(false); + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: any): void { + setCollapseStateRecursivly(foldingModel, false, this.getSelectedLines(editor)); } } @@ -687,9 +444,9 @@ class FoldAction extends FoldingAction { }); } - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor, args: FoldingArguments): void { + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: FoldingArguments): void { args = args ? args : { levels: 1, direction: 'up' }; - foldingController.fold(args.levels || 1, args.direction === 'up'); + fold(foldingModel, args.levels || 1, args.direction === 'up', this.getSelectedLines(editor)); } } @@ -709,8 +466,13 @@ class FoldRecursivelyAction extends FoldingAction { }); } - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor): void { - foldingController.foldUnfoldRecursively(true); + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { + let selectedLines = this.getSelectedLines(editor); + setCollapseStateRecursivly(foldingModel, true, selectedLines); + if (selectedLines.length > 0) { + foldingController.reveal(selectedLines[0]); + } + } } @@ -730,8 +492,8 @@ class FoldAllAction extends FoldingAction { }); } - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor): void { - foldingController.foldAll(); + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { + setCollapseStateRecursivly(foldingModel, true); } } @@ -751,8 +513,8 @@ class UnfoldAllAction extends FoldingAction { }); } - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor): void { - foldingController.unfoldAll(); + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { + setCollapseStateRecursivly(foldingModel, false); } } @@ -764,12 +526,8 @@ class FoldLevelAction extends FoldingAction { return parseInt(this.id.substr(FoldLevelAction.ID_PREFIX.length)); } - private getSelectedLines(editor: editorCommon.ICommonCodeEditor) { - return editor.getSelections().map(s => s.startLineNumber); - } - - invoke(foldingController: FoldingController, editor: editorCommon.ICommonCodeEditor): void { - foldingController.foldLevel(this.getFoldingLevel(), this.getSelectedLines(editor)); + invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { + setCollapseStateAtLevel(foldingModel, this.getFoldingLevel(), true, this.getSelectedLines(editor)); } } diff --git a/src/vs/editor/contrib/folding/browser/foldingDecorations.ts b/src/vs/editor/contrib/folding/browser/foldingDecorations.ts new file mode 100644 index 00000000000..df965777690 --- /dev/null +++ b/src/vs/editor/contrib/folding/browser/foldingDecorations.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { FoldingRegion, IDecorationProvider } from 'vs/editor/contrib/folding/common/foldingModel'; + +export class FoldingDecorationProvider implements IDecorationProvider { + + private COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + afterContentClassName: 'inline-folded', + linesDecorationsClassName: 'folding collapsed' + }); + + private EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + linesDecorationsClassName: 'folding autoHide' + }); + + private EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + linesDecorationsClassName: 'folding' + }); + + public autoHideFoldingControls: boolean = true; + + getDecorationOption(region: FoldingRegion): ModelDecorationOptions { + if (region.isCollapsed) { + return this.COLLAPSED_VISUAL_DECORATION; + } else if (this.autoHideFoldingControls) { + return this.EXPANDED_AUTO_HIDE_VISUAL_DECORATION; + } else { + return this.EXPANDED_VISUAL_DECORATION; + } + } +} diff --git a/src/vs/editor/contrib/folding/common/folding.ts b/src/vs/editor/contrib/folding/common/folding.ts deleted file mode 100644 index c0f677cb95c..00000000000 --- a/src/vs/editor/contrib/folding/common/folding.ts +++ /dev/null @@ -1,15 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IEditorContribution } from 'vs/editor/common/editorCommon'; - -export const ID = 'editor.contrib.folding'; - -export interface IFoldingController extends IEditorContribution { - - foldAll(): void; - unfoldAll(): void; - -} \ No newline at end of file diff --git a/src/vs/editor/contrib/folding/common/foldingModel.ts b/src/vs/editor/contrib/folding/common/foldingModel.ts index 16a1b1c8cdc..aacf0acf458 100644 --- a/src/vs/editor/contrib/folding/common/foldingModel.ts +++ b/src/vs/editor/contrib/folding/common/foldingModel.ts @@ -3,230 +3,368 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as editorCommon from 'vs/editor/common/editorCommon'; -import { Range } from 'vs/editor/common/core/range'; -import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { IModel, IModelDecorationOptions } from 'vs/editor/common/editorCommon'; +import Event, { Emitter } from 'vs/base/common/event'; -export interface IFoldingRange { +export interface IFoldingRange extends ILineRange { + indent: number; +} + +export interface ILineRange { startLineNumber: number; endLineNumber: number; - indent: number; - isCollapsed?: boolean; } export function toString(range: IFoldingRange): string { - return (range ? range.startLineNumber + '/' + range.endLineNumber : 'null') + (range.isCollapsed ? ' (collapsed)' : '') + ' - ' + range.indent; + return (range ? range.startLineNumber + '/' + range.endLineNumber : 'null') + ' - ' + range.indent; } -export class CollapsibleRegion { +export interface IFoldingRangeProvider { + getFoldingRanges(textModel: IModel): Thenable; +} - private decorationIds: string[]; - private _isCollapsed: boolean; - private _indent: number; +export interface IDecorationProvider { + getDecorationOption(region: FoldingRegion): IModelDecorationOptions; +} - private _lastRange: IFoldingRange; +export interface FoldingModelChangeEvent { + model: FoldingModel; + collapseStateChanged?: FoldingRegion[]; +} - public constructor(range: IFoldingRange, model: editorCommon.IModel, changeAccessor: editorCommon.IModelDecorationsChangeAccessor) { - this.decorationIds = []; - this.update(range, model, changeAccessor); +export class FoldingModel { + private _textModel: IModel; + private _decorationProvider: IDecorationProvider; + + private _regions: FoldingRegion[] = []; + private _updateEventEmitter = new Emitter(); + + public get regions(): FoldingRegion[] { return this._regions; }; + public get onDidChange(): Event { return this._updateEventEmitter.event; }; + public get textModel() { return this._textModel; } + + constructor(textModel: IModel, decorationProvider: IDecorationProvider) { + this._textModel = textModel; + this._decorationProvider = decorationProvider; } - public get isCollapsed(): boolean { - return this._isCollapsed; - } - - public get isExpanded(): boolean { - return !this._isCollapsed; - } - - public get indent(): number { - return this._indent; - } - - public get foldingRange(): IFoldingRange { - return this._lastRange; - } - - public get startLineNumber(): number { - return this._lastRange ? this._lastRange.startLineNumber : void 0; - } - - public get endLineNumber(): number { - return this._lastRange ? this._lastRange.endLineNumber : void 0; - } - - public setCollapsed(isCollaped: boolean, changeAccessor: editorCommon.IModelDecorationsChangeAccessor): void { - this._isCollapsed = isCollaped; - if (this.decorationIds.length > 0) { - changeAccessor.changeDecorationOptions(this.decorationIds[0], this.getVisualDecorationOptions()); + public toggleCollapseState(regions: FoldingRegion[]) { + if (!regions.length) { + return; } + let processed = {}; + this._textModel.changeDecorations(accessor => { + for (let region of regions) { + if (!processed[region.editorDecorationId]) { + processed[region.editorDecorationId] = true; + region.isCollapsed = !region.isCollapsed; + accessor.changeDecorationOptions(region.editorDecorationId, this._decorationProvider.getDecorationOption(region)); + } + } + }); + this._updateEventEmitter.fire({ model: this, collapseStateChanged: regions }); } - public getDecorationRange(model: editorCommon.IModel): Range { - if (this.decorationIds.length > 0) { - return model.getDecorationRange(this.decorationIds[1]); + public update(newRanges: IFoldingRange[]): void { + let editorDecorationIds = []; + let newEditorDecorations = []; + + // remember the latest start line numbers of the collapsed regions + let collapsedStartLineNumbers: number[] = []; + for (let region of this._regions) { + if (region.isCollapsed) { + let decRange = this._textModel.getDecorationRange(region.editorDecorationId); + if (decRange) { + collapsedStartLineNumbers.push(decRange.startLineNumber); + } + } + if (region.editorDecorationId) { + editorDecorationIds.push(region.editorDecorationId); + } } - return null; - } - private static _COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - afterContentClassName: 'inline-folded', - linesDecorationsClassName: 'folding collapsed' - }); + let recycleBin = this._regions; + let newRegions = []; - private static _EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - linesDecorationsClassName: 'folding' - }); + let newRegion = (range: IFoldingRange, isCollapsed: boolean) => { + let region = recycleBin.length ? recycleBin.pop() : new FoldingRegion(); + region.init(range, isCollapsed); + newRegions.push(region); - private getVisualDecorationOptions(): ModelDecorationOptions { - if (this._isCollapsed) { - return CollapsibleRegion._COLLAPSED_VISUAL_DECORATION; - } else { - return CollapsibleRegion._EXPANDED_VISUAL_DECORATION; - } - } - - private static _RANGE_DECORATION = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore - }); - - private getRangeDecorationOptions(): ModelDecorationOptions { - return CollapsibleRegion._RANGE_DECORATION; - } - - public update(newRange: IFoldingRange, model: editorCommon.IModel, changeAccessor: editorCommon.IModelDecorationsChangeAccessor): void { - this._lastRange = newRange; - this._isCollapsed = !!newRange.isCollapsed; - this._indent = newRange.indent; - - let newDecorations: editorCommon.IModelDeltaDecoration[] = []; - - let maxColumn = model.getLineMaxColumn(newRange.startLineNumber); - let visualRng = { - startLineNumber: newRange.startLineNumber, - startColumn: maxColumn, - endLineNumber: newRange.startLineNumber, - endColumn: maxColumn + let startLineNumber = range.startLineNumber; + let maxColumn = this._textModel.getLineMaxColumn(startLineNumber); + let decorationRange = { + startLineNumber: startLineNumber, + startColumn: maxColumn, + endLineNumber: startLineNumber, + endColumn: maxColumn + }; + newEditorDecorations.push({ range: decorationRange, options: this._decorationProvider.getDecorationOption(region) }); }; - newDecorations.push({ range: visualRng, options: this.getVisualDecorationOptions() }); - let colRng = { - startLineNumber: newRange.startLineNumber, - startColumn: 1, - endLineNumber: newRange.endLineNumber, - endColumn: model.getLineMaxColumn(newRange.endLineNumber) - }; - newDecorations.push({ range: colRng, options: this.getRangeDecorationOptions() }); - - this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, newDecorations); - } - - - public dispose(changeAccessor: editorCommon.IModelDecorationsChangeAccessor): void { - this._lastRange = null; - this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, []); - } - - public toString(): string { - let str = this.isCollapsed ? 'collapsed ' : 'expanded '; - if (this._lastRange) { - str += (this._lastRange.startLineNumber + '/' + this._lastRange.endLineNumber); - } else { - str += 'no range'; + let k = 0, i = 0; + while (i < collapsedStartLineNumbers.length && k < newRanges.length) { + let collapsedStartLineNumber = collapsedStartLineNumbers[i]; + while (k < newRanges.length && collapsedStartLineNumber > newRanges[k].startLineNumber) { + newRegion(newRanges[k], false); + k++; + } + if (k < newRanges.length) { + let currRange = newRanges[k]; + if (collapsedStartLineNumber < currRange.startLineNumber) { + i++; + } else if (collapsedStartLineNumber === currRange.startLineNumber) { + newRegion(newRanges[k], true); + i++; + k++; + } + } + } + while (k < newRanges.length) { + newRegion(newRanges[k], false); + k++; } - return str; + let newEditorDecorationIds = this._textModel.deltaDecorations(editorDecorationIds, newEditorDecorations); + for (let i = 0; i < newEditorDecorations.length; i++) { + newRegions[i].editorDecorationId = newEditorDecorationIds[i]; + } + + this._regions = newRegions; + this._updateEventEmitter.fire({ model: this }); + } + + public dispose() { + let editorDecorationIds = []; + for (let region of this._regions) { + if (region.editorDecorationId) { + editorDecorationIds.push(region.editorDecorationId); + } + } + this._textModel.deltaDecorations(editorDecorationIds, []); + } + + getAllRegionsAtLine(lineNumber: number, filter?: (r: FoldingRegion) => boolean): FoldingRegion[] { + let result: FoldingRegion[] = []; + for (let i = 0, len = this.regions.length; i < len; i++) { + let current = this.regions[i]; + if (current.range.endLineNumber < lineNumber) { + continue; + } + let startLineNumber = current.range.startLineNumber; + if (startLineNumber <= lineNumber) { + if (!filter || filter(current)) { + result.push(current); + } + } else { + break; + } + } + return result; + } + + + getRegionAtLine(lineNumber: number): FoldingRegion { + let result: FoldingRegion; + for (let i = 0, len = this.regions.length; i < len; i++) { + let current = this.regions[i]; + if (current.range.endLineNumber < lineNumber) { + continue; + } + let startLineNumber = current.range.startLineNumber; + if (startLineNumber <= lineNumber) { + result = current; + } else { + break; + } + } + return result; + } + + getRegionsInside(range: ILineRange, filter?: (r: FoldingRegion, level?: number) => boolean): FoldingRegion[] { + let result = []; + let trackLevel = filter && filter.length === 2; + let levelStack: ILineRange[] = trackLevel ? [range] : null;; + + for (let i = 0, len = this.regions.length; i < len; i++) { + let current = this.regions[i]; + let endLineNumber = current.range.endLineNumber; + if (endLineNumber <= range.startLineNumber) { + continue; + } + let startLineNumber = current.range.startLineNumber; + if (startLineNumber < range.endLineNumber) { + if (endLineNumber <= range.endLineNumber && startLineNumber >= range.startLineNumber) { + if (trackLevel) { + while (!current.containedBy(levelStack[levelStack.length - 1])) { + levelStack.pop(); + } + levelStack.push(current.range); + if (filter(current, levelStack.length - 1)) { + result.push(current); + } + } else if (!filter || filter(current)) { + result.push(current); + } + } + } else { + break; + } + } + return result; + } + +} + +export class FoldingRegion { + + public editorDecorationId: string; + public isCollapsed: boolean; + public range: IFoldingRange; + + constructor() { + } + + public init(range: IFoldingRange, isCollapsed: boolean): void { + this.range = range; + this.isCollapsed = isCollapsed; + this.editorDecorationId = void 0; + } + isAfterLine(lineNumber: number): boolean { + return lineNumber < this.range.startLineNumber; + } + isBeforeLine(lineNumber: number): boolean { + return lineNumber > this.range.endLineNumber; + } + contains(range: ILineRange): boolean { + return this.range.startLineNumber <= range.startLineNumber && this.range.endLineNumber >= range.endLineNumber; + } + containedBy(range: ILineRange): boolean { + return range.startLineNumber <= this.range.startLineNumber && range.endLineNumber >= this.range.endLineNumber; + } + containsLine(lineNumber: number) { + return this.range.startLineNumber <= lineNumber && lineNumber <= this.range.endLineNumber; + } + hidesLine(lineNumber: number) { + return this.range.startLineNumber < lineNumber && lineNumber <= this.range.endLineNumber; } } -export function getCollapsibleRegionsToFoldAtLine(allRegions: CollapsibleRegion[], model: editorCommon.IModel, lineNumber: number, levels: number, up: boolean): CollapsibleRegion[] { - let surroundingRegion: CollapsibleRegion = getCollapsibleRegionAtLine(allRegions, model, lineNumber); +export function unfold(foldingModel: FoldingModel, levels: number, lineNumbers: number[]): void { + let toToggle = []; + for (let lineNumber of lineNumbers) { + let regionsAtLine = getCollapsibleRegionsToUnfoldAtLine(foldingModel, lineNumber, levels); + if (regionsAtLine.length > 0) { + for (let region of regionsAtLine) { + if (region.isCollapsed) { + toToggle.push(region); + } + } + } + }; + foldingModel.toggleCollapseState(toToggle); +} + +export function fold(foldingModel: FoldingModel, levels: number, up: boolean, lineNumbers: number[]): void { + let toToggle = []; + for (let lineNumber of lineNumbers) { + let regionsAtLine = getCollapsibleRegionsToFoldAtLine(foldingModel, lineNumber, levels, up); + for (let region of regionsAtLine) { + if (region.isCollapsed) { + toToggle.push(region); + } + } + } + foldingModel.toggleCollapseState(toToggle); +} + +/** + * Collapse or expand the regions at the given locations including all children. + * @param doCollapse Wheter to collase or expand + * @param lineNumbers the regions to fold, or if not set all regions in the model. + */ +export function setCollapseStateRecursivly(foldingModel: FoldingModel, doCollapse: boolean, lineNumbers?: number[]): void { + let toToggle = []; + if (!lineNumbers) { + toToggle = foldingModel.regions.filter(region => region.isCollapsed !== doCollapse); + } else { + for (let lineNumber of lineNumbers) { + let region = foldingModel.getRegionAtLine(lineNumber); + if (region) { + let regionsInside = foldingModel.getRegionsInside(region.range, r => r.isCollapsed !== doCollapse); + toToggle.push(...regionsInside); + } + } + } + foldingModel.toggleCollapseState(toToggle); +} + +/** + * Folds or unfolds all regions that have a given level, except if they contain one of the blocked lines. + * @param foldLevel level. Level == 1 is the top level + * @param doCollapse Wheter to collase or expand +* @param blockedLineNumbers +*/ +export function setCollapseStateAtLevel(foldingModel: FoldingModel, foldLevel: number, doCollapse: boolean, blockedLineNumbers: number[]): void { + let filter = (region, level) => level === foldLevel && region.isCollapsed !== doCollapse && !blockedLineNumbers.some(line => region.containsLine(line)); + let toToggle = foldingModel.getRegionsInside({ startLineNumber: 1, endLineNumber: Number.MAX_VALUE }, filter); + foldingModel.toggleCollapseState(toToggle); +} + + + +// old + +export function getCollapsibleRegionsToFoldAtLine(model: FoldingModel, lineNumber: number, levels: number, up: boolean): FoldingRegion[] { + let surroundingRegion: FoldingRegion = model.getRegionAtLine(lineNumber); if (!surroundingRegion) { return []; } if (levels === 1) { return [surroundingRegion]; } - let result = getCollapsibleRegionsFor(surroundingRegion, allRegions, model, levels, up); + let result = getCollapsibleRegionsFor(model, surroundingRegion, levels, up); return result.filter(collapsibleRegion => !collapsibleRegion.isCollapsed); } -export function getCollapsibleRegionsToUnfoldAtLine(allRegions: CollapsibleRegion[], model: editorCommon.IModel, lineNumber: number, levels: number): CollapsibleRegion[] { - let surroundingRegion: CollapsibleRegion = getCollapsibleRegionAtLine(allRegions, model, lineNumber); +export function getCollapsibleRegionsToUnfoldAtLine(model: FoldingModel, lineNumber: number, levels: number): FoldingRegion[] { + let surroundingRegion: FoldingRegion = model.getRegionAtLine(lineNumber); if (!surroundingRegion) { return []; } if (levels === 1) { - let regionToUnfold = surroundingRegion.isCollapsed ? surroundingRegion : getFoldedCollapsibleRegionAfterLine(allRegions, model, surroundingRegion, lineNumber); + let regionToUnfold = surroundingRegion.isCollapsed ? surroundingRegion : getFoldedCollapsibleRegionAfterLine(model, surroundingRegion, lineNumber); return regionToUnfold ? [regionToUnfold] : []; } - let result = getCollapsibleRegionsFor(surroundingRegion, allRegions, model, levels, false); + let result = getCollapsibleRegionsFor(model, surroundingRegion, levels, false); return result.filter(collapsibleRegion => collapsibleRegion.isCollapsed); } -function getCollapsibleRegionAtLine(allRegions: CollapsibleRegion[], model: editorCommon.IModel, lineNumber: number): CollapsibleRegion { - let collapsibleRegion: CollapsibleRegion = null; - for (let i = 0, len = allRegions.length; i < len; i++) { - let dec = allRegions[i]; - let decRange = dec.getDecorationRange(model); - if (decRange) { - if (doesLineBelongsToCollapsibleRegion(decRange, lineNumber)) { - collapsibleRegion = dec; - } - if (doesCollapsibleRegionIsAfterLine(decRange, lineNumber)) { - break; - } - } - } - return collapsibleRegion; -} -function getFoldedCollapsibleRegionAfterLine(allRegions: CollapsibleRegion[], model: editorCommon.IModel, surroundingRegion: CollapsibleRegion, lineNumber: number): CollapsibleRegion { +function getFoldedCollapsibleRegionAfterLine(model: FoldingModel, surroundingRegion: FoldingRegion, lineNumber: number): FoldingRegion { + let allRegions = model.regions; let index = allRegions.indexOf(surroundingRegion); for (let i = index + 1; i < allRegions.length; i++) { - let dec = allRegions[i]; - let decRange = dec.getDecorationRange(model); - if (decRange) { - if (doesCollapsibleRegionIsAfterLine(decRange, lineNumber)) { - if (!doesCollapsibleRegionContains(surroundingRegion.foldingRange, decRange)) { - return null; - } - if (dec.isCollapsed) { - return dec; - } + let region = allRegions[i]; + if (region.isAfterLine(lineNumber)) { + if (!surroundingRegion.contains(region.range)) { + return null; + } + if (region.isCollapsed) { + return region; } } } return null; } -export function doesLineBelongsToCollapsibleRegion(range: IFoldingRange | Range, lineNumber: number): boolean { - return lineNumber >= range.startLineNumber && lineNumber <= range.endLineNumber; -} - -function doesCollapsibleRegionIsAfterLine(range: IFoldingRange | Range, lineNumber: number): boolean { - return lineNumber < range.startLineNumber; -} -function doesCollapsibleRegionIsBeforeLine(range: IFoldingRange | Range, lineNumber: number): boolean { - return lineNumber > range.endLineNumber; -} - -function doesCollapsibleRegionContains(range1: IFoldingRange | Range, range2: IFoldingRange | Range): boolean { - if (range1 instanceof Range && range2 instanceof Range) { - return range1.containsRange(range2); - } - return range1.startLineNumber <= range2.startLineNumber && range1.endLineNumber >= range2.endLineNumber; -} - -function getCollapsibleRegionsFor(surroundingRegion: CollapsibleRegion, allRegions: CollapsibleRegion[], model: editorCommon.IModel, levels: number, up: boolean): CollapsibleRegion[] { - let collapsibleRegionsHierarchy: CollapsibleRegionsHierarchy = up ? new CollapsibleRegionsParentHierarchy(surroundingRegion, allRegions, model) : new CollapsibleRegionsChildrenHierarchy(surroundingRegion, allRegions, model); +function getCollapsibleRegionsFor(model: FoldingModel, surroundingRegion: FoldingRegion, levels: number, up: boolean): FoldingRegion[] { + let collapsibleRegionsHierarchy: CollapsibleRegionsHierarchy = up ? new CollapsibleRegionsParentHierarchy(model, surroundingRegion) : new CollapsibleRegionsChildrenHierarchy(model, surroundingRegion); return collapsibleRegionsHierarchy.getRegionsTill(levels); } interface CollapsibleRegionsHierarchy { - getRegionsTill(level: number): CollapsibleRegion[]; + getRegionsTill(level: number): FoldingRegion[]; } class CollapsibleRegionsChildrenHierarchy implements CollapsibleRegionsHierarchy { @@ -234,29 +372,27 @@ class CollapsibleRegionsChildrenHierarchy implements CollapsibleRegionsHierarchy children: CollapsibleRegionsChildrenHierarchy[] = []; lastChildIndex: number; - constructor(private region: CollapsibleRegion, allRegions: CollapsibleRegion[], model: editorCommon.IModel) { + constructor(model: FoldingModel, private region: FoldingRegion) { + let allRegions = model.regions; for (let index = allRegions.indexOf(region) + 1; index < allRegions.length; index++) { - let dec = allRegions[index]; - let decRange = dec.getDecorationRange(model); - if (decRange) { - if (doesCollapsibleRegionContains(region.foldingRange, decRange)) { - index = this.processChildRegion(dec, allRegions, model, index); - } - if (doesCollapsibleRegionIsAfterLine(decRange, region.foldingRange.endLineNumber)) { - break; - } + let curr = allRegions[index]; + if (curr.contains(region.range)) { + index = this.processChildRegion(model, curr, index); + } + if (curr.isAfterLine(region.range.endLineNumber)) { + break; } } } - private processChildRegion(dec: CollapsibleRegion, allRegions: CollapsibleRegion[], model: editorCommon.IModel, index: number): number { - let childRegion = new CollapsibleRegionsChildrenHierarchy(dec, allRegions, model); + private processChildRegion(model: FoldingModel, dec: FoldingRegion, index: number): number { + let childRegion = new CollapsibleRegionsChildrenHierarchy(model, dec); this.children.push(childRegion); this.lastChildIndex = index; return childRegion.children.length > 0 ? childRegion.lastChildIndex : index; } - public getRegionsTill(level: number): CollapsibleRegion[] { + public getRegionsTill(level: number): FoldingRegion[] { let result = [this.region]; if (level > 1) { this.children.forEach(region => result = result.concat(region.getRegionsTill(level - 1))); @@ -269,23 +405,21 @@ class CollapsibleRegionsParentHierarchy implements CollapsibleRegionsHierarchy { parent: CollapsibleRegionsParentHierarchy; lastChildIndex: number; - constructor(private region: CollapsibleRegion, allRegions: CollapsibleRegion[], model: editorCommon.IModel) { + constructor(model: FoldingModel, private region: FoldingRegion) { + let allRegions = model.regions; for (let index = allRegions.indexOf(region) - 1; index >= 0; index--) { - let dec = allRegions[index]; - let decRange = dec.getDecorationRange(model); - if (decRange) { - if (doesCollapsibleRegionContains(decRange, region.foldingRange)) { - this.parent = new CollapsibleRegionsParentHierarchy(dec, allRegions, model); - break; - } - if (doesCollapsibleRegionIsBeforeLine(decRange, region.foldingRange.endLineNumber)) { - break; - } + let curr = allRegions[index]; + if (curr.contains(region.range)) { + this.parent = new CollapsibleRegionsParentHierarchy(model, curr); + break; + } + if (curr.isBeforeLine(region.range.endLineNumber)) { + break; } } } - public getRegionsTill(level: number): CollapsibleRegion[] { + public getRegionsTill(level: number): FoldingRegion[] { let result = [this.region]; if (this.parent && level > 1) { result = result.concat(this.parent.getRegionsTill(level - 1)); diff --git a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts new file mode 100644 index 00000000000..0f954cf9129 --- /dev/null +++ b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts @@ -0,0 +1,125 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import Event, { Emitter } from 'vs/base/common/event'; +import { Range, IRange } from 'vs/editor/common/core/range'; +import { FoldingRegion, FoldingModel, IFoldingRange } from 'vs/editor/contrib/folding/common/foldingModel'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { Selection } from 'vs/editor/common/core/selection'; +import { findFirst } from 'vs/base/common/arrays'; + + +export class HiddenRangeModel { + private _foldingModel: FoldingModel; + private _hiddenRanges: IRange[] = []; + private _foldingModelListener: IDisposable; + private _updateEventEmitter = new Emitter(); + + public get onDidChange(): Event { return this._updateEventEmitter.event; }; + public get hiddenRanges() { return this._hiddenRanges; } + + public constructor(model: FoldingModel) { + this._foldingModel = model; + this._foldingModelListener = model.onDidChange(_ => this.updateHiddenRanges()); + if (model.regions.length) { + this.updateHiddenRanges(); + } + } + + private updateHiddenRanges(): void { + let updateHiddenAreas = false; + let newHiddenAreas: IRange[] = []; + let i = 0; // index into hidden + + let lastCollapsed: FoldingRegion = null; + + let regions = this._foldingModel.regions; + for (let region of regions) { + if (!region.isCollapsed || lastCollapsed && lastCollapsed.contains(region.range)) { + // ignore ranges contained in collapsed regions + continue; + } + lastCollapsed = region; + let range = region.range; + + if (!updateHiddenAreas && i < this._hiddenRanges.length && matchesHiddenRange(this._hiddenRanges[i], range)) { + newHiddenAreas.push(this._hiddenRanges[i]); + i++; + } else { + updateHiddenAreas = true; + newHiddenAreas.push(new Range(range.startLineNumber + 1, 1, range.endLineNumber, 1)); + } + }; + if (updateHiddenAreas || i < this._hiddenRanges.length) { + this._hiddenRanges = newHiddenAreas; + this._updateEventEmitter.fire(newHiddenAreas); + } + } + + public hasRanges() { + return this._hiddenRanges.length > 0; + } + + public isHidden(line: number): boolean { + return findRange(this._hiddenRanges, line) !== null; + } + + public adjustSelections(selections: Selection[]): boolean { + let hasChanges = false; + let editorModel = this._foldingModel.textModel; + let lastRange = null; + + let adjustLine = (line: number) => { + if (!lastRange || !isInside(line, lastRange)) { + lastRange = findRange(this._hiddenRanges, line); + } + if (lastRange) { + return lastRange.startLineNumber - 1; + } + return null; + }; + for (let i = 0, len = selections.length; i < len; i++) { + let selection = selections[i]; + let adjustedStartLine = adjustLine(selection.startLineNumber); + if (adjustedStartLine) { + selection = selection.setStartPosition(adjustedStartLine, editorModel.getLineMaxColumn(adjustedStartLine)); + hasChanges = true; + } + let adjustedEndLine = adjustLine(selection.endLineNumber); + if (adjustedEndLine) { + selection = selection.setEndPosition(adjustedEndLine, editorModel.getLineMaxColumn(adjustedEndLine)); + hasChanges = true; + } + selections[i] = selection; + } + return hasChanges; + } + + + public dispose() { + if (this.hiddenRanges.length > 0) { + this._hiddenRanges = []; + this._updateEventEmitter.fire(this._hiddenRanges); + } + if (this._foldingModelListener) { + this._foldingModelListener.dispose(); + this._foldingModelListener = null; + } + } +} + +function matchesHiddenRange(hr: IRange, range: IFoldingRange) { + return hr.startLineNumber === range.startLineNumber + 1 && hr.endLineNumber === range.endLineNumber; +} +function isInside(line: number, range: IRange) { + return line >= range.startLineNumber && line <= range.endLineNumber; +} +function findRange(ranges: IRange[], line: number): IRange { + let i = findFirst(ranges, r => line < r.startLineNumber) - 1; + if (i >= 0 && ranges[i].endLineNumber >= line) { + return ranges[i]; + } + return null; +} \ No newline at end of file diff --git a/src/vs/editor/contrib/folding/test/foldingModel.test.ts b/src/vs/editor/contrib/folding/test/foldingModel.test.ts new file mode 100644 index 00000000000..f6a787c2840 --- /dev/null +++ b/src/vs/editor/contrib/folding/test/foldingModel.test.ts @@ -0,0 +1,371 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import { FoldingModel, FoldingRegion, setCollapseStateRecursivly, setCollapseStateAtLevel } from 'vs/editor/contrib/folding/common/foldingModel'; +import { Model } from 'vs/editor/common/model/model'; +import { computeRanges } from 'vs/editor/common/model/indentRanges'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { TrackedRangeStickiness } from 'vs/editor/common/editorCommon'; +import { EditOperation } from 'vs/editor/common/core/editOperation'; +import { Position } from 'vs/editor/common/core/position'; + + +interface ExpectedRegion { + startLineNumber: number; + endLineNumber: number; + isCollapsed: boolean; +} + +export class TestDecorationProvider { + + private testDecorator = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + linesDecorationsClassName: 'folding' + }); + + getDecorationOption(region: FoldingRegion): ModelDecorationOptions { + return this.testDecorator; + } +} + +suite('Folding Model', () => { + function r(startLineNumber: number, endLineNumber: number, isCollapsed: boolean = false): ExpectedRegion { + return { startLineNumber, endLineNumber, isCollapsed }; + } + + function assertRegion(actual: FoldingRegion, expected: ExpectedRegion, message?: string) { + assert.equal(!!actual, !!expected, message); + if (actual) { + assert.equal(actual.range.startLineNumber, expected.startLineNumber, message); + assert.equal(actual.range.endLineNumber, expected.endLineNumber, message); + assert.equal(actual.isCollapsed, expected.isCollapsed, message); + } + } + + function assertFoldedRegions(foldingModel: FoldingModel, expectedRegions: ExpectedRegion[], message?: string) { + assert.deepEqual(foldingModel.regions.filter(r => r.isCollapsed).map(r => ({ startLineNumber: r.range.startLineNumber, endLineNumber: r.range.endLineNumber, isCollapsed: false })), expectedRegions, message); + } + + function assertRegions(actual: FoldingRegion[], expectedRegions: ExpectedRegion[], message?: string) { + assert.deepEqual(actual.map(r => ({ startLineNumber: r.range.startLineNumber, endLineNumber: r.range.endLineNumber, isCollapsed: r.isCollapsed })), expectedRegions, message); + } + + test('getRegionAtLine', () => { + let lines = [ + /* 1*/ '/**', + /* 2*/ ' * Comment', + /* 3*/ ' */', + /* 4*/ 'class A {', + /* 5*/ ' void foo() {', + /* 6*/ ' // comment {', + /* 7*/ ' }', + /* 8*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, null); + foldingModel.update(ranges); + + let r1 = r(1, 3, false); + let r2 = r(4, 7, false); + let r3 = r(5, 6, false); + + assertRegions(foldingModel.regions, [r1, r2, r3]); + + assertRegion(foldingModel.getRegionAtLine(1), r1, '1'); + assertRegion(foldingModel.getRegionAtLine(2), r1, '2'); + assertRegion(foldingModel.getRegionAtLine(3), r1, '3'); + assertRegion(foldingModel.getRegionAtLine(4), r2, '4'); + assertRegion(foldingModel.getRegionAtLine(5), r3, '5'); + assertRegion(foldingModel.getRegionAtLine(6), r3, '5'); + assertRegion(foldingModel.getRegionAtLine(7), r2, '6'); + assertRegion(foldingModel.getRegionAtLine(8), null, '7'); + }); + + test('collapse', () => { + let lines = [ + /* 1*/ '/**', + /* 2*/ ' * Comment', + /* 3*/ ' */', + /* 4*/ 'class A {', + /* 5*/ ' void foo() {', + /* 6*/ ' // comment {', + /* 7*/ ' }', + /* 8*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, null); + foldingModel.update(ranges); + + let r1 = r(1, 3, false); + let r2 = r(4, 7, false); + let r3 = r(5, 6, false); + + assertRegions(foldingModel.regions, [r1, r2, r3]); + + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1)]); + foldingModel.update(ranges); + + assertRegions(foldingModel.regions, [r(1, 3, true), r2, r3]); + + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(5)]); + foldingModel.update(ranges); + + assertRegions(foldingModel.regions, [r(1, 3, true), r2, r(5, 6, true)]); + + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(7)]); + foldingModel.update(ranges); + + assertRegions(foldingModel.regions, [r(1, 3, true), r(4, 7, true), r(5, 6, true)]); + + }); + + test('update', () => { + let lines = [ + /* 1*/ '/**', + /* 2*/ ' * Comment', + /* 3*/ ' */', + /* 4*/ 'class A {', + /* 5*/ ' void foo() {', + /* 6*/ ' // comment {', + /* 7*/ ' }', + /* 8*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, null); + foldingModel.update(ranges); + + let r1 = r(1, 3, false); + let r2 = r(4, 7, false); + let r3 = r(5, 6, false); + + assertRegions(foldingModel.regions, [r1, r2, r3]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(2), foldingModel.getRegionAtLine(5)]); + + textModel.applyEdits([EditOperation.insert(new Position(4, 1), '//hello\n')]); + + foldingModel.update(computeRanges(textModel, false, null)); + + assertRegions(foldingModel.regions, [r(1, 3, true), r(5, 8, false), r(6, 7, true)]); + }); + + test('getRegionsInside', () => { + let lines = [ + /* 1*/ '/**', + /* 2*/ ' * Comment', + /* 3*/ ' */', + /* 4*/ 'class A {', + /* 5*/ ' void foo() {', + /* 6*/ ' // comment {', + /* 7*/ ' }', + /* 8*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, null); + foldingModel.update(ranges); + + let r1 = r(1, 3, false); + let r2 = r(4, 7, false); + let r3 = r(5, 6, false); + + assertRegions(foldingModel.regions, [r1, r2, r3]); + + assertRegions(foldingModel.getRegionsInside(r(1, 8)), [r1, r2, r3], '1'); + assertRegions(foldingModel.getRegionsInside(r(1, 3)), [r1], '2'); + assertRegions(foldingModel.getRegionsInside(r(4, 7)), [r2, r3], '3'); + assertRegions(foldingModel.getRegionsInside(r(4, 6)), [r3], '4'); + assertRegions(foldingModel.getRegionsInside(r(2, 5)), [], '5'); + assertRegions(foldingModel.getRegionsInside(r(6, 8)), [], '6'); + + }); + + test('getRegionsInsideWithLevel', () => { + let lines = [ + /* 1*/ '//#region', + /* 2*/ '//#endregion', + /* 3*/ 'class A {', + /* 4*/ ' void foo() {', + /* 5*/ ' if (true) {', + /* 6*/ ' return;', + /* 7*/ ' }', + /* 8*/ ' if (true) {', + /* 9*/ ' return;', + /* 10*/ ' }', + /* 11*/ ' }', + /* 12*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ }); + foldingModel.update(ranges); + + let r1 = r(1, 2, false); + let r2 = r(3, 11, false); + let r3 = r(4, 10, false); + let r4 = r(5, 6, false); + let r5 = r(8, 9, false); + + assertRegions(foldingModel.regions, [r1, r2, r3, r4, r5]); + + assertRegions(foldingModel.getRegionsInside(r(1, 12), (r, level) => level === 1), [r1, r2], '1'); + assertRegions(foldingModel.getRegionsInside(r(1, 12), (r, level) => level === 2), [r3], '2'); + assertRegions(foldingModel.getRegionsInside(r(1, 12), (r, level) => level === 3), [r4, r5], '3'); + + assertRegions(foldingModel.getRegionsInside(r(4, 11), (r, level) => level === 1), [r3], '4'); + assertRegions(foldingModel.getRegionsInside(r(4, 11), (r, level) => level === 2), [r4, r5], '5'); + + assertRegions(foldingModel.getRegionsInside(r(1, 10), (r) => !r.hidesLine(9)), [r1, r4], '6'); + + }); + + test('getRegionAtLine', () => { + let lines = [ + /* 1*/ '//#region', + /* 2*/ 'class A {', + /* 3*/ ' void foo() {', + /* 4*/ ' if (true) {', + /* 5*/ ' //hello', + /* 6*/ ' }', + /* 7*/ '', + /* 8*/ ' }', + /* 9*/ '}', + /* 10*/ '//#endregion', + /* 11*/ '']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ }); + foldingModel.update(ranges); + + let r1 = r(1, 10, false); + let r2 = r(2, 8, false); + let r3 = r(3, 7, false); + let r4 = r(4, 5, false); + + assertRegions(foldingModel.regions, [r1, r2, r3, r4]); + + assertRegions(foldingModel.getAllRegionsAtLine(1), [r1], '1'); + assertRegions(foldingModel.getAllRegionsAtLine(2), [r1, r2], '2'); + assertRegions(foldingModel.getAllRegionsAtLine(3), [r1, r2, r3], '3'); + assertRegions(foldingModel.getAllRegionsAtLine(4), [r1, r2, r3, r4], '4'); + assertRegions(foldingModel.getAllRegionsAtLine(5), [r1, r2, r3, r4], '5'); + assertRegions(foldingModel.getAllRegionsAtLine(6), [r1, r2, r3], '6'); + assertRegions(foldingModel.getAllRegionsAtLine(7), [r1, r2, r3], '7'); + assertRegions(foldingModel.getAllRegionsAtLine(8), [r1, r2], '8'); + assertRegions(foldingModel.getAllRegionsAtLine(9), [r1], '9'); + assertRegions(foldingModel.getAllRegionsAtLine(10), [r1], '10'); + assertRegions(foldingModel.getAllRegionsAtLine(11), [], '10'); + }); + + test('setCollapseStateRecursivly', () => { + let lines = [ + /* 1*/ '//#region', + /* 2*/ '//#endregion', + /* 3*/ 'class A {', + /* 4*/ ' void foo() {', + /* 5*/ ' if (true) {', + /* 6*/ ' return;', + /* 7*/ ' }', + /* 8*/ '', + /* 9*/ ' if (true) {', + /* 10*/ ' return;', + /* 11*/ ' }', + /* 12*/ ' }', + /* 13*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ }); + foldingModel.update(ranges); + + let r1 = r(1, 2, false); + let r2 = r(3, 12, false); + let r3 = r(4, 11, false); + let r4 = r(5, 6, false); + let r5 = r(9, 10, false); + assertRegions(foldingModel.regions, [r1, r2, r3, r4, r5]); + + setCollapseStateRecursivly(foldingModel, true, [4]); + assertFoldedRegions(foldingModel, [r3, r4, r5], '1'); + + setCollapseStateRecursivly(foldingModel, false, [8]); + assertFoldedRegions(foldingModel, [], '2'); + + setCollapseStateRecursivly(foldingModel, true, [12]); + assertFoldedRegions(foldingModel, [r2, r3, r4, r5], '1'); + + setCollapseStateRecursivly(foldingModel, false, [7]); + assertFoldedRegions(foldingModel, [r2], '1'); + + setCollapseStateRecursivly(foldingModel, false); + assertFoldedRegions(foldingModel, [], '1'); + + setCollapseStateRecursivly(foldingModel, true); + assertFoldedRegions(foldingModel, [r1, r2, r3, r4, r5], '1'); + + }); + + test('setCollapseStateAtLevel', () => { + let lines = [ + /* 1*/ '//#region', + /* 2*/ '//#endregion', + /* 3*/ 'class A {', + /* 4*/ ' void foo() {', + /* 5*/ ' if (true) {', + /* 6*/ ' return;', + /* 7*/ ' }', + /* 8*/ '', + /* 9*/ ' if (true) {', + /* 10*/ ' return;', + /* 11*/ ' }', + /* 12*/ ' }', + /* 13*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ }); + foldingModel.update(ranges); + + let r1 = r(1, 2, false); + let r2 = r(3, 12, false); + let r3 = r(4, 11, false); + let r4 = r(5, 6, false); + let r5 = r(9, 10, false); + assertRegions(foldingModel.regions, [r1, r2, r3, r4, r5]); + + setCollapseStateAtLevel(foldingModel, 1, true, []); + assertFoldedRegions(foldingModel, [r1, r2], '1'); + + setCollapseStateAtLevel(foldingModel, 1, false, [5]); + assertFoldedRegions(foldingModel, [r2], '1'); + + setCollapseStateAtLevel(foldingModel, 1, false, [1]); + assertFoldedRegions(foldingModel, [], '1'); + + setCollapseStateAtLevel(foldingModel, 2, true, []); + assertFoldedRegions(foldingModel, [r3], '1'); + + setCollapseStateAtLevel(foldingModel, 3, true, [4, 9]); + assertFoldedRegions(foldingModel, [r3, r4], '1'); + + setCollapseStateAtLevel(foldingModel, 3, false, [4, 9]); + assertFoldedRegions(foldingModel, [r3], '1'); + + }); + +}); \ No newline at end of file diff --git a/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts b/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts new file mode 100644 index 00000000000..e8c0c409e75 --- /dev/null +++ b/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import { FoldingModel } from 'vs/editor/contrib/folding/common/foldingModel'; +import { Model } from 'vs/editor/common/model/model'; +import { computeRanges } from 'vs/editor/common/model/indentRanges'; +import { TestDecorationProvider } from './foldingModel.test'; +import { HiddenRangeModel } from 'vs/editor/contrib/folding/common/hiddenRangeModel'; +import { IRange } from 'vs/editor/common/core/range'; + + +interface ExpectedRange { + startLineNumber: number; + endLineNumber: number; +} + +suite('Hidden Range Model', () => { + function r(startLineNumber: number, endLineNumber: number): ExpectedRange { + return { startLineNumber, endLineNumber }; + } + + function assertRanges(actual: IRange[], expectedRegions: ExpectedRange[], message?: string) { + assert.deepEqual(actual.map(r => ({ startLineNumber: r.startLineNumber, endLineNumber: r.endLineNumber })), expectedRegions, message); + } + + test('hasRanges', () => { + let lines = [ + /* 1*/ '/**', + /* 2*/ ' * Comment', + /* 3*/ ' */', + /* 4*/ 'class A {', + /* 5*/ ' void foo() {', + /* 6*/ ' if (true) {', + /* 7*/ ' //hello', + /* 8*/ ' }', + /* 9*/ ' }', + /* 10*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + let hiddenRangeModel = new HiddenRangeModel(foldingModel); + + assert.equal(hiddenRangeModel.hasRanges(), false); + + let ranges = computeRanges(textModel, false, null); + foldingModel.update(ranges); + + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1), foldingModel.getRegionAtLine(6)]); + assertRanges(hiddenRangeModel.hiddenRanges, [r(2, 3), r(7, 7)]); + + assert.equal(hiddenRangeModel.hasRanges(), true); + assert.equal(hiddenRangeModel.isHidden(1), false); + assert.equal(hiddenRangeModel.isHidden(2), true); + assert.equal(hiddenRangeModel.isHidden(3), true); + assert.equal(hiddenRangeModel.isHidden(4), false); + assert.equal(hiddenRangeModel.isHidden(5), false); + assert.equal(hiddenRangeModel.isHidden(6), false); + assert.equal(hiddenRangeModel.isHidden(7), true); + assert.equal(hiddenRangeModel.isHidden(8), false); + assert.equal(hiddenRangeModel.isHidden(9), false); + assert.equal(hiddenRangeModel.isHidden(10), false); + + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(4)]); + assertRanges(hiddenRangeModel.hiddenRanges, [r(2, 3), r(5, 9)]); + + assert.equal(hiddenRangeModel.hasRanges(), true); + assert.equal(hiddenRangeModel.isHidden(1), false); + assert.equal(hiddenRangeModel.isHidden(2), true); + assert.equal(hiddenRangeModel.isHidden(3), true); + assert.equal(hiddenRangeModel.isHidden(4), false); + assert.equal(hiddenRangeModel.isHidden(5), true); + assert.equal(hiddenRangeModel.isHidden(6), true); + assert.equal(hiddenRangeModel.isHidden(7), true); + assert.equal(hiddenRangeModel.isHidden(8), true); + assert.equal(hiddenRangeModel.isHidden(9), true); + assert.equal(hiddenRangeModel.isHidden(10), false); + + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1), foldingModel.getRegionAtLine(6), foldingModel.getRegionAtLine(4)]); + assertRanges(hiddenRangeModel.hiddenRanges, []); + assert.equal(hiddenRangeModel.hasRanges(), false); + assert.equal(hiddenRangeModel.isHidden(1), false); + assert.equal(hiddenRangeModel.isHidden(2), false); + assert.equal(hiddenRangeModel.isHidden(3), false); + assert.equal(hiddenRangeModel.isHidden(4), false); + assert.equal(hiddenRangeModel.isHidden(5), false); + assert.equal(hiddenRangeModel.isHidden(6), false); + assert.equal(hiddenRangeModel.isHidden(7), false); + assert.equal(hiddenRangeModel.isHidden(8), false); + assert.equal(hiddenRangeModel.isHidden(9), false); + assert.equal(hiddenRangeModel.isHidden(10), false); + + }); + + +}); \ No newline at end of file From 0d1c1e6296a13629f02bca87c87824efc9f56a68 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 15:14:56 +0200 Subject: [PATCH 255/394] Store decorations in two trees, one with all decorations that appear in the overview ruler, and one with decorations that do not appear in the overview ruler --- src/vs/editor/common/model/intervalTree.ts | 24 ++--- .../common/model/textModelWithDecorations.ts | 101 +++++++++++++++++- 2 files changed, 108 insertions(+), 17 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 83d15c75a34..fd975e97e41 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -80,7 +80,7 @@ function setNodeIsForValidation(node: IntervalNode, value: boolean): void { (node.metadata & Constants.IsForValidationMaskInverse) | ((value ? 1 : 0) << Constants.IsForValidationOffset) ); } -function getNodeIsInOverviewRuler(node: IntervalNode): boolean { +export function getNodeIsInOverviewRuler(node: IntervalNode): boolean { return ((node.metadata & Constants.IsInOverviewRulerMask) >>> Constants.IsInOverviewRulerOffset) === 1; } function setNodeIsInOverviewRuler(node: IntervalNode, value: boolean): void { @@ -207,11 +207,11 @@ export class IntervalTree { return intervalSearch(this, start, end, filterOwnerId, filterOutValidation, cachedVersionId); } - public search(filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { + public search(filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { if (this.root === SENTINEL) { return []; } - return search(this, filterOwnerId, filterOutValidation, overviewRulerOnly, cachedVersionId); + return search(this, filterOwnerId, filterOutValidation, cachedVersionId); } public count(): number { @@ -228,6 +228,13 @@ export class IntervalTree { return collectNodesFromOwner(this, ownerId); } + /** + * Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes! + */ + public collectNodesPostOrder(): IntervalNode[] { + return collectNodesPostOrder(this); + } + public insert(node: IntervalNode): void { rbTreeInsert(this, node); } @@ -277,10 +284,6 @@ export class IntervalTree { } } - public collectNodesPostOrder(): IntervalNode[] { - return collectNodesPostOrder(this); - } - public assertInvariants(): void { assert(getNodeColor(SENTINEL) === NodeColor.Black); assert(SENTINEL.parent === SENTINEL); @@ -294,7 +297,7 @@ export class IntervalTree { } public getAllInOrder(): IntervalNode[] { - return search(this, 0, false, false, 0); + return search(this, 0, false, 0); } public print(): void { @@ -679,7 +682,7 @@ function collectNodesPostOrder(T: IntervalTree): IntervalNode[] { return result; } -function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { +function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { let node = T.root; let delta = 0; let nodeStart = 0; @@ -717,9 +720,6 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo if (filterOutValidation && getNodeIsForValidation(node)) { include = false; } - if (overviewRulerOnly && !getNodeIsInOverviewRuler(node)) { - include = false; - } if (include) { result[resultLen++] = node; } diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index a024b227d6d..ff79fbfccce 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -15,7 +15,7 @@ import { LanguageIdentifier } from 'vs/editor/common/modes'; import { ITextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; -import { IntervalNode, IntervalTree, recomputeMaxEnd } from 'vs/editor/common/model/intervalTree'; +import { IntervalNode, IntervalTree, recomputeMaxEnd, getNodeIsInOverviewRuler } from 'vs/editor/common/model/intervalTree'; let _INSTANCE_COUNT = 0; /** @@ -45,7 +45,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi private _currentDecorationsTrackerCnt: number; private _currentDecorationsTrackerDidChange: boolean; private _decorations: { [decorationId: string]: IntervalNode; }; - private _decorationsTree: IntervalTree; + private _decorationsTree: DecorationsTrees; constructor(rawTextSource: IRawTextSource, creationOptions: editorCommon.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier) { super(rawTextSource, creationOptions, languageIdentifier); @@ -55,7 +55,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi this._currentDecorationsTrackerCnt = 0; this._currentDecorationsTrackerDidChange = false; this._decorations = Object.create(null); - this._decorationsTree = new IntervalTree(); + this._decorationsTree = new DecorationsTrees(); } public dispose(): void { @@ -70,7 +70,7 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi // Destroy all my decorations this._decorations = Object.create(null); - this._decorationsTree = new IntervalTree(); + this._decorationsTree = new DecorationsTrees(); } _getTrackedRangesCount(): number { @@ -371,7 +371,17 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi return; } - node.setOptions(options); + const nodeWasInOverviewRuler = (node.options.overviewRuler.color ? true : false); + const nodeIsInOverviewRuler = (options.overviewRuler.color ? true : false); + + if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) { + // Delete + Insert due to an overview ruler status change + this._decorationsTree.delete(node); + node.setOptions(options); + this._decorationsTree.insert(node); + } else { + node.setOptions(options); + } } private _deltaDecorationsImpl(ownerId: number, oldDecorationsIds: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[] { @@ -436,6 +446,87 @@ export class TextModelWithDecorations extends TextModelWithTokens implements edi } } +class DecorationsTrees { + + /** + * This tree holds decorations that do not show up in the overview ruler. + */ + private _decorationsTree0: IntervalTree; + + /** + * This tree holds decorations that show up in the overview ruler. + */ + private _decorationsTree1: IntervalTree; + + constructor() { + this._decorationsTree0 = new IntervalTree(); + this._decorationsTree1 = new IntervalTree(); + } + + public intervalSearch(start: number, end: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { + const r0 = this._decorationsTree0.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId); + const r1 = this._decorationsTree1.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId); + return r0.concat(r1); + } + + public search(filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { + if (overviewRulerOnly) { + return this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId); + } else { + const r0 = this._decorationsTree0.search(filterOwnerId, filterOutValidation, cachedVersionId); + const r1 = this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId); + return r0.concat(r1); + } + } + + public count(): number { + const c0 = this._decorationsTree0.count(); + const c1 = this._decorationsTree1.count(); + return c0 + c1; + } + + public collectNodesFromOwner(ownerId: number): IntervalNode[] { + const r0 = this._decorationsTree0.collectNodesFromOwner(ownerId); + const r1 = this._decorationsTree1.collectNodesFromOwner(ownerId); + return r0.concat(r1); + } + + public collectNodesPostOrder(): IntervalNode[] { + const r0 = this._decorationsTree0.collectNodesPostOrder(); + const r1 = this._decorationsTree1.collectNodesPostOrder(); + return r0.concat(r1); + } + + public insert(node: IntervalNode): void { + if (getNodeIsInOverviewRuler(node)) { + this._decorationsTree1.insert(node); + } else { + this._decorationsTree0.insert(node); + } + } + + public delete(node: IntervalNode): void { + if (getNodeIsInOverviewRuler(node)) { + this._decorationsTree1.delete(node); + } else { + this._decorationsTree0.delete(node); + } + } + + public resolveNode(node: IntervalNode, cachedVersionId: number): void { + if (getNodeIsInOverviewRuler(node)) { + this._decorationsTree1.resolveNode(node, cachedVersionId); + } else { + this._decorationsTree0.resolveNode(node, cachedVersionId); + } + } + + public acceptReplace(offset: number, length: number, textLength: number, forceMoveMarkers: boolean): void { + this._decorationsTree0.acceptReplace(offset, length, textLength, forceMoveMarkers); + this._decorationsTree1.acceptReplace(offset, length, textLength, forceMoveMarkers); + } +} + function cleanClassName(className: string): string { return className.replace(/[^a-z0-9\-]/gi, ' '); } From b5138af4293acc730430aa04fe2d15f65fbc0e47 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 15:31:40 +0200 Subject: [PATCH 256/394] ActivityService --- .../parts/activitybar/activitybarPart.ts | 4 +-- .../parts/compositebar/compositeBar.ts | 2 +- .../parts/compositebar/compositeBarActions.ts | 2 +- .../browser/parts/panel/panelPart.ts | 7 ++++- .../workbench/electron-browser/workbench.ts | 6 ++-- .../electron-browser/extensionsViewlet.ts | 8 ++--- .../parts/files/common/dirtyFilesTracker.ts | 6 ++-- .../parts/scm/electron-browser/scmActivity.ts | 6 ++-- .../parts/update/electron-browser/update.ts | 6 ++-- .../activity/browser/activityService.ts | 31 +++++++++++++++++++ .../{activityBarService.ts => activity.ts} | 8 ++--- .../progress/browser/progressService2.ts | 2 -- 12 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 src/vs/workbench/services/activity/browser/activityService.ts rename src/vs/workbench/services/activity/common/{activityBarService.ts => activity.ts} (82%) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 842b4f2d76f..13674e9edd6 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -17,7 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Part } from 'vs/workbench/browser/part'; import { GlobalActivityActionItem, GlobalActivityAction, ViewletActivityAction, ToggleViewletAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { IActivityBarService, IBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IPartService, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; @@ -32,7 +32,7 @@ import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; -export class ActivitybarPart extends Part implements IActivityBarService { +export class ActivitybarPart extends Part { private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets'; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 37d2ba36ed9..07c8d3b6efc 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -12,7 +12,7 @@ import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; import { Dimension } from 'vs/base/browser/builder'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { IBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 914b4a935c0..d01442ab9e4 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -15,7 +15,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { dispose } from 'vs/base/common/lifecycle'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; -import { TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_BADGE_BACKGROUND } from 'vs/workbench/common/theme'; diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index b64f22d394f..29984f1f377 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -29,7 +29,8 @@ import { activeContrastBorder, focusBorder, contrastBorder, editorBackground } f import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { dispose } from 'vs/base/common/lifecycle'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { IBadge } from 'vs/workbench/services/activity/common/activity'; export class PanelPart extends CompositePart implements IPanelService { @@ -137,6 +138,10 @@ export class PanelPart extends CompositePart implements IPanelService { return promise.then(() => this.openComposite(id, focus)); } + public showActivity(panelId: string, badge: IBadge, clazz?: string): IDisposable { + return this.compositeBar.showActivity(panelId, badge, clazz); + } + private getPanel(panelId: string): IPanelIdentifier { return Registry.as(PanelExtensions.Panels).getPanels().filter(p => p.id === panelId).pop(); } diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 89a41c79fb2..5b34ea90179 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -52,7 +52,7 @@ import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyServ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing'; import { ContextKeyExpr, RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IActivityBarService } from 'vs/workbench/services/activity/common/activityBarService'; +import { IActivityService } from 'vs/workbench/services/activity/common/activity'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { ViewletService } from 'vs/workbench/services/viewlet/browser/viewletService'; import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService'; @@ -96,6 +96,7 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService'; import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService'; import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; +import { ActivityService } from 'vs/workbench/services/activity/browser/activityService'; import URI from 'vs/base/common/uri'; export const MessagesVisibleContext = new RawContextKey('globalMessageVisible', false); @@ -550,7 +551,8 @@ export class Workbench implements IPartService { this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART); this.toDispose.push(this.activitybarPart); this.toShutdown.push(this.activitybarPart); - serviceCollection.set(IActivityBarService, this.activitybarPart); + const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart); + serviceCollection.set(IActivityService, activityService); // File Service this.fileService = this.instantiationService.createInstance(RemoteFileService); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts index 317a82c415b..26f160e6164 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts @@ -41,7 +41,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; import Severity from 'vs/base/common/severity'; -import { IActivityBarService, ProgressBadge, NumberBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IActivityService, ProgressBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { inputForeground, inputBackground, inputBorder } from 'vs/platform/theme/common/colorRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -399,7 +399,7 @@ export class StatusUpdater implements IWorkbenchContribution { private badgeHandle: IDisposable; constructor( - @IActivityBarService private activityBarService: IActivityBarService, + @IActivityService private activityService: IActivityService, @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService ) { extensionsWorkbenchService.onChange(this.onServiceChange, this, this.disposables); @@ -414,14 +414,14 @@ export class StatusUpdater implements IWorkbenchContribution { dispose(this.badgeHandle); if (this.extensionsWorkbenchService.local.some(e => e.state === ExtensionState.Installing)) { - this.badgeHandle = this.activityBarService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge'); + this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge'); return; } const outdated = this.extensionsWorkbenchService.local.reduce((r, e) => r + (e.outdated ? 1 : 0), 0); if (outdated > 0) { const badge = new NumberBadge(outdated, n => localize('outdatedExtensions', '{0} Outdated Extensions', n)); - this.badgeHandle = this.activityBarService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge'); + this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge'); } } diff --git a/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts b/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts index f02e1e86e24..31c62f9d546 100644 --- a/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts +++ b/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts @@ -19,7 +19,7 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IActivityBarService, NumberBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import arrays = require('vs/base/common/arrays'); @@ -35,7 +35,7 @@ export class DirtyFilesTracker implements IWorkbenchContribution { @ILifecycleService private lifecycleService: ILifecycleService, @IEditorGroupService editorGroupService: IEditorGroupService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IActivityBarService private activityBarService: IActivityBarService, + @IActivityService private activityService: IActivityService, @IWindowService private windowService: IWindowService, @IUntitledEditorService private untitledEditorService: IUntitledEditorService ) { @@ -141,7 +141,7 @@ export class DirtyFilesTracker implements IWorkbenchContribution { this.lastDirtyCount = dirtyCount; dispose(this.badgeHandle); if (dirtyCount > 0) { - this.badgeHandle = this.activityBarService.showActivity(VIEWLET_ID, new NumberBadge(dirtyCount, num => num === 1 ? nls.localize('dirtyFile', "1 unsaved file") : nls.localize('dirtyFiles', "{0} unsaved files", dirtyCount)), 'explorer-viewlet-label'); + this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, new NumberBadge(dirtyCount, num => num === 1 ? nls.localize('dirtyFile', "1 unsaved file") : nls.localize('dirtyFiles', "{0} unsaved files", dirtyCount)), 'explorer-viewlet-label'); } } diff --git a/src/vs/workbench/parts/scm/electron-browser/scmActivity.ts b/src/vs/workbench/parts/scm/electron-browser/scmActivity.ts index f5900b648ef..2558e2a1717 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmActivity.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmActivity.ts @@ -11,7 +11,7 @@ import { IDisposable, dispose, empty as EmptyDisposable, combinedDisposable } fr import { filterEvent, any as anyEvent } from 'vs/base/common/event'; import { VIEWLET_ID } from 'vs/workbench/parts/scm/common/scm'; import { ISCMService, ISCMRepository } from 'vs/workbench/services/scm/common/scm'; -import { IActivityBarService, NumberBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar'; @@ -25,7 +25,7 @@ export class StatusUpdater implements IWorkbenchContribution { constructor( @ISCMService private scmService: ISCMService, - @IActivityBarService private activityBarService: IActivityBarService + @IActivityService private activityService: IActivityService ) { this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables); this.render(); @@ -64,7 +64,7 @@ export class StatusUpdater implements IWorkbenchContribution { if (count > 0) { const badge = new NumberBadge(count, num => localize('scmPendingChangesBadge', '{0} pending changes', num)); - this.badgeDisposable = this.activityBarService.showActivity(VIEWLET_ID, badge, 'scm-viewlet-label'); + this.badgeDisposable = this.activityService.showActivity(VIEWLET_ID, badge, 'scm-viewlet-label'); } else { this.badgeDisposable = EmptyDisposable; } diff --git a/src/vs/workbench/parts/update/electron-browser/update.ts b/src/vs/workbench/parts/update/electron-browser/update.ts index 9795b43c6ed..6440c37f601 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.ts @@ -17,7 +17,7 @@ import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; import URI from 'vs/base/common/uri'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IActivityBarService, NumberBadge } from 'vs/workbench/services/activity/common/activityBarService'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput'; import { IGlobalActivity } from 'vs/workbench/common/activity'; @@ -323,7 +323,7 @@ export class UpdateContribution implements IGlobalActivity { @IMessageService private messageService: IMessageService, @IUpdateService private updateService: IUpdateService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, - @IActivityBarService private activityBarService: IActivityBarService + @IActivityService private activityService: IActivityService ) { const onUpdateAvailable = isLinux ? mapEvent(updateService.onUpdateAvailable, e => e.version) @@ -363,7 +363,7 @@ export class UpdateContribution implements IGlobalActivity { if (isUpdateAvailable) { const badge = new NumberBadge(1, () => nls.localize('updateIsReady', "New {0} update available.", product.nameShort)); - this.badgeDisposable = this.activityBarService.showActivity(this.id, badge); + this.badgeDisposable = this.activityService.showActivity(this.id, badge); } } diff --git a/src/vs/workbench/services/activity/browser/activityService.ts b/src/vs/workbench/services/activity/browser/activityService.ts new file mode 100644 index 00000000000..4f328baa8ae --- /dev/null +++ b/src/vs/workbench/services/activity/browser/activityService.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart'; +import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart'; +import { IActivityService, IBadge } from 'vs/workbench/services/activity/common/activity'; +import { IDisposable } from 'vs/base/common/lifecycle'; + +export class ActivityService implements IActivityService { + + public _serviceBrand: any; + + constructor( + private activitybarPart: ActivitybarPart, + private panelPart: PanelPart, + @IPanelService private panelService: IPanelService + ) { } + + public showActivity(compositeOrActionId: string, badge: IBadge, clazz?: string): IDisposable { + if (this.panelService.getPanels().filter(p => p.id === compositeOrActionId).length) { + return this.panelPart.showActivity(compositeOrActionId, badge, clazz); + } + + return this.activitybarPart.showActivity(compositeOrActionId, badge, clazz); + } +} diff --git a/src/vs/workbench/services/activity/common/activityBarService.ts b/src/vs/workbench/services/activity/common/activity.ts similarity index 82% rename from src/vs/workbench/services/activity/common/activityBarService.ts rename to src/vs/workbench/services/activity/common/activity.ts index 2d7d55ce74b..e2f5286ba2e 100644 --- a/src/vs/workbench/services/activity/common/activityBarService.ts +++ b/src/vs/workbench/services/activity/common/activity.ts @@ -58,13 +58,13 @@ export class IconBadge extends BaseBadge { export class ProgressBadge extends BaseBadge { } -export const IActivityBarService = createDecorator('activityBarService'); +export const IActivityService = createDecorator('activityService'); -export interface IActivityBarService { +export interface IActivityService { _serviceBrand: any; /** - * Show activity in the activitybar for the given viewlet or global action. + * Show activity in the panel for the given panel or in the activitybar for the given viewlet or global action. */ - showActivity(viewletOrActionId: string, badge: IBadge, clazz?: string): IDisposable; + showActivity(compositeOrActionId: string, badge: IBadge, clazz?: string): IDisposable; } diff --git a/src/vs/workbench/services/progress/browser/progressService2.ts b/src/vs/workbench/services/progress/browser/progressService2.ts index a47ab0f2c3a..b6de990d858 100644 --- a/src/vs/workbench/services/progress/browser/progressService2.ts +++ b/src/vs/workbench/services/progress/browser/progressService2.ts @@ -7,7 +7,6 @@ import 'vs/css!./media/progressService2'; import * as dom from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; -import { IActivityBarService } from 'vs/workbench/services/activity/common/activityBarService'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IProgressService2, IProgressOptions, ProgressLocation, IProgress, IProgressStep, Progress, emptyProgress } from 'vs/platform/progress/common/progress'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -61,7 +60,6 @@ export class ProgressService2 implements IProgressService2 { private _stack: [IProgressOptions, Progress][] = []; constructor( - @IActivityBarService private _activityBar: IActivityBarService, @IViewletService private _viewletService: IViewletService ) { // From caa5593e4afb2a30ce2c17dc923c231000b26574 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 15:35:20 +0200 Subject: [PATCH 257/394] Reimplement the decorations overview ruler --- src/vs/editor/browser/view/viewImpl.ts | 4 +- .../overviewRuler/decorationsOverviewRuler.ts | 267 ---------- .../decorationsOverviewRuler2.ts | 488 ++++++++++++++++++ 3 files changed, 490 insertions(+), 269 deletions(-) delete mode 100644 src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts create mode 100644 src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 1a53e3d9814..8e14fe9b1ff 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -30,7 +30,7 @@ import { Margin } from 'vs/editor/browser/viewParts/margin/margin'; import { LinesDecorationsOverlay } from 'vs/editor/browser/viewParts/linesDecorations/linesDecorations'; import { MarginViewLineDecorationsOverlay } from 'vs/editor/browser/viewParts/marginDecorations/marginDecorations'; import { ViewOverlayWidgets } from 'vs/editor/browser/viewParts/overlayWidgets/overlayWidgets'; -import { DecorationsOverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler'; +import { DecorationsOverviewRuler2 } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2'; import { OverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/overviewRuler'; import { Rulers } from 'vs/editor/browser/viewParts/rulers/rulers'; import { ScrollDecorationViewPart } from 'vs/editor/browser/viewParts/scrollDecoration/scrollDecoration'; @@ -170,7 +170,7 @@ export class View extends ViewEventHandler { this.viewParts.push(this.viewZones); // Decorations overview ruler - let decorationsOverviewRuler = new DecorationsOverviewRuler(this._context); + let decorationsOverviewRuler = new DecorationsOverviewRuler2(this._context); this.viewParts.push(decorationsOverviewRuler); diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts deleted file mode 100644 index 91ebeaf3945..00000000000 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ /dev/null @@ -1,267 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as editorCommon from 'vs/editor/common/editorCommon'; -import { ViewPart } from 'vs/editor/browser/view/viewPart'; -import { OverviewRulerImpl } from 'vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl'; -import { ViewContext } from 'vs/editor/common/view/viewContext'; -import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext'; -import { Position } from 'vs/editor/common/core/position'; -import { TokenizationRegistry } from 'vs/editor/common/modes'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import * as viewEvents from 'vs/editor/common/view/viewEvents'; -import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager'; -import { editorOverviewRulerBorder, editorCursorForeground } from 'vs/editor/common/view/editorColorRegistry'; -import { Color } from 'vs/base/common/color'; -import { ThemeColor } from 'vs/platform/theme/common/themeService'; - -export class DecorationsOverviewRuler extends ViewPart { - - static MIN_DECORATION_HEIGHT = 6; - static MAX_DECORATION_HEIGHT = 60; - - private readonly _tokensColorTrackerListener: IDisposable; - - private _overviewRuler: OverviewRulerImpl; - - private _renderBorder: boolean; - private _borderColor: string; - private _cursorColor: string; - - private _shouldUpdateDecorations: boolean; - private _shouldUpdateCursorPosition: boolean; - - private _hideCursor: boolean; - private _cursorPositions: Position[]; - - private _zonesFromDecorations: OverviewRulerZone[]; - private _zonesFromCursors: OverviewRulerZone[]; - - constructor(context: ViewContext) { - super(context); - this._overviewRuler = new OverviewRulerImpl( - 1, - 'decorationsOverviewRuler', - this._context.viewLayout.getScrollHeight(), - this._context.configuration.editor.lineHeight, - this._context.configuration.editor.pixelRatio, - DecorationsOverviewRuler.MIN_DECORATION_HEIGHT, - DecorationsOverviewRuler.MAX_DECORATION_HEIGHT, - (lineNumber: number) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber) - ); - this._overviewRuler.setLanesCount(this._context.configuration.editor.viewInfo.overviewRulerLanes, false); - this._overviewRuler.setLayout(this._context.configuration.editor.layoutInfo.overviewRuler, false); - - this._renderBorder = this._context.configuration.editor.viewInfo.overviewRulerBorder; - - this._updateColors(); - - this._updateBackground(false); - this._tokensColorTrackerListener = TokenizationRegistry.onDidChange((e) => { - if (e.changedColorMap) { - this._updateBackground(true); - } - }); - - this._shouldUpdateDecorations = true; - this._zonesFromDecorations = []; - - this._shouldUpdateCursorPosition = true; - this._hideCursor = this._context.configuration.editor.viewInfo.hideCursorInOverviewRuler; - - this._zonesFromCursors = []; - this._cursorPositions = []; - } - - public dispose(): void { - super.dispose(); - this._overviewRuler.dispose(); - this._tokensColorTrackerListener.dispose(); - } - - private _updateBackground(render: boolean): void { - const minimapEnabled = this._context.configuration.editor.viewInfo.minimap.enabled; - this._overviewRuler.setUseBackground((minimapEnabled ? TokenizationRegistry.getDefaultBackground() : null), render); - } - - // ---- begin view event handlers - - public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { - let prevLanesCount = this._overviewRuler.getLanesCount(); - let newLanesCount = this._context.configuration.editor.viewInfo.overviewRulerLanes; - - if (prevLanesCount !== newLanesCount) { - this._overviewRuler.setLanesCount(newLanesCount, false); - } - - if (e.lineHeight) { - this._overviewRuler.setLineHeight(this._context.configuration.editor.lineHeight, false); - } - - if (e.pixelRatio) { - this._overviewRuler.setPixelRatio(this._context.configuration.editor.pixelRatio, false); - } - - if (e.viewInfo) { - this._renderBorder = this._context.configuration.editor.viewInfo.overviewRulerBorder; - this._hideCursor = this._context.configuration.editor.viewInfo.hideCursorInOverviewRuler; - this._shouldUpdateCursorPosition = true; - this._updateBackground(false); - } - - if (e.layoutInfo) { - this._overviewRuler.setLayout(this._context.configuration.editor.layoutInfo.overviewRuler, false); - } - - return true; - } - - public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { - this._shouldUpdateCursorPosition = true; - this._cursorPositions = []; - for (let i = 0, len = e.selections.length; i < len; i++) { - this._cursorPositions[i] = e.selections[i].getPosition(); - } - return true; - } - - public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { - this._shouldUpdateDecorations = true; - return true; - } - - public onFlushed(e: viewEvents.ViewFlushedEvent): boolean { - this._shouldUpdateCursorPosition = true; - this._shouldUpdateDecorations = true; - return true; - } - - public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean { - this._overviewRuler.setScrollHeight(e.scrollHeight, false); - return super.onScrollChanged(e) || e.scrollHeightChanged; - } - - public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean { - return true; - } - - public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean { - this._updateColors(); - this._shouldUpdateDecorations = true; - this._shouldUpdateCursorPosition = true; - return true; - } - - // ---- end view event handlers - - public getDomNode(): HTMLElement { - return this._overviewRuler.getDomNode(); - } - - private _updateColors() { - let borderColor = this._context.theme.getColor(editorOverviewRulerBorder); - this._borderColor = borderColor ? borderColor.toString() : null; - - let cursorColor = this._context.theme.getColor(editorCursorForeground); - this._cursorColor = cursorColor ? cursorColor.transparent(0.7).toString() : null; - - this._overviewRuler.setThemeType(this._context.theme.type, false); - } - - private _createZonesFromDecorations(): OverviewRulerZone[] { - let decorations = this._context.model.getAllOverviewRulerDecorations(); - let zones: OverviewRulerZone[] = []; - - for (let i = 0, len = decorations.length; i < len; i++) { - let dec = decorations[i]; - let overviewRuler = dec.source.options.overviewRuler; - zones[i] = new OverviewRulerZone( - dec.range.startLineNumber, - dec.range.endLineNumber, - overviewRuler.position, - 0, - this.resolveRulerColor(overviewRuler.color), - this.resolveRulerColor(overviewRuler.darkColor), - this.resolveRulerColor(overviewRuler.hcColor) - ); - } - - return zones; - } - - private resolveRulerColor(color: string | ThemeColor): string { - if (editorCommon.isThemeColor(color)) { - let c = this._context.theme.getColor(color.id) || Color.transparent; - return c.toString(); - } - return color; - } - - private _createZonesFromCursors(): OverviewRulerZone[] { - let zones: OverviewRulerZone[] = []; - - for (let i = 0, len = this._cursorPositions.length; i < len; i++) { - let cursor = this._cursorPositions[i]; - - zones[i] = new OverviewRulerZone( - cursor.lineNumber, - cursor.lineNumber, - editorCommon.OverviewRulerLane.Full, - 2, - this._cursorColor, - this._cursorColor, - this._cursorColor - ); - } - - return zones; - } - - public prepareRender(ctx: RenderingContext): void { - // Nothing to read - } - - public render(ctx: RestrictedRenderingContext): void { - if (this._shouldUpdateDecorations || this._shouldUpdateCursorPosition) { - - if (this._shouldUpdateDecorations) { - this._shouldUpdateDecorations = false; - this._zonesFromDecorations = this._createZonesFromDecorations(); - } - - if (this._shouldUpdateCursorPosition) { - this._shouldUpdateCursorPosition = false; - if (this._hideCursor) { - this._zonesFromCursors = []; - } else { - this._zonesFromCursors = this._createZonesFromCursors(); - } - } - - let allZones: OverviewRulerZone[] = []; - allZones = allZones.concat(this._zonesFromCursors); - allZones = allZones.concat(this._zonesFromDecorations); - - this._overviewRuler.setZones(allZones, false); - } - - let hasRendered = this._overviewRuler.render(false); - - if (hasRendered && this._renderBorder && this._borderColor && this._overviewRuler.getLanesCount() > 0 && (this._zonesFromDecorations.length > 0 || this._zonesFromCursors.length > 0)) { - let ctx2 = this._overviewRuler.getDomNode().getContext('2d'); - ctx2.beginPath(); - ctx2.lineWidth = 1; - ctx2.strokeStyle = this._borderColor; - ctx2.moveTo(0, 0); - ctx2.lineTo(0, this._overviewRuler.getPixelHeight()); - ctx2.stroke(); - - ctx2.moveTo(0, 0); - ctx2.lineTo(this._overviewRuler.getPixelWidth(), 0); - ctx2.stroke(); - } - } -} diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts new file mode 100644 index 00000000000..3586b00f799 --- /dev/null +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts @@ -0,0 +1,488 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as editorCommon from 'vs/editor/common/editorCommon'; +import { ViewPart } from 'vs/editor/browser/view/viewPart'; +import { ViewContext } from 'vs/editor/common/view/viewContext'; +import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext'; +import { Position } from 'vs/editor/common/core/position'; +import { TokenizationRegistry } from 'vs/editor/common/modes'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import * as viewEvents from 'vs/editor/common/view/viewEvents'; +import { editorOverviewRulerBorder, editorCursorForeground } from 'vs/editor/common/view/editorColorRegistry'; +import { Color } from 'vs/base/common/color'; +import { ITheme, ThemeColor } from 'vs/platform/theme/common/themeService'; +import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; +import { ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations'; + +class Settings { + + public readonly lineHeight: number; + public readonly pixelRatio: number; + public readonly overviewRulerLanes: number; + + public readonly renderBorder: boolean; + public readonly borderColor: string; + + public readonly hideCursor: boolean; + public readonly cursorColor: string; + + public readonly themeType: 'light' | 'dark' | 'hc'; + public readonly backgroundColor: string; + + public readonly top: number; + public readonly right: number; + public readonly domWidth: number; + public readonly domHeight: number; + public readonly canvasWidth: number; + public readonly canvasHeight: number; + + public readonly x: number[]; + public readonly w: number[]; + + constructor(config: editorCommon.IConfiguration, theme: ITheme) { + this.lineHeight = config.editor.lineHeight; + this.pixelRatio = config.editor.pixelRatio; + this.overviewRulerLanes = config.editor.viewInfo.overviewRulerLanes; + + this.renderBorder = config.editor.viewInfo.overviewRulerBorder; + const borderColor = theme.getColor(editorOverviewRulerBorder); + this.borderColor = borderColor ? borderColor.toString() : null; + + this.hideCursor = config.editor.viewInfo.hideCursorInOverviewRuler; + const cursorColor = theme.getColor(editorCursorForeground); + this.cursorColor = cursorColor ? cursorColor.transparent(0.7).toString() : null; + + this.themeType = theme.type; + + const minimapEnabled = config.editor.viewInfo.minimap.enabled; + const backgroundColor = (minimapEnabled ? TokenizationRegistry.getDefaultBackground() : null); + this.backgroundColor = (backgroundColor ? Color.Format.CSS.formatHex(backgroundColor) : null); + + const position = config.editor.layoutInfo.overviewRuler; + this.top = position.top; + this.right = position.right; + this.domWidth = position.width; + this.domHeight = position.height; + this.canvasWidth = (this.domWidth * this.pixelRatio) | 0; + this.canvasHeight = (this.domHeight * this.pixelRatio) | 0; + + const [x, w] = this._initLanes(1, this.canvasWidth, this.overviewRulerLanes); + this.x = x; + this.w = w; + } + + private _initLanes(canvasLeftOffset: number, canvasWidth: number, laneCount: number): [number[], number[]] { + const remainingWidth = canvasWidth - canvasLeftOffset; + + if (laneCount >= 3) { + const leftWidth = Math.floor(remainingWidth / 3); + const rightWidth = Math.floor(remainingWidth / 3); + const centerWidth = remainingWidth - leftWidth - rightWidth; + const leftOffset = canvasLeftOffset; + const centerOffset = leftOffset + leftWidth; + const rightOffset = leftOffset + leftWidth + centerWidth; + + return [ + [ + 0, + leftOffset, // Left + centerOffset, // Center + leftOffset, // Left | Center + rightOffset, // Right + leftOffset, // Left | Right + centerOffset, // Center | Right + leftOffset, // Left | Center | Right + ], [ + 0, + leftWidth, // Left + centerWidth, // Center + leftWidth + centerWidth, // Left | Center + rightWidth, // Right + leftWidth + centerWidth + rightWidth, // Left | Right + centerWidth + rightWidth, // Center | Right + leftWidth + centerWidth + rightWidth, // Left | Center | Right + ] + ]; + } else if (laneCount === 2) { + const leftWidth = Math.floor(remainingWidth / 2); + const rightWidth = remainingWidth - leftWidth; + const leftOffset = canvasLeftOffset; + const rightOffset = leftOffset + leftWidth; + + return [ + [ + 0, + leftOffset, // Left + leftOffset, // Center + leftOffset, // Left | Center + rightOffset, // Right + leftOffset, // Left | Right + leftOffset, // Center | Right + leftOffset, // Left | Center | Right + ], [ + 0, + leftWidth, // Left + leftWidth, // Center + leftWidth, // Left | Center + rightWidth, // Right + leftWidth + rightWidth, // Left | Right + leftWidth + rightWidth, // Center | Right + leftWidth + rightWidth, // Left | Center | Right + ] + ]; + } else { + const offset = canvasLeftOffset; + const width = remainingWidth; + + return [ + [ + 0, + offset, // Left + offset, // Center + offset, // Left | Center + offset, // Right + offset, // Left | Right + offset, // Center | Right + offset, // Left | Center | Right + ], [ + 0, + width, // Left + width, // Center + width, // Left | Center + width, // Right + width, // Left | Right + width, // Center | Right + width, // Left | Center | Right + ] + ]; + } + } + + public equals(other: Settings): boolean { + return ( + this.lineHeight === other.lineHeight + && this.pixelRatio === other.pixelRatio + && this.overviewRulerLanes === other.overviewRulerLanes + && this.renderBorder === other.renderBorder + && this.borderColor === other.borderColor + && this.hideCursor === other.hideCursor + && this.cursorColor === other.cursorColor + && this.themeType === other.themeType + && this.backgroundColor === other.backgroundColor + && this.top === other.top + && this.right === other.right + && this.domWidth === other.domWidth + && this.domHeight === other.domHeight + && this.canvasWidth === other.canvasWidth + && this.canvasHeight === other.canvasHeight + ); + } +} + +const enum Constants { + MIN_DECORATION_HEIGHT = 6 +} + +const enum OverviewRulerLane { + Left = 1, + Center = 2, + Right = 4, + Full = 7 +} + +export class DecorationsOverviewRuler2 extends ViewPart { + + private readonly _tokensColorTrackerListener: IDisposable; + private readonly _domNode: FastDomNode; + private _settings: Settings; + private _cursorPositions: Position[]; + + constructor(context: ViewContext) { + super(context); + + this._domNode = createFastDomNode(document.createElement('canvas')); + this._domNode.setClassName('decorationsOverviewRuler'); + this._domNode.setPosition('absolute'); + this._domNode.setLayerHinting(true); + + this._settings = null; + this._updateSettings(false); + + this._tokensColorTrackerListener = TokenizationRegistry.onDidChange((e) => { + if (e.changedColorMap) { + this._updateSettings(true); + } + }); + + this._cursorPositions = []; + } + + public dispose(): void { + super.dispose(); + this._tokensColorTrackerListener.dispose(); + } + + private _updateSettings(renderNow: boolean): boolean { + const newSettings = new Settings(this._context.configuration, this._context.theme); + if (this._settings !== null && this._settings.equals(newSettings)) { + // nothing to do + return false; + } + + this._settings = newSettings; + + this._domNode.setTop(this._settings.top); + this._domNode.setRight(this._settings.right); + this._domNode.setWidth(this._settings.domWidth); + this._domNode.setHeight(this._settings.domHeight); + this._domNode.domNode.width = this._settings.canvasWidth; + this._domNode.domNode.height = this._settings.canvasHeight; + + if (renderNow) { + this._render(); + } + + return true; + } + + // ---- begin view event handlers + + public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { + return this._updateSettings(false); + } + public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { + this._cursorPositions = []; + for (let i = 0, len = e.selections.length; i < len; i++) { + this._cursorPositions[i] = e.selections[i].getPosition(); + } + return true; + } + public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { + return true; + } + public onFlushed(e: viewEvents.ViewFlushedEvent): boolean { + return true; + } + public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean { + return e.scrollHeightChanged; + } + public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean { + return true; + } + public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean { + // invalidate color cache + const decorations = this._context.model.getAllOverviewRulerDecorations(); + for (let i = 0, len = decorations.length; i < len; i++) { + const decoration = decorations[i]; + const opts = decoration.source.options.overviewRuler; + opts._resolvedColor = null; + } + return this._updateSettings(false); + } + + // ---- end view event handlers + + public getDomNode(): HTMLElement { + return this._domNode.domNode; + } + + public prepareRender(ctx: RenderingContext): void { + // Nothing to read + } + + public render(editorCtx: RestrictedRenderingContext): void { + this._render(); + } + + private _render(): void { + const canvasWidth = this._settings.canvasWidth; + const canvasHeight = this._settings.canvasHeight; + const lineHeight = this._settings.lineHeight; + const viewLayout = this._context.viewLayout; + const theme = this._context.theme; + const outerHeight = this._context.viewLayout.getScrollHeight(); + const heightRatio = canvasHeight / outerHeight; + const decorations = this._context.model.getAllOverviewRulerDecorations(); + + const minDecorationHeight = (Constants.MIN_DECORATION_HEIGHT * this._settings.pixelRatio) | 0; + const halfMinDecorationHeight = (minDecorationHeight / 2) | 0; + + const canvasCtx = this._domNode.domNode.getContext('2d'); + if (this._settings.backgroundColor === null) { + canvasCtx.clearRect(0, 0, canvasWidth, canvasHeight); + } else { + canvasCtx.fillStyle = this._settings.backgroundColor; + canvasCtx.fillRect(0, 0, canvasWidth, canvasHeight); + } + + const paintQueue = new PaintQueue(canvasCtx, this._settings.x, this._settings.w); + for (let i = 0, len = decorations.length; i < len; i++) { + const decoration = decorations[i]; + const opts = decoration.source.options.overviewRuler; + const lane = opts.position; + if (lane === 0) { + continue; + } + const startLineNumber = decoration.range.startLineNumber; + const endLineNumber = decoration.range.endLineNumber; + const color = resolveColor(opts, theme); + + let y1 = (viewLayout.getVerticalOffsetForLineNumber(startLineNumber) * heightRatio) | 0; + let y2 = ((viewLayout.getVerticalOffsetForLineNumber(endLineNumber) + lineHeight) * heightRatio) | 0; + let height = y2 - y1; + if (height < minDecorationHeight) { + let yCenter = ((y1 + y2) / 2) | 0; + if (yCenter < halfMinDecorationHeight) { + yCenter = halfMinDecorationHeight; + } else if (yCenter + halfMinDecorationHeight > canvasHeight) { + yCenter = canvasHeight - halfMinDecorationHeight; + } + y1 = yCenter - halfMinDecorationHeight; + y2 = yCenter + halfMinDecorationHeight; + } + + paintQueueAccept(paintQueue, color, y1, y2, lane); + } + for (let i = 0, len = paintQueue.req.length; i < len; i++) { + paintQueueFlush(paintQueue, paintQueue.req[i]); + } + + // Draw cursors + if (!this._settings.hideCursor) { + const cursorHeight = (2 * this._settings.pixelRatio) | 0; + const halfCursorHeight = (cursorHeight / 2) | 0; + const x = this._settings.x[OverviewRulerLane.Full]; + const w = this._settings.w[OverviewRulerLane.Full]; + canvasCtx.fillStyle = this._settings.cursorColor; + for (let i = 0, len = this._cursorPositions.length; i < len; i++) { + const cursor = this._cursorPositions[i]; + + let yCenter = (viewLayout.getVerticalOffsetForLineNumber(cursor.lineNumber) * heightRatio) | 0; + if (yCenter < halfCursorHeight) { + yCenter = halfCursorHeight; + } else if (yCenter + halfCursorHeight > canvasHeight) { + yCenter = canvasHeight - halfCursorHeight; + } + const y1 = yCenter - halfCursorHeight; + + canvasCtx.fillRect(x, y1, w, cursorHeight); + } + } + + if (this._settings.renderBorder && this._settings.borderColor && this._settings.overviewRulerLanes > 0) { + canvasCtx.beginPath(); + canvasCtx.lineWidth = 1; + canvasCtx.strokeStyle = this._settings.borderColor; + canvasCtx.moveTo(0, 0); + canvasCtx.lineTo(0, canvasHeight); + canvasCtx.stroke(); + + canvasCtx.moveTo(0, 0); + canvasCtx.lineTo(canvasWidth, 0); + canvasCtx.stroke(); + } + } +} + +class PaintRequest { + public color: string; + public y1: number; + public y2: number; + public lane: number; + + public init(color: string, y1: number, y2: number, lane: number): void { + this.color = color; + this.y1 = y1; + this.y2 = y2; + this.lane = lane; + } +} + +class PaintQueue { + readonly ctx: CanvasRenderingContext2D; + + readonly x: number[]; + readonly w: number[]; + + readonly req: PaintRequest[] = []; + readonly pool: PaintRequest[] = []; + + constructor(ctx: CanvasRenderingContext2D, x: number[], w: number[]) { + this.ctx = ctx; + this.x = x; + this.w = w; + } +} + +function paintQueueAccept(Q: PaintQueue, color: string, y1: number, y2: number, lane: number): void { + let result: PaintRequest = null; + for (let i = 0, len = Q.req.length; i < len; i++) { + const req = Q.req[i]; + if (req.y2 < y1) { + paintQueueFlush(Q, req); + + if (i + 1 === len) { + // last element + Q.req.pop(); + Q.pool.push(req); + break; + } else { + Q.req[i] = Q.req.pop(); + len--; + Q.pool.push(req); + i--; + continue; + } + } + + if (req.lane === lane && req.color === color) { + result = req; + break; + } + } + + if (result !== null) { + // there is already an ongoing request for this color & lane + // => simply merge into it + result.y2 = y2; + return; + } + + if (Q.pool.length > 0) { + result = Q.pool.pop(); + } else { + result = new PaintRequest(); + } + + result.init(color, y1, y2, lane); + Q.req.push(result); +} + +function paintQueueFlush(Q: PaintQueue, req: PaintRequest): void { + Q.ctx.fillStyle = req.color; + Q.ctx.fillRect(Q.x[req.lane], req.y1, Q.w[req.lane], req.y2 - req.y1); +} + +function resolveColor(opts: ModelDecorationOverviewRulerOptions, theme: ITheme): string { + if (!opts._resolvedColor) { + const themeType = theme.type; + const color = (themeType === 'dark' ? opts.darkColor : themeType === 'light' ? opts.color : opts.hcColor); + opts._resolvedColor = resolveRulerColor(color, theme); + } + return opts._resolvedColor; +} + +function resolveRulerColor(color: string | ThemeColor, theme: ITheme): string { + if (typeof color === 'string') { + return color; + } + let c = color ? theme.getColor(color.id) : null; + if (!c) { + c = Color.transparent; + } + return c.toString(); +} From 22e5969e1b5b6ab9f407ba98cbc86070b1708775 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 15:44:26 +0200 Subject: [PATCH 258/394] CompositeBar: better overflow math --- .../workbench/browser/parts/compositebar/compositeBar.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 07c8d3b6efc..43afc0d47bf 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -36,6 +36,7 @@ export interface ICompositeBarOptions { export class CompositeBar implements ICompositeBar { + private static OVERFLOW_ACTION_SIZE = 50; private _onDidContextMenu: Emitter; private dimension: Dimension; @@ -219,8 +220,10 @@ export class CompositeBar implements ICompositeBar { } overflows = compositesToShow.length > maxVisible; - if (overflows) { - compositesToShow = compositesToShow.slice(0, maxVisible - 1 /* make room for overflow action */); + compositesToShow = compositesToShow.slice(0, maxVisible); + // Check if we need to make room for the overflow action + if (overflows && (size + CompositeBar.OVERFLOW_ACTION_SIZE - this.compositeSizeInBar.get(compositesToShow[maxVisible - 1]) - this.compositeSizeInBar.get(compositesToShow[maxVisible]) > limit)) { + compositesToShow.pop(); } } From 9edfc0685b9592813b0b51b4b1a94d51be0e25c2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Oct 2017 16:08:36 +0200 Subject: [PATCH 259/394] More tests to configuration service --- .../common/configurationModels.ts | 3 +- .../common/configurationModels.ts | 29 + .../node/configurationService.ts | 19 +- .../node/configurationEditingService.test.ts | 15 - .../test/node/configurationService.test.ts | 636 ++++++------------ 5 files changed, 253 insertions(+), 449 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 56ec4b29832..f8c58ea3689 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -539,8 +539,9 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i changedConfigurationByResource = changedConfigurationByResource.merge(arg1._changedConfigurationByResource.get(resource)); this._changedConfigurationByResource.set(resource, changedConfigurationByResource); } + } else { + this.changeWithKeys(arg1, arg2); } - this.changeWithKeys(arg1, arg2); return this; } diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 69fd5bd628a..3e72fc9fe57 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -14,6 +14,7 @@ import { IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces import { Workspace } from 'vs/platform/workspace/common/workspace'; import { StrictResourceMap } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; +import { distinct } from 'vs/base/common/arrays'; export class WorkspaceConfigurationModel extends CustomConfigurationModel { @@ -266,6 +267,34 @@ export class Configuration extends BaseConfiguration { getFolderConfigurationModel(folder: URI): FolderConfigurationModel { return this.folders.get(folder); } + + compare(other: Configuration): string[] { + let from = other.allKeys(); + let to = this.allKeys(); + + const added = to.filter(key => from.indexOf(key) === -1); + const removed = from.filter(key => to.indexOf(key) === -1); + const updated = []; + + for (const key of from) { + const value1 = this.getValue(key); + const value2 = other.getValue(key); + if (!equals(value1, value2)) { + updated.push(key); + } + } + + return [...added, ...removed, ...updated]; + } + + allKeys(): string[] { + let keys = this.keys(); + let all = [...keys.default, ...keys.user, ...keys.workspace]; + for (const resource of this.folders.keys()) { + all.push(...this.folders.get(resource).keys); + } + return distinct(all); + } } export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent { diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index e0f5321a8f6..0b307b25972 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -219,15 +219,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService); } - handleWorkspaceFileEvents(event: FileChangesEvent): void { + handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { switch (this.getWorkbenchState()) { case WorkbenchState.FOLDER: - this.onSingleFolderFileChanges(event); - return; + return this.onSingleFolderFileChanges(event); case WorkbenchState.WORKSPACE: - this.onWorkspaceFileChanges(event); - return; + return this.onWorkspaceFileChanges(event); } + return TPromise.as(void 0); } private createWorkspace(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { @@ -325,11 +324,15 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat const folderConfigurationModels = new StrictResourceMap(); folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration)); + const currentConfiguration = this._configuration; this._configuration = new Configuration(this.baseConfigurationService.configuration.defaults, this.baseConfigurationService.configuration.user, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null - // TODO Sandy: compare with old values?? - const keys = this._configuration.keys(); - this._onDidChangeConfiguration.fire(new AllKeysConfigurationChangeEvent([...keys.default, ...keys.user, ...keys.workspace, ...keys.workspaceFolder], ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE))); + if (currentConfiguration) { + const changedKeys = this._configuration.compare(currentConfiguration); + this.triggerConfigurationChange(new ConfigurationChangeEvent().change(changedKeys), ConfigurationTarget.WORKSPACE); + } else { + this._onDidChangeConfiguration.fire(new AllKeysConfigurationChangeEvent(this._configuration.allKeys(), ConfigurationTarget.WORKSPACE, this.getTargetConfiguration(ConfigurationTarget.WORKSPACE))); + } }); } diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index f1847573483..8bfb2c6fbe5 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -195,41 +195,31 @@ suite('ConfigurationEditingService', () => { test('write one setting - empty file', () => { return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }) - .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); const parsed = json.parse(contents); assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); - assert.equal(instantiationService.get(IConfigurationService).getValue('configurationEditing.service.testSetting'), 'value'); }); }); test('write one setting - existing file', () => { fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }'); return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }) - .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const contents = fs.readFileSync(globalSettingsFile).toString('utf8'); const parsed = json.parse(contents); assert.equal(parsed['configurationEditing.service.testSetting'], 'value'); assert.equal(parsed['my.super.setting'], 'my.super.value'); - - const configurationService = instantiationService.get(IConfigurationService); - assert.equal(configurationService.getValue('configurationEditing.service.testSetting'), 'value'); - assert.equal(configurationService.getValue('my.super.setting'), 'my.super.value'); }); }); test('write workspace standalone setting - empty file', () => { return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' }) - .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']); const contents = fs.readFileSync(target).toString('utf8'); const parsed = json.parse(contents); assert.equal(parsed['service.testSetting'], 'value'); - const configurationService = instantiationService.get(IConfigurationService); - assert.equal(configurationService.getValue('tasks.service.testSetting'), 'value'); }); }); @@ -237,16 +227,11 @@ suite('ConfigurationEditingService', () => { const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']); fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }'); return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'launch.service.testSetting', value: 'value' }) - .then(() => instantiationService.get(IConfigurationService).reloadConfiguration()) .then(() => { const contents = fs.readFileSync(target).toString('utf8'); const parsed = json.parse(contents); assert.equal(parsed['service.testSetting'], 'value'); assert.equal(parsed['my.super.setting'], 'my.super.value'); - - const configurationService = instantiationService.get(IConfigurationService); - assert.equal(configurationService.getValue('launch.service.testSetting'), 'value'); - assert.equal(configurationService.getValue('launch.my.super.setting'), 'my.super.value'); }); }); diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index 0887b2eb530..390f2140053 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -21,7 +21,7 @@ import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files'; -import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService } from 'vs/workbench/test/workbenchTestServices'; import { FileService } from 'vs/workbench/services/files/node/fileService'; @@ -39,29 +39,10 @@ class SettingsTestEnvironmentService extends EnvironmentService { get appSettingsPath(): string { return this.customAppSettingsHome; } } -function createWorkspace(callback: (workspaceDir: string, globalSettingsFile: string, cleanUp: (callback: () => void) => void) => void): void { +function setUpFolderWorkspace(folderName: string): TPromise<{ parentDir: string, folderDir: string }> { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const workspaceDir = path.join(parentDir, 'workspaceconfig', id); - const workspaceSettingsDir = path.join(workspaceDir, '.vscode'); - const globalSettingsFile = path.join(workspaceDir, 'config.json'); - - extfs.mkdirp(workspaceSettingsDir, 493, (error) => { - callback(workspaceDir, globalSettingsFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback)); - }); -} - -function setUpFolderWorkspace(folderName: string): TPromise<{ parentDir: string, folderDir: string, workspaceService: WorkspaceService, environmentService: IEnvironmentService }> { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const globalSettingsFile = path.join(parentDir, 'settings.json'); - - return setUpFolder(folderName, parentDir) - .then(folderDir => { - const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); - const workspaceService = new WorkspaceService(environmentService, null); - return workspaceService.initialize(folderDir).then(() => ({ parentDir, folderDir, workspaceService, environmentService })); - }); + return setUpFolder(folderName, parentDir).then(folderDir => ({ parentDir, folderDir })); } function setUpFolder(folderName: string, parentDir: string): TPromise { @@ -78,11 +59,10 @@ function setUpFolder(folderName: string, parentDir: string): TPromise { }); } -function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, workspaceService: WorkspaceService, environmentService: IEnvironmentService }> { +function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, configPath: string }> { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const globalSettingsFile = path.join(parentDir, 'settings.json'); return createDir(parentDir) .then(() => { @@ -91,12 +71,9 @@ function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, worksp fs.writeFileSync(configPath, JSON.stringify(workspace, null, '\t')); return TPromise.join(folders.map(folder => setUpFolder(folder, parentDir))) - .then(() => { - const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); - const workspaceService = new WorkspaceService(environmentService, null); - return workspaceService.initialize({ id, configPath }).then(() => ({ parentDir, workspaceService, environmentService })); - }); + .then(() => ({ parentDir, configPath })); }); + } function createDir(dir: string): TPromise { @@ -111,23 +88,19 @@ function createDir(dir: string): TPromise { }); } -function createService(workspaceDir: string, globalSettingsFile: string): TPromise { - const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); - const service = new WorkspaceService(environmentService, null); - - return service.initialize(workspaceDir).then(() => service); -} - suite('WorkspaceContextService - Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceResource: string, workspaceContextService: IWorkspaceContextService; setup(() => { return setUpFolderWorkspace(workspaceName) - .then(({ parentDir, folderDir, workspaceService }) => { + .then(({ parentDir, folderDir }) => { parentResource = parentDir; workspaceResource = folderDir; - workspaceContextService = workspaceService; + const globalSettingsFile = path.join(parentDir, 'settings.json'); + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); + workspaceContextService = new WorkspaceService(environmentService, null); + return (workspaceContextService).initialize(folderDir); }); }); @@ -171,379 +144,9 @@ suite('WorkspaceContextService - Folder', () => { }); }); -suite('WorkspaceContextService - Folder', () => { -}); +suite('WorkspaceConfigurationService - Folder', () => { -suite('WorkspaceConfigurationService', () => { - - test('defaults', (done: () => void) => { - interface ITestSetting { - workspace: { - service: { - testSetting: string; - } - }; - } - - const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); - configurationRegistry.registerConfiguration({ - 'id': '_test_workspace', - 'type': 'object', - 'properties': { - 'workspace.service.testSetting': { - 'type': 'string', - 'default': 'isSet' - } - } - }); - - configurationRegistry.registerConfiguration({ - 'id': '_test', - 'type': 'object', - 'properties': { - 'workspaceLookup.service.testSetting': { - 'type': 'string', - 'default': 'isSet' - } - } - }); - - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - const config = service.getConfiguration(); - assert.equal(config.workspace.service.testSetting, 'isSet'); - - service.dispose(); - - cleanUp(done); - }); - }); - }); - - test('globals', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); - - service.reloadConfiguration().then(() => { - const config = service.getConfiguration<{ testworkbench: { editor: { tabs: boolean } } }>(); - assert.equal(config.testworkbench.editor.tabs, true); - - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - - test('reload configuration emits events', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); - - return service.initialize(workspaceDir).then(() => { - service.onDidChangeConfiguration(event => { - const config = service.getConfiguration<{ testworkbench: { editor: { tabs: boolean } } }>(); - assert.equal(config.testworkbench.editor.tabs, false); - - service.dispose(); - - cleanUp(done); - }); - - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": false }'); - - // this has to trigger the event since the config changes - service.reloadUserConfiguration().done(); - }); - - }); - }); - }); - - test('globals override defaults', (done: () => void) => { - interface ITestSetting { - workspace: { - service: { - testSetting: string; - } - }; - } - - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - fs.writeFileSync(globalSettingsFile, '{ "workspace.service.testSetting": "isChanged" }'); - - service.reloadUserConfiguration().then(() => { - const config = service.getConfiguration(); - assert.equal(config.workspace.service.testSetting, 'isChanged'); - - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - - test('workspace settings', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); - - service.reloadWorkspaceConfiguration().then(() => { - const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean } } }>(); - assert.equal(config.testworkbench.editor.icons, true); - - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - - test('workspace settings override user settings', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.icons": false, "testworkbench.other.setting": true }'); - fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); - - service.reloadConfiguration().then(() => { - const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean }, other: { setting: string } } }>(); - assert.equal(config.testworkbench.editor.icons, true); - assert.equal(config.testworkbench.other.setting, true); - - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - - test('workspace change triggers event', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - service.onDidChangeConfiguration(event => { - const config = service.getConfiguration<{ testworkbench: { editor: { icons: boolean } } }>(); - assert.equal(config.testworkbench.editor.icons, true); - assert.equal(service.getConfiguration().testworkbench.editor.icons, true); - - service.dispose(); - - cleanUp(done); - }); - - const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); - fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": true }'); - - const event = new FileChangesEvent([{ resource: URI.file(settingsFile), type: FileChangeType.ADDED }]); - service.handleWorkspaceFileEvents(event); - }); - }); - }); - - test('workspace reload should triggers event if content changed', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); - fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": true }'); - - const target = sinon.stub(); - service.onDidChangeConfiguration(event => target()); - - fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": false }'); - - service.reloadWorkspaceConfiguration().done(() => { - assert.ok(target.calledOnce); - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - - test('workspace reload should not trigger event if nothing changed', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); - fs.writeFileSync(settingsFile, '{ "testworkbench.editor.icons": true }'); - - service.reloadWorkspaceConfiguration().done(() => { - const target = sinon.stub(); - service.onDidChangeConfiguration(event => target()); - - service.reloadWorkspaceConfiguration().done(() => { - assert.ok(!target.called); - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - }); - - test('workspace reload should not trigger event if there is no model', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - const target = sinon.stub(); - service.onDidChangeConfiguration(event => target()); - service.reloadUserConfiguration().done(() => { - assert.ok(!target.called); - service.dispose(); - cleanUp(done); - }); - }); - }); - }); - - - test('lookup', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - let res = service.inspect('something.missing'); - assert.ok(!res.default); - assert.ok(!res.user); - assert.ok(!res.workspace); - assert.ok(!res.value); - - res = service.inspect('workspaceLookup.service.testSetting'); - assert.equal(res.default, 'isSet'); - assert.equal(res.value, 'isSet'); - assert.ok(!res.user); - assert.ok(!res.workspace); - - fs.writeFileSync(globalSettingsFile, '{ "workspaceLookup.service.testSetting": true }'); - - return service.reloadUserConfiguration().then(() => { - res = service.inspect('workspaceLookup.service.testSetting'); - assert.equal(res.default, 'isSet'); - assert.equal(res.user, true); - assert.equal(res.value, true); - assert.ok(!res.workspace); - - const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); - fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.testSetting": 55 }'); - - return service.reloadWorkspaceConfiguration().then(() => { - res = service.inspect('workspaceLookup.service.testSetting'); - assert.equal(res.default, 'isSet'); - assert.equal(res.user, true); - assert.equal(res.workspace, 55); - assert.equal(res.value, 55); - - service.dispose(); - - cleanUp(done); - }); - - }); - - }); - }); - }); - - test('keys', (done: () => void) => { - - function contains(array: string[], key: string): boolean { - return array.indexOf(key) >= 0; - } - - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - let keys = service.keys(); - - assert.ok(!contains(keys.default, 'something.missing')); - assert.ok(!contains(keys.user, 'something.missing')); - assert.ok(!contains(keys.workspace, 'something.missing')); - - assert.ok(contains(keys.default, 'workspaceLookup.service.testSetting')); - assert.ok(!contains(keys.user, 'workspaceLookup.service.testSetting')); - assert.ok(!contains(keys.workspace, 'workspaceLookup.service.testSetting')); - - fs.writeFileSync(globalSettingsFile, '{ "workspaceLookup.service.testSetting": true }'); - - return service.reloadUserConfiguration().then(() => { - keys = service.keys(); - - assert.ok(contains(keys.default, 'workspaceLookup.service.testSetting')); - assert.ok(contains(keys.user, 'workspaceLookup.service.testSetting')); - assert.ok(!contains(keys.workspace, 'workspaceLookup.service.testSetting')); - - const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); - fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.testSetting": 55 }'); - - return service.reloadWorkspaceConfiguration().then(() => { - keys = service.keys(); - - assert.ok(contains(keys.default, 'workspaceLookup.service.testSetting')); - assert.ok(contains(keys.user, 'workspaceLookup.service.testSetting')); - assert.ok(contains(keys.workspace, 'workspaceLookup.service.testSetting')); - - const settingsFile = path.join(workspaceDir, '.vscode', 'tasks.json'); - fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.taskTestSetting": 55 }'); - - return service.reloadWorkspaceConfiguration().then(() => { - keys = service.keys(); - - assert.ok(!contains(keys.default, 'tasks.workspaceLookup.service.taskTestSetting')); - assert.ok(!contains(keys.user, 'tasks.workspaceLookup.service.taskTestSetting')); - assert.ok(contains(keys.workspace, 'tasks.workspaceLookup.service.taskTestSetting')); - - service.dispose(); - - cleanUp(done); - }); - }); - }); - }); - }); - }); - - test('values', (done: () => void) => { - createWorkspace((workspaceDir, globalSettingsFile, cleanUp) => { - return createService(workspaceDir, globalSettingsFile).then(service => { - let values = service.inspect('workspaceLookup.service.testSetting'); - let value = values.value; - - assert.ok(value); - assert.equal(values.default, 'isSet'); - - fs.writeFileSync(globalSettingsFile, '{ "workspaceLookup.service.testSetting": true }'); - - return service.reloadUserConfiguration().then(() => { - values = service.inspect('workspaceLookup.service.testSetting'); - value = values.value; - - assert.ok(value); - assert.equal(values.user, true); - - const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); - fs.writeFileSync(settingsFile, '{ "workspaceLookup.service.testSetting": 55 }'); - - return service.reloadWorkspaceConfiguration().then(() => { - values = service.inspect('workspaceLookup.service.testSetting'); - value = values.value; - - assert.ok(value); - assert.equal(values.user, true); - assert.equal(values.workspace, 55); - - done(); - }); - }); - }); - }); - }); -}); - -suite('WorkspaceConfigurationService - Update', () => { - - let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, testObject: IConfigurationService; + let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string; suiteSetup(() => { const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -561,20 +164,26 @@ suite('WorkspaceConfigurationService - Update', () => { setup(() => { return setUpFolderWorkspace(workspaceName) - .then(({ parentDir, folderDir, workspaceService, environmentService }) => { + .then(({ parentDir, folderDir }) => { parentResource = parentDir; - testObject = workspaceService; - folderDir = folderDir; + workspaceDir = folderDir; + globalSettingsFile = path.join(parentDir, 'settings.json'); const instantiationService = workbenchInstantiationService(); + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); + const workspaceService = new WorkspaceService(environmentService, null); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(IEnvironmentService, environmentService); - instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - workspaceService.setInstantiationService(instantiationService); + + return workspaceService.initialize(folderDir).then(() => { + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.setInstantiationService(instantiationService); + testObject = workspaceService; + }); }); }); @@ -587,6 +196,142 @@ suite('WorkspaceConfigurationService - Update', () => { } }); + test('defaults', () => { + assert.deepEqual(testObject.getValue('configurationService'), { 'folder': { 'testSetting': 'isSet' } }); + }); + + test('globals override defaults', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'userValue')); + }); + + test('globals', () => { + fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('testworkbench.editor.tabs'), true)); + }); + + test('workspace settings', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('testworkbench.editor.icons'), true)); + }); + + test('workspace settings override user settings', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue')); + }); + + test('workspace change triggers event', () => { + const settingsFile = path.join(workspaceDir, '.vscode', 'settings.json'); + fs.writeFileSync(settingsFile, '{ "configurationService.folder.testSetting": "workspaceValue" }'); + const event = new FileChangesEvent([{ resource: URI.file(settingsFile), type: FileChangeType.ADDED }]); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return (testObject).handleWorkspaceFileEvents(event) + .then(() => { + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue'); + assert.ok(target.called); + }); + }); + + test('reload configuration emits events after global configuraiton changes', () => { + fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.reloadConfiguration().then(() => assert.ok(target.called)); + }); + + test('reload configuration emits events after workspace configuraiton changes', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.reloadConfiguration().then(() => assert.ok(target.called)); + }); + + test('reload configuration should not emit event if no changes', () => { + fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(() => { target(); }); + return testObject.reloadConfiguration() + .then(() => assert.ok(!target.called)); + }); + }); + + test('inspect', () => { + let actual = testObject.inspect('something.missing'); + assert.equal(actual.default, void 0); + assert.equal(actual.user, void 0); + assert.equal(actual.workspace, void 0); + assert.equal(actual.workspaceFolder, void 0); + assert.equal(actual.value, void 0); + + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, void 0); + assert.equal(actual.workspace, void 0); + assert.equal(actual.workspaceFolder, void 0); + assert.equal(actual.value, 'isSet'); + + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, void 0); + assert.equal(actual.workspaceFolder, void 0); + assert.equal(actual.value, 'userValue'); + + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, 'workspaceValue'); + assert.equal(actual.workspaceFolder, void 0); + assert.equal(actual.value, 'workspaceValue'); + }); + }); + }); + + test('keys', () => { + let actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, []); + assert.deepEqual(actual.workspace, []); + assert.deepEqual(actual.workspaceFolder, []); + + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspace, []); + assert.deepEqual(actual.workspaceFolder, []); + + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspace, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspaceFolder, []); + }); + }); + }); + test('update user configuration', () => { return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER) .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'value')); @@ -623,11 +368,41 @@ suite('WorkspaceConfigurationService - Update', () => { .then(() => assert.ok(target.called)); }); + test('initialize with different folder triggers configuration event if there are changes', () => { + return setUpFolderWorkspace(`testWorkspace${uuid.generateUuid()}`) + .then(({ folderDir }) => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + + fs.writeFileSync(path.join(folderDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue2" }'); + return (testObject).initialize(folderDir) + .then(() => { + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue2'); + assert.ok(target.called); + }); + }); + }); + + test('initialize with different folder triggers configuration event if there are no changes', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "workspaceValue2" }'); + return testObject.reloadConfiguration() + .then(() => setUpFolderWorkspace(`testWorkspace${uuid.generateUuid()}`)) + .then(({ folderDir }) => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(() => target()); + fs.writeFileSync(path.join(folderDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue2" }'); + return (testObject).initialize(folderDir) + .then(() => { + assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue2'); + assert.ok(!target.called); + }); + }); + }); }); suite('WorkspaceConfigurationService - Update (Multiroot)', () => { - let parentResource: string, workspace: IWorkspace, testObject: IConfigurationService; + let parentResource: string, workspaceContextService: IWorkspaceContextService, testObject: IConfigurationService; suiteSetup(() => { const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); @@ -650,20 +425,28 @@ suite('WorkspaceConfigurationService - Update (Multiroot)', () => { setup(() => { return setUpWorkspace(['1', '2']) - .then(({ parentDir, workspaceService, environmentService }) => { + .then(({ parentDir, configPath }) => { parentResource = parentDir; - testObject = workspaceService; - workspace = workspaceService.getWorkspace();; + + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, path.join(parentDir, 'settings.json')); + const workspaceService = new WorkspaceService(environmentService, null); const instantiationService = workbenchInstantiationService(); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(IEnvironmentService, environmentService); - instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - workspaceService.setInstantiationService(instantiationService); + + return workspaceService.initialize({ id: configPath, configPath }).then(() => { + + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.setInstantiationService(instantiationService); + + workspaceContextService = workspaceService; + testObject = workspaceService; + }); }); }); @@ -701,11 +484,13 @@ suite('WorkspaceConfigurationService - Update (Multiroot)', () => { }); test('update workspace folder configuration', () => { + const workspace = workspaceContextService.getWorkspace(); return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) .then(() => assert.equal(testObject.getValue('configurationService.workspace.testResourceSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue')); }); test('update workspace folder configuration should trigger change event before promise is resolve', () => { + const workspace = workspaceContextService.getWorkspace(); const target = sinon.spy(); testObject.onDidChangeConfiguration(target); return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) @@ -713,6 +498,7 @@ suite('WorkspaceConfigurationService - Update (Multiroot)', () => { }); test('update tasks configuration', () => { + const workspace = workspaceContextService.getWorkspace(); return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) .then(() => assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); }); From 3a3f0e41968ddd3cef6c1e4a090ca8ef8bc6b049 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Oct 2017 16:13:23 +0200 Subject: [PATCH 260/394] [theming] editor.selectionForeground is not working. Fixes #36490 --- src/vs/editor/browser/viewParts/lines/viewLine.ts | 15 ++++++++------- .../editor/browser/viewParts/lines/viewLines.ts | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 8c5c4ff20e3..37625d0dbaf 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -15,8 +15,9 @@ import { IVisibleLine } from 'vs/editor/browser/view/viewLayer'; import { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil'; import { HorizontalRange } from 'vs/editor/common/view/renderingContext'; import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; -import { ThemeType, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { ITheme } from 'vs/platform/theme/common/themeService'; import { IStringBuilder } from 'vs/editor/common/core/stringBuilder'; +import { editorSelectionForeground } from 'vs/platform/theme/common/colorRegistry'; const canUseFastRenderedViewLine = (function () { if (platform.isNative) { @@ -69,7 +70,7 @@ export class DomReadingContext { } export class ViewLineOptions { - public readonly themeType: ThemeType; + public readonly useSelectionForegroundColor: boolean; public readonly renderWhitespace: 'none' | 'boundary' | 'all'; public readonly renderControlCharacters: boolean; public readonly spaceWidth: number; @@ -78,8 +79,8 @@ export class ViewLineOptions { public readonly stopRenderingLineAfter: number; public readonly fontLigatures: boolean; - constructor(config: IConfiguration, themeType: ThemeType) { - this.themeType = themeType; + constructor(config: IConfiguration, theme: ITheme) { + this.useSelectionForegroundColor = !!theme.getColor(editorSelectionForeground); this.renderWhitespace = config.editor.viewInfo.renderWhitespace; this.renderControlCharacters = config.editor.viewInfo.renderControlCharacters; this.spaceWidth = config.editor.fontInfo.spaceWidth; @@ -94,7 +95,7 @@ export class ViewLineOptions { public equals(other: ViewLineOptions): boolean { return ( - this.themeType === other.themeType + this.useSelectionForegroundColor === other.useSelectionForegroundColor && this.renderWhitespace === other.renderWhitespace && this.renderControlCharacters === other.renderControlCharacters && this.spaceWidth === other.spaceWidth @@ -150,7 +151,7 @@ export class ViewLine implements IVisibleLine { this._options = newOptions; } public onSelectionChanged(): boolean { - if (alwaysRenderInlineSelection || this._options.themeType === HIGH_CONTRAST) { + if (alwaysRenderInlineSelection || this._options.useSelectionForegroundColor) { this._isMaybeInvalid = true; return true; } @@ -169,7 +170,7 @@ export class ViewLine implements IVisibleLine { const options = this._options; const actualInlineDecorations = LineDecoration.filter(lineData.inlineDecorations, lineNumber, lineData.minColumn, lineData.maxColumn); - if (alwaysRenderInlineSelection || options.themeType === HIGH_CONTRAST) { + if (alwaysRenderInlineSelection || options.useSelectionForegroundColor) { const selections = viewportData.selections; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 14341b3c952..9c873fa9496 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -96,7 +96,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, this._isViewportWrapping = conf.editor.wrappingInfo.isViewportWrapping; this._revealHorizontalRightPadding = conf.editor.viewInfo.revealHorizontalRightPadding; this._canUseLayerHinting = conf.editor.canUseLayerHinting; - this._viewLineOptions = new ViewLineOptions(conf, this._context.theme.type); + this._viewLineOptions = new ViewLineOptions(conf, this._context.theme); PartFingerprints.write(this.domNode, PartFingerprint.ViewLines); this.domNode.setClassName('view-lines'); @@ -170,7 +170,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, private _onOptionsMaybeChanged(): boolean { const conf = this._context.configuration; - let newViewLineOptions = new ViewLineOptions(conf, this._context.theme.type); + let newViewLineOptions = new ViewLineOptions(conf, this._context.theme); if (!this._viewLineOptions.equals(newViewLineOptions)) { this._viewLineOptions = newViewLineOptions; From 9dd8e048b785c64c8adbfdcbe75cf63ca2fcadc1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Oct 2017 16:12:36 +0200 Subject: [PATCH 261/394] :lipstick: --- .../node/configurationService.ts | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 0b307b25972..edd6058936e 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -190,25 +190,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.getWorkbenchState() === WorkbenchState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.folders[0].uri).workspaceSettingsConfig.unsupportedKeys : []; } - reloadUserConfiguration(key?: string): TPromise { - return this.baseConfigurationService.reloadConfiguration(); - } - - reloadWorkspaceConfiguration(key?: string): TPromise { - const workbenchState = this.getWorkbenchState(); - if (workbenchState === WorkbenchState.FOLDER) { - return this.onWorkspaceFolderConfigurationChanged(this.workspace.folders[0], key); - } - if (workbenchState === WorkbenchState.WORKSPACE) { - return this.workspaceConfiguration.reload().then(() => this.onWorkspaceConfigurationChanged()); - } - return TPromise.as(null); - } - - reloadWorkspaceFolderConfiguration(folder: IWorkspaceFolder, key?: string): TPromise { - return this.onWorkspaceFolderConfigurationChanged(folder, key); - } - initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { return this.createWorkspace(arg) .then(workspace => this.setWorkspace(workspace)) @@ -312,6 +293,25 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.loadConfiguration(); } + private reloadUserConfiguration(key?: string): TPromise { + return this.baseConfigurationService.reloadConfiguration(); + } + + private reloadWorkspaceConfiguration(key?: string): TPromise { + const workbenchState = this.getWorkbenchState(); + if (workbenchState === WorkbenchState.FOLDER) { + return this.onWorkspaceFolderConfigurationChanged(this.workspace.folders[0], key); + } + if (workbenchState === WorkbenchState.WORKSPACE) { + return this.workspaceConfiguration.reload().then(() => this.onWorkspaceConfigurationChanged()); + } + return TPromise.as(null); + } + + private reloadWorkspaceFolderConfiguration(folder: IWorkspaceFolder, key?: string): TPromise { + return this.onWorkspaceFolderConfigurationChanged(folder, key); + } + private loadConfiguration(): TPromise { // reset caches this.cachedFolderConfigs = new StrictResourceMap(); From 6d6104b3fdbd5151cf78b77b55a9f64c50529559 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 19 Oct 2017 16:17:34 +0200 Subject: [PATCH 262/394] dont run git status after check-ignore fixes #36552 --- extensions/git/src/repository.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 8e8740f7b31..04e7dc49012 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -221,7 +221,8 @@ export enum Operation { Merge = 1 << 16, Ignore = 1 << 17, Tag = 1 << 18, - Stash = 1 << 19 + Stash = 1 << 19, + CheckIgnore = 1 << 20 } // function getOperationName(operation: Operation): string { @@ -250,6 +251,7 @@ function isReadOnly(operation: Operation): boolean { switch (operation) { case Operation.Show: case Operation.GetCommitTemplate: + case Operation.CheckIgnore: return true; default: return false; @@ -645,7 +647,7 @@ export class Repository implements Disposable { } checkIgnore(filePaths: string[]): Promise> { - return this.run(Operation.Ignore, () => { + return this.run(Operation.CheckIgnore, () => { return new Promise>((resolve, reject) => { filePaths = filePaths.filter(filePath => !path.relative(this.root, filePath).startsWith('..')); From 3207ab91ed4e182d44fdfd25c1c0c5d663e535cb Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 16:21:53 +0200 Subject: [PATCH 263/394] CompositeBar: colors --- .../parts/activitybar/activitybarActions.ts | 6 +-- .../parts/activitybar/activitybarPart.ts | 12 ++++-- .../parts/compositebar/compositeBar.ts | 8 ++-- .../parts/compositebar/compositeBarActions.ts | 32 ++++++++------ .../browser/parts/panel/panelPart.ts | 9 +++- src/vs/workbench/common/theme.ts | 42 ++++++++++++------- 6 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index e02a364582f..6b40f9a0937 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -21,8 +21,7 @@ import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colo import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; -import { ActivityAction, ActivityActionItem } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { ActivityAction, ActivityActionItem, ICompositeBarColors } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; export class ViewletActivityAction extends ActivityAction { @@ -96,10 +95,11 @@ export class GlobalActivityActionItem extends ActivityActionItem { constructor( action: GlobalActivityAction, + colors: ICompositeBarColors, @IThemeService themeService: IThemeService, @IContextMenuService protected contextMenuService: IContextMenuService ) { - super(action, { draggable: false, backgroundColor: ACTIVITY_BAR_FOREGROUND }, themeService); + super(action, { draggable: false, colors }, themeService); } public render(container: HTMLElement): void { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 13674e9edd6..efa7e390e64 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -27,7 +27,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme'; +import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; @@ -35,6 +35,12 @@ import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/composit export class ActivitybarPart extends Part { private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets'; + private static COLORS = { + backgroundColor: ACTIVITY_BAR_FOREGROUND, + badgeBackground: ACTIVITY_BAR_BADGE_BACKGROUND, + badgeForeground: ACTIVITY_BAR_BADGE_FOREGROUND, + dragAndDropBackground: ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND + }; public _serviceBrand: any; @@ -69,7 +75,7 @@ export class ActivitybarPart extends Part { getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), hidePart: () => this.partService.setSideBarHidden(true), - backgroundColor: ACTIVITY_BAR_FOREGROUND + colors: ActivitybarPart.COLORS }); this.registerListeners(); } @@ -161,7 +167,7 @@ export class ActivitybarPart extends Part { .map(a => new GlobalActivityAction(a)); this.globalActionBar = new ActionBar(container, { - actionItemProvider: a => this.instantiationService.createInstance(GlobalActivityActionItem, a), + actionItemProvider: a => this.instantiationService.createInstance(GlobalActivityActionItem, a, ActivitybarPart.COLORS), orientation: ActionsOrientation.VERTICAL, ariaLabel: nls.localize('globalActions', "Global Actions"), animated: false diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 43afc0d47bf..6f0ca9a6f33 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -17,7 +17,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import Event, { Emitter } from 'vs/base/common/event'; -import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; import { TPromise } from 'vs/base/common/winjs.base'; export interface ICompositeBarOptions { @@ -25,7 +25,7 @@ export interface ICompositeBarOptions { storageId: string; orientation: ActionsOrientation; composites: { id: string, name: string }[]; - backgroundColor: string; + colors: ICompositeBarColors; getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; getOnCompositeClickAction: (compositeId: string) => Action; @@ -283,7 +283,7 @@ export class CompositeBar implements ICompositeBar { () => this.activeCompositeId, (compositeId: string) => this.compositeIdToActivityStack[compositeId] && this.compositeIdToActivityStack[compositeId][0].badge, this.options.getOnCompositeClickAction, - this.options.backgroundColor + this.options.colors ); this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true }); @@ -327,7 +327,7 @@ export class CompositeBar implements ICompositeBar { const compositeActivityAction = this.options.getActivityAction(compositeId); const pinnedAction = this.options.getCompositePinnedAction(compositeId); - this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this, this.options.backgroundColor); + this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this.options.colors, this); this.compositeIdToActions[compositeId] = compositeActivityAction; return compositeActivityAction; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index d01442ab9e4..415f8c9daa1 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -18,7 +18,6 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_BADGE_BACKGROUND } from 'vs/workbench/common/theme'; import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -31,17 +30,17 @@ export interface ICompositeActivity { export interface ICompositeBar { /** - * Unpins a composite from the activitybar. + * Unpins a composite from the composite bar. */ unpin(compositeId: string): void; /** - * Pin a composite inside the activity bar. + * Pin a composite inside the composite bar. */ pin(compositeId: string): void; /** - * Find out if a composite is pinned in the activity bar. + * Find out if a composite is pinned in the composite bar. */ isPinned(compositeId: string): boolean; @@ -91,9 +90,16 @@ export class ActivityAction extends Action { } } +export interface ICompositeBarColors { + backgroundColor: string; + badgeBackground: string; + badgeForeground: string; + dragAndDropBackground: string; +} + export interface IActivityActionItemOptions extends IBaseActionItemOptions { icon?: boolean; - backgroundColor: string; + colors: ICompositeBarColors; } export class ActivityActionItem extends BaseActionItem { @@ -125,15 +131,15 @@ export class ActivityActionItem extends BaseActionItem { // Label if (this.$label) { - const background = theme.getColor(this.options.backgroundColor); + const background = theme.getColor(this.options.colors.backgroundColor); this.$label.style('background-color', background ? background.toString() : null); } // Badge if (this.$badgeContent) { - const badgeForeground = theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND); - const badgeBackground = theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND); + const badgeForeground = theme.getColor(this.options.colors.badgeForeground); + const badgeBackground = theme.getColor(this.options.colors.badgeBackground); const contrastBorderColor = theme.getColor(contrastBorder); this.$badgeContent.style('color', badgeForeground ? badgeForeground.toString() : null); @@ -295,12 +301,12 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem { private getActiveCompositeId: () => string, private getBadge: (compositeId: string) => IBadge, private getCompositeOpenAction: (compositeId: string) => Action, - backgroundColor: string, + colors: ICompositeBarColors, @IInstantiationService private instantiationService: IInstantiationService, @IContextMenuService private contextMenuService: IContextMenuService, @IThemeService themeService: IThemeService ) { - super(action, { icon: true, backgroundColor }, themeService); + super(action, { icon: true, colors }, themeService); this.cssClass = action.class; this.name = action.label; @@ -374,14 +380,14 @@ export class CompositeActionItem extends ActivityActionItem { constructor( private compositeActivityAction: ActivityAction, private toggleCompositePinnedAction: Action, + colors: ICompositeBarColors, private compositeBar: ICompositeBar, - backgroundColor: string, @IContextMenuService private contextMenuService: IContextMenuService, @IKeybindingService private keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService ) { - super(compositeActivityAction, { draggable: true, backgroundColor }, themeService); + super(compositeActivityAction, { draggable: true, colors }, themeService); this.cssClass = compositeActivityAction.class; @@ -497,7 +503,7 @@ export class CompositeActionItem extends ActivityActionItem { private updateFromDragging(element: HTMLElement, isDragging: boolean): void { const theme = this.themeService.getTheme(); - const dragBackground = theme.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND); + const dragBackground = theme.getColor(this.options.colors.dragAndDropBackground); element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : null; } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 29984f1f377..7f8862e0dd8 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -24,7 +24,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ClosePanelAction, ToggleMaximizedPanelAction, PanelActivityAction, OpenPanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; -import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER } from 'vs/workbench/common/theme'; +import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_BADGE_BACKGROUND, PANEL_BADGE_FOREGROUND, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; import { activeContrastBorder, focusBorder, contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; @@ -84,7 +84,12 @@ export class PanelPart extends CompositePart implements IPanelService { getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(OpenPanelAction, this.getPanel(compositeId)), getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), hidePart: () => this.partService.setPanelHidden(true), - backgroundColor: PANEL_BACKGROUND + colors: { + backgroundColor: PANEL_BACKGROUND, + badgeBackground: PANEL_BADGE_BACKGROUND, + badgeForeground: PANEL_BADGE_FOREGROUND, + dragAndDropBackground: PANEL_DRAG_AND_DROP_BACKGROUND + } }); this.toUnbind.push(this.compositeBar); diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 5097ff16f1c..449f39e74fd 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -108,6 +108,24 @@ export const EDITOR_DRAG_AND_DROP_BACKGROUND = registerColor('editorGroup.dropBa // < --- Panels --- > +const DRAG_AND_DROP_BACKGROUND = { + dark: Color.white.transparent(0.12), + light: Color.white.transparent(0.12), + hc: Color.white.transparent(0.12), +}; + +const BADGE_BACKGROUND = { + dark: '#007ACC', + light: '#007ACC', + hc: '#000000' +}; + +const BADGE_FOREGROUND = { + dark: Color.white, + light: Color.white, + hc: Color.white +}; + export const PANEL_BACKGROUND = registerColor('panel.background', { dark: editorBackground, light: editorBackground, @@ -138,6 +156,12 @@ export const PANEL_ACTIVE_TITLE_BORDER = registerColor('panelTitle.activeBorder' hc: contrastBorder }, nls.localize('panelActiveTitleBorder', "Border color for the active panel title. Panels are shown below the editor area and contain views like output and integrated terminal.")); +export const PANEL_DRAG_AND_DROP_BACKGROUND = registerColor('panel.dropBackground', DRAG_AND_DROP_BACKGROUND, nls.localize('panelDragAndDropBackground', "Drag and drop feedback color for the panel title items. The color should have transparency so that the panel entries can still shine through. Panels are shown below the editor area and contain views like output and integrated terminal.")); + +export const PANEL_BADGE_BACKGROUND = registerColor('panelBadge.background', BADGE_BACKGROUND, nls.localize('panelBadgeBackground', "Activity notification badge background color. Panels are shown below the editor area and contain views like output and integrated terminal.")); + +export const PANEL_BADGE_FOREGROUND = registerColor('panelBadge.foreground', BADGE_FOREGROUND, nls.localize('panelBadgeForeground', "Activity notification badge foreground color. Panels are shown below the editor area and contain views like output and integrated terminal.")); + // < --- Status --- > @@ -224,24 +248,12 @@ export const ACTIVITY_BAR_BORDER = registerColor('activityBar.border', { hc: contrastBorder }, nls.localize('activityBarBorder', "Activity bar border color separating to the side bar. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); -export const ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND = registerColor('activityBar.dropBackground', { - dark: Color.white.transparent(0.12), - light: Color.white.transparent(0.12), - hc: Color.white.transparent(0.12), -}, nls.localize('activityBarDragAndDropBackground', "Drag and drop feedback color for the activity bar items. The color should have transparency so that the activity bar entries can still shine through. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); -export const ACTIVITY_BAR_BADGE_BACKGROUND = registerColor('activityBarBadge.background', { - dark: '#007ACC', - light: '#007ACC', - hc: '#000000' -}, nls.localize('activityBarBadgeBackground', "Activity notification badge background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +export const ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND = registerColor('activityBar.dropBackground', DRAG_AND_DROP_BACKGROUND, nls.localize('activityBarDragAndDropBackground', "Drag and drop feedback color for the activity bar items. The color should have transparency so that the activity bar entries can still shine through. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); -export const ACTIVITY_BAR_BADGE_FOREGROUND = registerColor('activityBarBadge.foreground', { - dark: Color.white, - light: Color.white, - hc: Color.white -}, nls.localize('activityBarBadgeForeground', "Activity notification badge foreground color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +export const ACTIVITY_BAR_BADGE_BACKGROUND = registerColor('activityBarBadge.background', BADGE_BACKGROUND, nls.localize('activityBarBadgeBackground', "Activity notification badge background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +export const ACTIVITY_BAR_BADGE_FOREGROUND = registerColor('activityBarBadge.foreground', BADGE_FOREGROUND, nls.localize('activityBarBadgeForeground', "Activity notification badge foreground color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); // < --- Side Bar --- > From 8b54485c809634b4a9cef3762001542dc4d07702 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 16:36:20 +0200 Subject: [PATCH 264/394] fix elipses in activity bar --- src/vs/workbench/browser/parts/panel/media/panelpart.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index c96afe134ab..c048091c711 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -32,7 +32,7 @@ /** Panel Switcher */ -.monaco-workbench .composite-bar > .monaco-action-bar .action-label.toggle-more { +.monaco-workbench > .part.panel .composite-bar > .monaco-action-bar .action-label.toggle-more { background: url('ellipsis.svg') center center no-repeat; display: block; height: 35px; From 96fd5af15878123cddb6401a43fc7af373498b5d Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 16:41:00 +0200 Subject: [PATCH 265/394] more specific terminal panel css selector --- .../terminal/electron-browser/media/xterm.css | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css index 4eb09d1fb3d..d93b34d1050 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css @@ -39,7 +39,7 @@ * Default styles for xterm.js */ -.terminal:not(.action-label) { +.panel.terminal { font-family: courier-new, courier, monospace; font-feature-settings: "liga" 0; position: relative; @@ -48,12 +48,12 @@ -webkit-user-select: none; } -.terminal.focus, -.terminal:focus { +.panel.terminal.focus, +.panel.terminal:focus { outline: none; } -.terminal .xterm-helpers { +.panel.terminal .xterm-helpers { position: absolute; top: 0; /** @@ -63,7 +63,7 @@ z-index: 10; } -.terminal .xterm-helper-textarea { +.panel.terminal .xterm-helper-textarea { /* * HACK: to fix IE's blinking cursor * Move textarea out of the screen to the far left, so that the cursor is not visible. @@ -81,7 +81,7 @@ resize: none; } -.terminal .composition-view { +.panel.terminal .composition-view { /* TODO: Composition position got messed up somewhere */ background: #000; color: #FFF; @@ -91,38 +91,38 @@ z-index: 1; } -.terminal .composition-view.active { +.panel.terminal .composition-view.active { display: block; } -.terminal .xterm-viewport { +.panel.terminal .xterm-viewport { /* On OS X this is required in order for the scroll bar to appear fully opaque */ background-color: #000; overflow-y: scroll; } -.terminal canvas { +.panel.terminal canvas { position: absolute; left: 0; top: 0; } -.terminal .xterm-scroll-area { +.panel.terminal .xterm-scroll-area { visibility: hidden; } -.terminal .xterm-char-measure-element { +.panel.terminal .xterm-char-measure-element { display: inline-block; visibility: hidden; position: absolute; left: -9999em; } -.terminal.enable-mouse-events { +.panel.terminal.enable-mouse-events { /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ cursor: default; } -.terminal:not(.enable-mouse-events) { +.panel.terminal:not(.enable-mouse-events) { cursor: text; } From 4e7f1872f04cf7cb2a9f1725d0a31d5efde43034 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 16:45:52 +0200 Subject: [PATCH 266/394] fix sizes of elements in panel title --- src/vs/workbench/browser/parts/panel/media/panelpart.css | 1 + src/vs/workbench/parts/markers/browser/media/markers.css | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index c048091c711..1a85bcff400 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -67,6 +67,7 @@ .monaco-workbench .panel .monaco-action-bar .action-item .select-box { cursor: pointer; + min-width: 100px; } .monaco-workbench .hide-panel-action { diff --git a/src/vs/workbench/parts/markers/browser/media/markers.css b/src/vs/workbench/parts/markers/browser/media/markers.css index 78b9a6132bd..91252ec8466 100644 --- a/src/vs/workbench/parts/markers/browser/media/markers.css +++ b/src/vs/workbench/parts/markers/browser/media/markers.css @@ -5,7 +5,7 @@ .monaco-action-bar .action-item.markers-panel-action-filter { max-width: 400px; - min-width: 100px; + min-width: 150px; flex: 1; cursor: default; margin: 4px 10px 0 0; From 1f483271e02164bd1b336516fe192fb259fb6b14 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 19 Oct 2017 16:52:04 +0200 Subject: [PATCH 267/394] fix insider hardcoding for smoketest --- build/tfs/darwin/build.sh | 3 +- build/tfs/darwin/smoketest.sh | 33 --------------------- build/tfs/linux/smoketest.sh | 54 ----------------------------------- build/tfs/win32/smoketest.ps1 | 50 -------------------------------- 4 files changed, 2 insertions(+), 138 deletions(-) delete mode 100755 build/tfs/darwin/smoketest.sh delete mode 100644 build/tfs/linux/smoketest.sh delete mode 100644 build/tfs/win32/smoketest.ps1 diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index adbbc89b9b4..b7efbf7b386 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -41,7 +41,8 @@ function smoketest { ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" rm -rf $ARTIFACTS - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --log $ARTIFACTS + [[ "$VSCODE_QUALITY" == "insider" ]] && VSCODE_APPNAME="Visual Studio Code - Insiders" || VSCODE_APPNAME="Visual Studio Code" + npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/$VSCODE_APPNAME.app" --log $ARTIFACTS } step "Run smoke test" \ diff --git a/build/tfs/darwin/smoketest.sh b/build/tfs/darwin/smoketest.sh deleted file mode 100755 index 0d4510edcb3..00000000000 --- a/build/tfs/darwin/smoketest.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -. ./build/tfs/common/node.sh -. ./scripts/env.sh -. ./build/tfs/common/common.sh - -export VSCODE_MIXIN_PASSWORD="$1" -VSO_PAT="$2" - -echo "machine monacotools.visualstudio.com password $VSO_PAT" > ~/.netrc - -step "Install dependencies" \ - npm install - -step "Mix in repository from vscode-distro" \ - npm run gulp -- mixin - -step "Install distro dependencies" \ - node build/tfs/common/installDistro.js - -step "Build minified & upload source maps" \ - npm run gulp -- vscode-darwin-min - -function runSmokeTest { - SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" - LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" - rm -rf $SCREENSHOTS $LOGS - - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app" --screenshots $SCREENSHOTS --logs $LOGS -} - -step "Run smoke test" \ - runSmokeTest \ No newline at end of file diff --git a/build/tfs/linux/smoketest.sh b/build/tfs/linux/smoketest.sh deleted file mode 100644 index c217e0bd2cb..00000000000 --- a/build/tfs/linux/smoketest.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -set -e - -. ./build/tfs/common/node.sh -. ./scripts/env.sh -. ./build/tfs/common/common.sh - -export ARCH="x64" -export VSCODE_MIXIN_PASSWORD="$1" -VSO_PAT="$2" - -echo "machine monacotools.visualstudio.com password $VSO_PAT" > ~/.netrc - -export SCREENSHOTS="$AGENT_BUILDDIRECTORY/smoketest-screenshots" -export LOGS="$AGENT_BUILDDIRECTORY/smoketest-logs" - -function configureEnvironment { - id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) - sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' - - sudo rm -rf $SCREENSHOTS - mkdir -p $SCREENSHOTS - chown -R testuser $SCREENSHOTS - - sudo rm -rf $LOGS - mkdir -p $LOGS - chown -R testuser $LOGS -} - -function runSmokeTest { - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-x64 --screenshots $SCREENSHOTS --logs $LOGS" -} - -step "Install dependencies" \ - npm install --arch=$ARCH --unsafe-perm - -step "Mix in repository from vscode-distro" \ - npm run gulp -- mixin - -step "Get Electron" \ - npm run gulp -- "electron-$ARCH" - -step "Install distro dependencies" \ - node build/tfs/common/installDistro.js --arch=$ARCH - -step "Build minified" \ - npm run gulp -- "vscode-linux-$ARCH-min" - -step "Configure environment" \ - configureEnvironment - -step "Run smoke test" \ - runSmokeTest - diff --git a/build/tfs/win32/smoketest.ps1 b/build/tfs/win32/smoketest.ps1 deleted file mode 100644 index 1fb60a05fd9..00000000000 --- a/build/tfs/win32/smoketest.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -Param( - [string]$arch, - [string]$mixinPassword, - [string]$vsoPAT -) - -. .\build\tfs\win32\node.ps1 -. .\scripts\env.ps1 -. .\build\tfs\win32\lib.ps1 - -# Create a _netrc file to download distro dependencies -# In order to get _netrc to work, we need a HOME variable setup -$env:HOME = $env:USERPROFILE -"machine monacotools.visualstudio.com password ${vsoPAT}" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII - -# Set the right architecture -$env:npm_config_arch = "$arch" - -step "Install dependencies" { - exec { & npm install } -} - -$env:VSCODE_MIXIN_PASSWORD = $mixinPassword -step "Mix in repository from vscode-distro" { - exec { & npm run gulp -- mixin } -} - -step "Get Electron" { - exec { & npm run gulp -- "electron-$global:arch" } -} - -step "Install distro dependencies" { - exec { & node build\tfs\common\installDistro.js } -} - -step "Build minified" { - exec { & npm run gulp -- "vscode-win32-$global:arch-min" } -} - -step "Run smoke test" { - $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" - Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots - - $Logs = "$env:AGENT_BUILDDIRECTORY\smoketest-logs" - Remove-Item -Recurse -Force -ErrorAction Ignore $Logs - - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --screenshots "$Screenshots" --logs "$Logs" } -} - -done \ No newline at end of file From b3201a12a08440a437219720cd96ee71914b7bee Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 19 Oct 2017 17:20:58 +0200 Subject: [PATCH 268/394] CompositeBar: badges --- .../browser/parts/panel/media/panelpart.css | 16 ++++++++-- .../browser/parts/panel/panelPart.ts | 8 ++--- src/vs/workbench/common/theme.ts | 29 +++++++------------ 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index 1a85bcff400..6861914b5c2 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -49,8 +49,8 @@ .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label { text-transform: uppercase; - margin-left: 16px; - margin-right: 16px; + margin-left: 12px; + margin-right: 20px; font-size: 11px; padding-bottom: 4px; /* puts the bottom border down */ } @@ -59,6 +59,18 @@ border-bottom: 1px solid; } +.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge .badge-content { + top: 8px; + right: 0px; + position: absolute; + font-size: 11px; + min-width: 6px; + line-height: 18px; + padding: 0 5px; + border-radius: 20px; + text-align: center; +} + /** Actions */ .monaco-workbench .panel .monaco-action-bar .action-item.select-container { diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 7f8862e0dd8..0cb16e61349 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -24,8 +24,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ClosePanelAction, ToggleMaximizedPanelAction, PanelActivityAction, OpenPanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; -import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_BADGE_BACKGROUND, PANEL_BADGE_FOREGROUND, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; -import { activeContrastBorder, focusBorder, contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry'; +import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; +import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; @@ -86,8 +86,8 @@ export class PanelPart extends CompositePart implements IPanelService { hidePart: () => this.partService.setPanelHidden(true), colors: { backgroundColor: PANEL_BACKGROUND, - badgeBackground: PANEL_BADGE_BACKGROUND, - badgeForeground: PANEL_BADGE_FOREGROUND, + badgeBackground, + badgeForeground, dragAndDropBackground: PANEL_DRAG_AND_DROP_BACKGROUND } }); diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 449f39e74fd..8bfcf69c9fe 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -114,18 +114,6 @@ const DRAG_AND_DROP_BACKGROUND = { hc: Color.white.transparent(0.12), }; -const BADGE_BACKGROUND = { - dark: '#007ACC', - light: '#007ACC', - hc: '#000000' -}; - -const BADGE_FOREGROUND = { - dark: Color.white, - light: Color.white, - hc: Color.white -}; - export const PANEL_BACKGROUND = registerColor('panel.background', { dark: editorBackground, light: editorBackground, @@ -158,11 +146,6 @@ export const PANEL_ACTIVE_TITLE_BORDER = registerColor('panelTitle.activeBorder' export const PANEL_DRAG_AND_DROP_BACKGROUND = registerColor('panel.dropBackground', DRAG_AND_DROP_BACKGROUND, nls.localize('panelDragAndDropBackground', "Drag and drop feedback color for the panel title items. The color should have transparency so that the panel entries can still shine through. Panels are shown below the editor area and contain views like output and integrated terminal.")); -export const PANEL_BADGE_BACKGROUND = registerColor('panelBadge.background', BADGE_BACKGROUND, nls.localize('panelBadgeBackground', "Activity notification badge background color. Panels are shown below the editor area and contain views like output and integrated terminal.")); - -export const PANEL_BADGE_FOREGROUND = registerColor('panelBadge.foreground', BADGE_FOREGROUND, nls.localize('panelBadgeForeground', "Activity notification badge foreground color. Panels are shown below the editor area and contain views like output and integrated terminal.")); - - // < --- Status --- > @@ -251,9 +234,17 @@ export const ACTIVITY_BAR_BORDER = registerColor('activityBar.border', { export const ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND = registerColor('activityBar.dropBackground', DRAG_AND_DROP_BACKGROUND, nls.localize('activityBarDragAndDropBackground', "Drag and drop feedback color for the activity bar items. The color should have transparency so that the activity bar entries can still shine through. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); -export const ACTIVITY_BAR_BADGE_BACKGROUND = registerColor('activityBarBadge.background', BADGE_BACKGROUND, nls.localize('activityBarBadgeBackground', "Activity notification badge background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +export const ACTIVITY_BAR_BADGE_BACKGROUND = registerColor('activityBarBadge.background', { + dark: '#007ACC', + light: '#007ACC', + hc: '#000000' +}, nls.localize('activityBarBadgeBackground', "Activity notification badge background color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); -export const ACTIVITY_BAR_BADGE_FOREGROUND = registerColor('activityBarBadge.foreground', BADGE_FOREGROUND, nls.localize('activityBarBadgeForeground', "Activity notification badge foreground color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +export const ACTIVITY_BAR_BADGE_FOREGROUND = registerColor('activityBarBadge.foreground', { + dark: Color.white, + light: Color.white, + hc: Color.white +}, nls.localize('activityBarBadgeForeground', "Activity notification badge foreground color. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); // < --- Side Bar --- > From 464f1a754f5906a88b20353816639e90aaf1414a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 19 Oct 2017 08:47:59 -0700 Subject: [PATCH 269/394] Pull in xterm.css changes that resolve .terminal naming issue See sourcelair/xterm.js#1068 --- .../terminal/electron-browser/media/xterm.css | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css index d93b34d1050..31206060c2b 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ /** - * xterm.js: xterm, in the browser - * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * Copyright (c) 2014 The xterm.js authors. All rights reserved. * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) * https://github.com/chjj/term.js + * @license MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,7 +39,7 @@ * Default styles for xterm.js */ -.panel.terminal { +.xterm { font-family: courier-new, courier, monospace; font-feature-settings: "liga" 0; position: relative; @@ -48,12 +48,12 @@ -webkit-user-select: none; } -.panel.terminal.focus, -.panel.terminal:focus { +.xterm.focus, +.xterm:focus { outline: none; } -.panel.terminal .xterm-helpers { +.xterm .xterm-helpers { position: absolute; top: 0; /** @@ -63,7 +63,7 @@ z-index: 10; } -.panel.terminal .xterm-helper-textarea { +.xterm .xterm-helper-textarea { /* * HACK: to fix IE's blinking cursor * Move textarea out of the screen to the far left, so that the cursor is not visible. @@ -81,7 +81,7 @@ resize: none; } -.panel.terminal .composition-view { +.xterm .composition-view { /* TODO: Composition position got messed up somewhere */ background: #000; color: #FFF; @@ -91,38 +91,38 @@ z-index: 1; } -.panel.terminal .composition-view.active { +.xterm .composition-view.active { display: block; } -.panel.terminal .xterm-viewport { +.xterm .xterm-viewport { /* On OS X this is required in order for the scroll bar to appear fully opaque */ background-color: #000; overflow-y: scroll; } -.panel.terminal canvas { +.xterm canvas { position: absolute; left: 0; top: 0; } -.panel.terminal .xterm-scroll-area { +.xterm .xterm-scroll-area { visibility: hidden; } -.panel.terminal .xterm-char-measure-element { +.xterm .xterm-char-measure-element { display: inline-block; visibility: hidden; position: absolute; left: -9999em; } -.panel.terminal.enable-mouse-events { +.xterm.enable-mouse-events { /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ cursor: default; } -.panel.terminal:not(.enable-mouse-events) { - cursor: text; +.xterm:not(.enable-mouse-events) { + cursor: text; } From 776419c4bf88785c4dca973269ffc1fb4fdf2e64 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Oct 2017 17:54:56 +0200 Subject: [PATCH 270/394] [folding] fix restoring collapse state (for #36555) --- .../editor/contrib/folding/browser/folding.ts | 36 ++++++----------- .../contrib/folding/common/foldingModel.ts | 40 +++++++++++++++++++ .../folding/common/hiddenRangeModel.ts | 26 ++++++++++-- 3 files changed, 74 insertions(+), 28 deletions(-) diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 959a8086a84..08cc9c3645d 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -17,7 +17,7 @@ import { ICommonCodeEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; -import { FoldingModel, FoldingRegion, setCollapseStateAtLevel, setCollapseStateRecursivly, fold, unfold } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingModel, setCollapseStateAtLevel, setCollapseStateRecursivly, fold, unfold, CollapseState } from 'vs/editor/contrib/folding/common/foldingModel'; import { computeRanges, limitByIndent } from 'vs/editor/contrib/folding/common/indentFoldStrategy'; import { FoldingDecorationProvider } from './foldingDecorations'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -99,27 +99,18 @@ export class FoldingController { /** * Store view state. */ - public saveViewState(): any { + public saveViewState(): { collapsedRegions?: CollapseState, lineCount?: number } { let model = this.editor.getModel(); if (!model) { return {}; } - let collapsedIndexes: number[] = []; - for (let region of this.foldingModel.regions) { - if (region.isCollapsed && region.editorDecorationId) { - var range = model.getDecorationRange(region.editorDecorationId); - if (range) { - collapsedIndexes.push(range.startLineNumber); - } - } - } - return { collapsedIndexes, lineCount: model.getLineCount() }; + return { collapsedRegions: this.foldingModel.getCollapseState(), lineCount: model.getLineCount() }; } /** * Restore view state. */ - public restoreViewState(state: any): void { + public restoreViewState(state: { collapsedRegions?: CollapseState, lineCount?: number }): void { let model = this.editor.getModel(); if (!model) { return; @@ -127,19 +118,16 @@ export class FoldingController { if (!this._isEnabled) { return; } - if (!state || !Array.isArray(state.collapsedIndexes) || state.collapsedIndexes.length === 0 || state.lineCount !== model.getLineCount()) { + if (!state || !state.collapsedRegions || state.lineCount !== model.getLineCount()) { return; } - this.getFoldingModel().then(foldingModel => { - let toToogle: FoldingRegion[] = []; - for (let index of state.collapsedIndexes) { - let region = foldingModel.getRegionAtLine(index); - if (region && !region.isCollapsed) { - toToogle.push(region); - } - } - foldingModel.toggleCollapseState(toToogle); - }); + + // set the hidden ranges right way, before waiting for the folding model. + if (this.hiddenRangeModel.applyCollapseState(state.collapsedRegions)) { + this.getFoldingModel().then(foldingModel => { + foldingModel.applyCollapseState(state.collapsedRegions); + }); + } } private onModelChanged(): void { diff --git a/src/vs/editor/contrib/folding/common/foldingModel.ts b/src/vs/editor/contrib/folding/common/foldingModel.ts index aacf0acf458..cf942cff7a3 100644 --- a/src/vs/editor/contrib/folding/common/foldingModel.ts +++ b/src/vs/editor/contrib/folding/common/foldingModel.ts @@ -32,6 +32,8 @@ export interface FoldingModelChangeEvent { collapseStateChanged?: FoldingRegion[]; } +export type CollapseState = ILineRange[]; + export class FoldingModel { private _textModel: IModel; private _decorationProvider: IDecorationProvider; @@ -134,6 +136,44 @@ export class FoldingModel { this._updateEventEmitter.fire({ model: this }); } + /** + * Collapse state, for persistence only + */ + public getCollapseState(): CollapseState { + let collapsedRanges: ILineRange[] = []; + for (let region of this._regions) { + if (region.isCollapsed && region.editorDecorationId) { + let range = this._textModel.getDecorationRange(region.editorDecorationId); + if (range) { + let startLineNumber = range.startLineNumber; + let endLineNumber = range.endLineNumber + region.range.endLineNumber + region.range.startLineNumber; + collapsedRanges.push({ startLineNumber, endLineNumber }); + } + } + } + if (collapsedRanges.length > 0) { + return collapsedRanges; + } + return null; + } + + /** + * Apply persisted state, for persistence only + */ + public applyCollapseState(state: CollapseState) { + if (!Array.isArray(state)) { + return; + } + let toToogle: FoldingRegion[] = []; + for (let range of state) { + let region = this.getRegionAtLine(range.startLineNumber); + if (region && !region.isCollapsed) { + toToogle.push(region); + } + } + this.toggleCollapseState(toToogle); + } + public dispose() { let editorDecorationIds = []; for (let region of this._regions) { diff --git a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts index 0f954cf9129..38131fb6ef6 100644 --- a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts +++ b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts @@ -5,12 +5,11 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Range, IRange } from 'vs/editor/common/core/range'; -import { FoldingRegion, FoldingModel, IFoldingRange } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingRegion, FoldingModel, IFoldingRange, CollapseState } from 'vs/editor/contrib/folding/common/foldingModel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Selection } from 'vs/editor/common/core/selection'; import { findFirst } from 'vs/base/common/arrays'; - export class HiddenRangeModel { private _foldingModel: FoldingModel; private _hiddenRanges: IRange[] = []; @@ -53,11 +52,30 @@ export class HiddenRangeModel { } }; if (updateHiddenAreas || i < this._hiddenRanges.length) { - this._hiddenRanges = newHiddenAreas; - this._updateEventEmitter.fire(newHiddenAreas); + this.applyHiddenRanges(newHiddenAreas); } } + public applyCollapseState(state: CollapseState): boolean { + if (!Array.isArray(state) || state.length === 0) { + return false; + } + let hiddenRanges = []; + for (let r of state) { + if (!r.startLineNumber || !r.endLineNumber) { + return false; + } + hiddenRanges.push(new Range(r.startLineNumber, 1, r.endLineNumber, 1)); + } + this.applyHiddenRanges(hiddenRanges); + return true; + } + + private applyHiddenRanges(newHiddenAreas: IRange[]) { + this._hiddenRanges = newHiddenAreas; + this._updateEventEmitter.fire(newHiddenAreas); + } + public hasRanges() { return this._hiddenRanges.length > 0; } From 69952f21a9166a746f3a942b48631e9b0219103b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 19 Oct 2017 18:19:34 +0200 Subject: [PATCH 271/394] Handle integer overflow around delta in the IntervalTree; also, make it highly unlikely that it would ever happen --- src/vs/editor/common/model/intervalTree.ts | 101 +++++++++++++++++- .../test/common/model/intervalTree.test.ts | 89 +++++++++++---- 2 files changed, 166 insertions(+), 24 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index fd975e97e41..8e5e123164a 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -53,7 +53,22 @@ const enum Constants { StickinessMask = 0b00110000, StickinessMaskInverse = 0b11001111, - StickinessOffset = 4 + StickinessOffset = 4, + + /** + * Due to how deletion works (in order to avoid always walking the right subtree of the deleted node), + * the deltas for nodes can grow and shrink dramatically. It has been observed, in practice, that unless + * the deltas are corrected, integer overflow will occur. + * + * The integer overflow occurs when 53 bits are used in the numbers, but we will try to avoid it as + * a node's delta gets below a negative 30 bits number. + * + * MIN SMI (SMall Integer) as defined in v8. + * one bit is lost for boxing/unboxing flag. + * one bit is lost for sign flag. + * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values + */ + MIN_SAFE_DELTA = -(1 << 30), } function getNodeColor(node: IntervalNode): NodeColor { @@ -132,7 +147,8 @@ export class IntervalNode implements IModelDecoration { this.start = start; this.end = end; - this.delta = start; + // FORCE_OVERFLOWING_TEST: this.delta = start; + this.delta = 0; this.maxEnd = end; this.id = id; @@ -195,9 +211,11 @@ setNodeColor(SENTINEL, NodeColor.Black); export class IntervalTree { public root: IntervalNode; + public requestNormalizeDelta: boolean; constructor() { this.root = SENTINEL; + this.requestNormalizeDelta = false; } public intervalSearch(start: number, end: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { @@ -237,10 +255,12 @@ export class IntervalTree { public insert(node: IntervalNode): void { rbTreeInsert(this, node); + this._normalizeDeltaIfNecessary(); } public delete(node: IntervalNode): void { rbTreeDelete(this, node); + this._normalizeDeltaIfNecessary(); } public resolveNode(node: IntervalNode, cachedVersionId: number): void { @@ -269,9 +289,11 @@ export class IntervalTree { const node = nodesOfInterest[i]; rbTreeDelete(this, node); } + this._normalizeDeltaIfNecessary(); // (3) edit all tree nodes except the nodes of interest noOverlapReplace(this, offset, offset + length, textLength); + this._normalizeDeltaIfNecessary(); // (4) edit the nodes of interest and insert them back in the tree for (let i = 0, len = nodesOfInterest.length; i < len; i++) { @@ -282,6 +304,7 @@ export class IntervalTree { node.maxEnd = node.end; rbTreeInsert(this, node); } + this._normalizeDeltaIfNecessary(); } public assertInvariants(): void { @@ -323,8 +346,57 @@ export class IntervalTree { out.push(`${indent} NIL\n`); } } + + private _normalizeDeltaIfNecessary(): void { + if (!this.requestNormalizeDelta) { + return; + } + this.requestNormalizeDelta = false; + normalizeDelta(this); + } } +//#region Delta Normalization +function normalizeDelta(T: IntervalTree): void { + let node = T.root; + let delta = 0; + while (node !== SENTINEL) { + + if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) { + // go left + node = node.left; + continue; + } + + if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) { + // go right + delta += node.delta; + node = node.right; + continue; + } + + // handle current node + node.start = delta + node.start; + node.end = delta + node.end; + node.delta = 0; + recomputeMaxEnd(node); + + setNodeIsVisited(node, true); + + // going up from this node + setNodeIsVisited(node.left, false); + setNodeIsVisited(node.right, false); + if (node === node.parent.right) { + delta -= node.parent.delta; + } + node = node.parent; + } + + if (T.root) { + setNodeIsVisited(T.root, false); + } +} +//#endregion //#region Editing @@ -508,6 +580,7 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt let delta = 0; let nodeMaxEnd = 0; let nodeStart = 0; + const editDelta = (textLength - (end - start)); while (node !== SENTINEL) { if (getNodeIsVisited(node)) { // going up from this node @@ -541,9 +614,12 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt // handle current node nodeStart = delta + node.start; if (nodeStart > end) { - node.start += (textLength - (end - start)); - node.end += (textLength - (end - start)); - node.delta += (textLength - (end - start)); + node.start += editDelta; + node.end += editDelta; + node.delta += editDelta; + if (node.delta < Constants.MIN_SAFE_DELTA) { + T.requestNormalizeDelta = true; + } // cover case a) from above // there is no need to search this node or its right subtree setNodeIsVisited(node, true); @@ -949,6 +1025,9 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { // x's delta is no longer influenced by z's delta x.delta += z.delta; + if (x.delta < Constants.MIN_SAFE_DELTA) { + T.requestNormalizeDelta = true; + } x.start += z.delta; x.end += z.delta; @@ -966,10 +1045,16 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { x.start += y.delta; x.end += y.delta; x.delta += y.delta; + if (x.delta < Constants.MIN_SAFE_DELTA) { + T.requestNormalizeDelta = true; + } y.start += z.delta; y.end += z.delta; y.delta = z.delta; + if (y.delta < Constants.MIN_SAFE_DELTA) { + T.requestNormalizeDelta = true; + } } if (y === T.root) { @@ -1130,6 +1215,9 @@ function leftRotate(T: IntervalTree, x: IntervalNode): void { const y = x.right; // set y. y.delta += x.delta; // y's delta is no longer influenced by x's delta + if (y.delta < Constants.MIN_SAFE_DELTA) { + T.requestNormalizeDelta = true; + } y.start += x.delta; y.end += x.delta; @@ -1157,6 +1245,9 @@ function rightRotate(T: IntervalTree, y: IntervalNode): void { const x = y.left; y.delta -= x.delta; + if (y.delta < Constants.MIN_SAFE_DELTA) { + T.requestNormalizeDelta = true; + } y.start -= x.delta; y.end -= x.delta; diff --git a/src/vs/editor/test/common/model/intervalTree.test.ts b/src/vs/editor/test/common/model/intervalTree.test.ts index f5ab68fcb0c..29a5978432e 100644 --- a/src/vs/editor/test/common/model/intervalTree.test.ts +++ b/src/vs/editor/test/common/model/intervalTree.test.ts @@ -14,6 +14,8 @@ const MIN_INTERVAL_START = 1; const MAX_INTERVAL_END = 100; const MIN_INSERTS = 1; const MAX_INSERTS = 30; +const MIN_CHANGE_CNT = 10; +const MAX_CHANGE_CNT = 20; suite('IntervalTree', () => { @@ -94,6 +96,17 @@ suite('IntervalTree', () => { this._treeNodes[op.id] = null; this._oracleNodes[op.id] = null; + } else if (op.type === 'change') { + + this._tree.delete(this._treeNodes[op.id]); + this._treeNodes[op.id].reset(0, op.begin, op.end, null); + this._tree.insert(this._treeNodes[op.id]); + + this._oracle.delete(this._oracleNodes[op.id]); + this._oracleNodes[op.id].start = op.begin; + this._oracleNodes[op.id].end = op.end; + this._oracle.insert(this._oracleNodes[op.id]); + } else { let actualNodes = this._tree.intervalSearch(op.begin, op.end, 0, false, 0); let actual = actualNodes.map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd)); @@ -139,13 +152,20 @@ suite('IntervalTree', () => { id: number; } + interface IChangeOperation { + type: 'change'; + id: number; + begin: number; + end: number; + } + interface ISearchOperation { type: 'search'; begin: number; end: number; } - type IOperation = IInsertOperation | IDeleteOperation | ISearchOperation; + type IOperation = IInsertOperation | IDeleteOperation | IChangeOperation | ISearchOperation; function testIntervalTree(ops: IOperation[]): void { let state = new TestState(); @@ -176,35 +196,53 @@ suite('IntervalTree', () => { private _state: TestState = new TestState(); private _insertCnt: number; private _deleteCnt: number; + private _changeCnt: number; constructor() { this._insertCnt = getRandomInt(MIN_INSERTS, MAX_INSERTS); + this._changeCnt = getRandomInt(MIN_CHANGE_CNT, MAX_CHANGE_CNT); this._deleteCnt = 0; } + private _doRandomInsert(): void { + let range = getRandomRange(MIN_INTERVAL_START, MAX_INTERVAL_END); + this._run({ + type: 'insert', + begin: range[0], + end: range[1] + }); + } + + private _doRandomDelete(): void { + let idx = getRandomInt(Math.floor(this._deleteCnt / 2), this._deleteCnt - 1); + this._run({ + type: 'delete', + id: this._state.getExistingNodeId(idx) + }); + } + + private _doRandomChange(): void { + let idx = getRandomInt(0, this._deleteCnt - 1); + let range = getRandomRange(MIN_INTERVAL_START, MAX_INTERVAL_END); + this._run({ + type: 'change', + id: this._state.getExistingNodeId(idx), + begin: range[0], + end: range[1] + }); + } + public run() { - while (this._insertCnt > 0 || this._deleteCnt > 0) { - let type: 'insert' | 'delete'; + while (this._insertCnt > 0 || this._deleteCnt > 0 || this._changeCnt > 0) { if (this._insertCnt > 0) { - type = 'insert'; - } else { - type = 'delete'; - } - if (type === 'insert') { - let range = getRandomRange(MIN_INTERVAL_START, MAX_INTERVAL_END); - this._run({ - type: 'insert', - begin: range[0], - end: range[1] - }); + this._doRandomInsert(); this._insertCnt--; this._deleteCnt++; + } else if (this._changeCnt > 0) { + this._doRandomChange(); + this._changeCnt--; } else { - let idx = getRandomInt(0, this._deleteCnt - 1); - this._run({ - type: 'delete', - id: this._state.getExistingNodeId(idx) - }); + this._doRandomDelete(); this._deleteCnt--; } @@ -401,6 +439,19 @@ suite('IntervalTree', () => { { type: 'search', begin: 65, end: 75 } ]); }); + + test('force delta overflow', () => { + // Search the IntervalNode ctor for FORCE_OVERFLOWING_TEST + // to force that this test leads to a delta normalization + testIntervalTree([ + { type: 'insert', begin: 686081138593427, end: 733009856502260 }, + { type: 'insert', begin: 591031326181669, end: 591031326181672 }, + { type: 'insert', begin: 940037682731896, end: 940037682731903 }, + { type: 'insert', begin: 598413641151120, end: 598413641151128 }, + { type: 'insert', begin: 800564156553344, end: 800564156553351 }, + { type: 'insert', begin: 894198957565481, end: 894198957565491 } + ]); + }); }); // TEST_COUNT = 0; From d6645f3ffe1a7206c3f8b29f6864534b360bc0c5 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 19 Oct 2017 19:20:11 +0200 Subject: [PATCH 272/394] Revert "smoke: let's catch the sucker" This reverts commit d475882151eaaef958c900a49ea77e0fcf51e44b. --- .../browser/controller/textAreaInput.ts | 3 +- .../browser/controller/textAreaState.ts | 4 --- src/vs/editor/browser/view/viewController.ts | 8 ----- .../src/areas/workbench/data-loss.test.ts | 35 +++++++------------ 4 files changed, 14 insertions(+), 36 deletions(-) diff --git a/src/vs/editor/browser/controller/textAreaInput.ts b/src/vs/editor/browser/controller/textAreaInput.ts index 2844d654431..97926f7e12a 100644 --- a/src/vs/editor/browser/controller/textAreaInput.ts +++ b/src/vs/editor/browser/controller/textAreaInput.ts @@ -11,7 +11,7 @@ import * as strings from 'vs/base/common/strings'; import Event, { Emitter } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable } from 'vs/base/common/lifecycle'; -import { ITypeData, TextAreaState, ITextAreaWrapper, log } from 'vs/editor/browser/controller/textAreaState'; +import { ITypeData, TextAreaState, ITextAreaWrapper } from 'vs/editor/browser/controller/textAreaState'; import * as browser from 'vs/base/browser/browser'; import * as platform from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; @@ -220,7 +220,6 @@ export class TextAreaInput extends Disposable { })); this._register(dom.addDisposableListener(textArea.domNode, 'input', () => { - log.push(`${Date.now()}: input, last known state: ${this._textAreaState}, current state: ${this._textAreaState.readFromTextArea(this._textArea)}`); // Pretend here we touched the text area, as the `input` event will most likely // result in a `selectionchange` event which we want to ignore this._textArea.setIgnoreSelectionChangeTime('received input event'); diff --git a/src/vs/editor/browser/controller/textAreaState.ts b/src/vs/editor/browser/controller/textAreaState.ts index 9c9220681a6..88389a1c924 100644 --- a/src/vs/editor/browser/controller/textAreaState.ts +++ b/src/vs/editor/browser/controller/textAreaState.ts @@ -9,9 +9,6 @@ import { Position } from 'vs/editor/common/core/position'; import { EndOfLinePreference } from 'vs/editor/common/editorCommon'; import * as strings from 'vs/base/common/strings'; -export let log: string[] = []; -(this).myLog = log; - export interface ITextAreaWrapper { getValue(): string; setValue(reason: string, value: string): void; @@ -76,7 +73,6 @@ export class TextAreaState { } public writeToTextArea(reason: string, textArea: ITextAreaWrapper, select: boolean): void { - log.push(`${Date.now()}: writeToTextArea - ${reason} - ${this}`); // console.log(Date.now() + ': applyToTextArea ' + reason + ': ' + this.toString()); textArea.setValue(reason, this.value); if (select) { diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 1dc419d8d79..e44a5286665 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -14,7 +14,6 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents'; import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/common/controller/coreCommands'; import { Configuration } from 'vs/editor/browser/config/configuration'; -import { log } from 'vs/editor/browser/controller/textAreaState'; export interface ExecCoreEditorCommandFunc { (editorCommand: CoreEditorCommand, args: any): void; @@ -64,7 +63,6 @@ export class ViewController { } public paste(source: string, text: string, pasteOnNewLine: boolean): void { - log.push(`${Date.now()}: viewController.paste: ${text}, ${pasteOnNewLine}`); this.commandService.executeCommand(editorCommon.Handler.Paste, { text: text, pasteOnNewLine: pasteOnNewLine, @@ -72,14 +70,12 @@ export class ViewController { } public type(source: string, text: string): void { - log.push(`${Date.now()}: viewController.type: ${text}`); this.commandService.executeCommand(editorCommon.Handler.Type, { text: text }); } public replacePreviousChar(source: string, text: string, replaceCharCnt: number): void { - log.push(`${Date.now()}: viewController.replacePreviousChar: ${text}, ${replaceCharCnt}`); this.commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, { text: text, replaceCharCnt: replaceCharCnt @@ -87,22 +83,18 @@ export class ViewController { } public compositionStart(source: string): void { - log.push(`${Date.now()}: viewController.compositionStart`); this.commandService.executeCommand(editorCommon.Handler.CompositionStart, {}); } public compositionEnd(source: string): void { - log.push(`${Date.now()}: viewController.compositionEnd`); this.commandService.executeCommand(editorCommon.Handler.CompositionEnd, {}); } public cut(source: string): void { - log.push(`${Date.now()}: viewController.cut`); this.commandService.executeCommand(editorCommon.Handler.Cut, {}); } public setSelection(source: string, modelSelection: Selection): void { - log.push(`${Date.now()}: viewController.setSelection: ${modelSelection}`); this._execCoreEditorCommandFunc(CoreNavigationCommands.SetSelection, { source: source, selection: modelSelection diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index 5eb4a801fd6..68d7dd1b377 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -8,41 +8,32 @@ import { SpectronApplication } from '../../spectron/application'; describe('Dataloss', () => { let app: SpectronApplication; before(() => { app = new SpectronApplication(); return app.start('Dataloss'); }); - after(async () => { - const log = await app.client.spectron.client.execute(() => { - return (window as any).myLog as string[]; - }); - - console.log(log.value.join('\n')); - - await app.stop(); - - }); + after(() => app.stop()); it(`verifies that 'hot exit' works for dirty files`, async function () { await app.workbench.newUntitledFile(); const untitled = 'Untitled-1'; - const textToTypeInUntitled = 'Hello, Unitled Code alexandru dimaaaaa joao moreno'; + const textToTypeInUntitled = 'Hello, Unitled Code'; await app.workbench.editor.waitForTypeInEditor(untitled, textToTypeInUntitled); await app.screenCapturer.capture('Untitled file before reload'); - await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1); const readmeMd = 'readme.md'; - const textToType = 'Hello, Code alexandru dimaaaaa joao moreno'; + const textToType = 'Hello, Code'; await app.workbench.explorer.openFile(readmeMd); await app.workbench.editor.waitForTypeInEditor(readmeMd, textToType); await app.screenCapturer.capture(`${readmeMd} before reload`); + + await app.reload(); + await app.screenCapturer.capture('After reload'); + + await app.workbench.waitForActiveTab(readmeMd, true); + await app.screenCapturer.capture(`${readmeMd} after reload`); await app.workbench.editor.waitForEditorContents(readmeMd, c => c.indexOf(textToType) > -1); - // await app.reload(); - // await app.screenCapturer.capture('After reload'); - - // await app.workbench.waitForActiveTab(readmeMd, true); - // await app.screenCapturer.capture(`${readmeMd} after reload`); - - // await app.workbench.waitForTab(untitled, true); - // await app.workbench.selectTab(untitled, true); - // await app.screenCapturer.capture('Untitled file after reload'); + await app.workbench.waitForTab(untitled, true); + await app.workbench.selectTab(untitled, true); + await app.screenCapturer.capture('Untitled file after reload'); + await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1); }); }); \ No newline at end of file From 2fc0bf43dfe8b35a58129e230542cba183b16ccc Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Thu, 19 Oct 2017 10:42:28 -0700 Subject: [PATCH 273/394] Activate emmet on expand abbr cmd Fixes #36267 --- extensions/emmet/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 9a8c21d3892..95c60978a31 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -16,6 +16,7 @@ }, "activationEvents": [ "onCommand:type", + "onCommand:emmet.expandAbbreviation", "onLanguage:html", "onLanguage:css", "onLanguage:scss", From 1eaa61055fe2ea323b15f731dbb0a1f557b64095 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 19 Oct 2017 19:45:52 +0200 Subject: [PATCH 274/394] fix ports finder for node.js 8 --- src/vs/base/node/ports.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/base/node/ports.ts b/src/vs/base/node/ports.ts index c515e902d8b..1ab7de9ab2c 100644 --- a/src/vs/base/node/ports.ts +++ b/src/vs/base/node/ports.ts @@ -46,6 +46,10 @@ function doFindFreePort(startPort: number, giveUpAfter: number, clb: (port: numb return doFindFreePort(startPort + 1, giveUpAfter - 1, clb); }); + client.once('data', () => { + // this listener is required since node.js 8.x + }); + client.once('error', (err: Error & { code?: string }) => { dispose(client); From 694a599fe00ec580784fa8ef60e40e3d6dc4abc1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Oct 2017 22:23:19 +0200 Subject: [PATCH 275/394] Fix #33323 --- .../standalone/browser/simpleServices.ts | 8 + src/vs/platform/workspace/common/workspace.ts | 41 +- .../electron-browser/mainThreadFileSystem.ts | 6 +- .../browser/actions/workspaceActions.ts | 8 +- src/vs/workbench/electron-browser/window.ts | 2 +- .../files/browser/views/explorerViewer.ts | 2 +- .../configuration/node/configuration.ts | 286 ++++++++++++++ .../node/configurationService.ts | 372 +++++------------- .../workspace/common/workspaceEditing.ts | 11 - .../workspace/node/workspaceEditingService.ts | 95 +---- .../workbench/test/workbenchTestServices.ts | 8 + 11 files changed, 445 insertions(+), 394 deletions(-) create mode 100644 src/vs/workbench/services/configuration/node/configuration.ts diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 88a323b05be..5bfb927109a 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -598,4 +598,12 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { return true; } + + public addFolders(foldersToAdd: URI[]): TPromise { + return TPromise.as(void 0); + } + + public removeFolders(foldersToRemove: URI[]): TPromise { + return TPromise.as(void 0); + } } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 04e273ff14c..78875f25837 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -13,6 +13,7 @@ import Event from 'vs/base/common/event'; import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, IStoredWorkspaceFolder, isRawFileWorkspaceFolder, isRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { coalesce, distinct } from 'vs/base/common/arrays'; import { isLinux } from 'vs/base/common/platform'; +import { TPromise } from 'vs/base/common/winjs.base'; export const IWorkspaceContextService = createDecorator('contextService'); @@ -31,21 +32,6 @@ export interface IWorkspaceFoldersChangeEvent { export interface IWorkspaceContextService { _serviceBrand: any; - /** - * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened - * without workspace (empty); - */ - getWorkspace(): IWorkspace; - - /** - * Return the state of the workbench. - * - * WorkbenchState.EMPTY - if the workbench was opened with empty window or file - * WorkbenchState.FOLDER - if the workbench was opened with a folder - * WorkbenchState.WORKSPACE - if the workbench was opened with a workspace - */ - getWorkbenchState(): WorkbenchState; - /** * An event which fires on workbench state changes. */ @@ -61,6 +47,31 @@ export interface IWorkspaceContextService { */ onDidChangeWorkspaceFolders: Event; + /** + * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened + * without workspace (empty); + */ + getWorkspace(): IWorkspace; + + /** + * add folders to the existing workspace + */ + addFolders(folders: URI[]): TPromise; + + /** + * remove folders from the existing workspace + */ + removeFolders(folders: URI[]): TPromise; + + /** + * Return the state of the workbench. + * + * WorkbenchState.EMPTY - if the workbench was opened with empty window or file + * WorkbenchState.FOLDER - if the workbench was opened with a folder + * WorkbenchState.WORKSPACE - if the workbench was opened with a workspace + */ + getWorkbenchState(): WorkbenchState; + /** * Returns the folder for the given resource from the workspace. * Can be null if there is no workspace or the resource is not inside the workspace. diff --git a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts index 5b6ea8b6f3a..a786896b834 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts @@ -12,8 +12,8 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { IProgress } from 'vs/platform/progress/common/progress'; -import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { ISearchResultProvider, ISearchQuery, ISearchComplete, ISearchProgressItem, QueryType, IFileMatch, ISearchService } from 'vs/platform/search/common/search'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @extHostNamedCustomer(MainContext.MainThreadFileSystem) export class MainThreadFileSystem implements MainThreadFileSystemShape { @@ -26,7 +26,7 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape { extHostContext: IExtHostContext, @IFileService private readonly _fileService: IFileService, @ISearchService private readonly _searchService: ISearchService, - @IWorkspaceEditingService private readonly _workspaceEditService: IWorkspaceEditingService + @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService ) { this._proxy = extHostContext.get(ExtHostContext.ExtHostFileSystem); } @@ -45,7 +45,7 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape { } $onDidAddFileSystemRoot(uri: URI): void { - this._workspaceEditService.addFolders([uri]); + this._workspaceContextService.addFolders([uri]); } $onFileSystemChange(handle: number, changes: IFileChange[]): void { diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index ea253e70218..50a08486f98 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -119,7 +119,7 @@ export class AddRootFolderAction extends BaseWorkspacesAction { return TPromise.as(null); } - addFoldersPromise = this.workspaceEditingService.addFolders(folders.map(folder => URI.file(folder))); + addFoldersPromise = this.contextService.addFolders(folders.map(folder => URI.file(folder))); } // Empty or Folder @@ -163,7 +163,7 @@ export class GlobalRemoveRootFolderAction extends BaseWorkspacesAction { } // Workspace: remove folder - return this.workspaceEditingService.removeFolders([folder.uri]).then(() => true); + return this.contextService.removeFolders([folder.uri]).then(() => true); } return true; @@ -216,13 +216,13 @@ export class RemoveRootFolderAction extends Action { private rootUri: URI, id: string, label: string, - @IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService + @IWorkspaceContextService private contextService: IWorkspaceContextService ) { super(id, label); } public run(): TPromise { - return this.workspaceEditingService.removeFolders([this.rootUri]); + return this.contextService.removeFolders([this.rootUri]); } } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 5049e7db79e..aeefa814e9f 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -400,7 +400,7 @@ export class ElectronWindow extends Themable { // Workspace: just add to workspace config if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - this.workspaceEditingService.addFolders(foldersToAdd).done(null, errors.onUnexpectedError); + this.contextService.addFolders(foldersToAdd).done(null, errors.onUnexpectedError); } // Single folder or no workspace: create workspace and open diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 21617036d53..8c02ed1ac07 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -910,7 +910,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { const folders = result.filter(result => result.stat.isDirectory).map(result => result.stat.resource); if (folders.length > 0) { if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - return this.workspaceEditingService.addFolders(folders); + return this.contextService.addFolders(folders); } // If we are in single-folder context, ask for confirmation to create a workspace diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts new file mode 100644 index 00000000000..23a4fa18b23 --- /dev/null +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -0,0 +1,286 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import URI from 'vs/base/common/uri'; +import * as paths from 'vs/base/common/paths'; +import { TPromise } from 'vs/base/common/winjs.base'; +import Event, { Emitter } from 'vs/base/common/event'; +import { readFile } from 'vs/base/node/pfs'; +import * as errors from 'vs/base/common/errors'; +import * as collections from 'vs/base/common/collections'; +import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; +import { isLinux } from 'vs/base/common/platform'; +import { ConfigWatcher } from 'vs/base/node/config'; +import { CustomConfigurationModel, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; +import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; +import { WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; +import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import { IStoredWorkspace, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; +import * as extfs from 'vs/base/node/extfs'; +import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; + +// node.hs helper functions + +interface IStat { + resource: URI; + isDirectory?: boolean; + children?: { resource: URI; }[]; +} + +interface IContent { + resource: URI; + value: string; +} + +function resolveContents(resources: URI[]): TPromise { + const contents: IContent[] = []; + + return TPromise.join(resources.map(resource => { + return resolveContent(resource).then(content => { + contents.push(content); + }); + })).then(() => contents); +} + +function resolveContent(resource: URI): TPromise { + return readFile(resource.fsPath).then(contents => ({ resource, value: contents.toString() })); +} + +function resolveStat(resource: URI): TPromise { + return new TPromise((c, e) => { + extfs.readdir(resource.fsPath, (error, children) => { + if (error) { + if ((error).code === 'ENOTDIR') { + c({ resource }); + } else { + e(error); + } + } else { + c({ + resource, + isDirectory: true, + children: children.map(child => { return { resource: URI.file(paths.join(resource.fsPath, child)) }; }) + }); + } + }); + }); +} + +export class WorkspaceConfiguration extends Disposable { + + private _workspaceConfigPath: URI; + private _workspaceConfigurationWatcher: ConfigWatcher; + private _workspaceConfigurationWatcherDisposables: IDisposable[] = []; + + private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); + public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + + load(workspaceConfigPath: URI): TPromise { + if (this._workspaceConfigPath && this._workspaceConfigPath.fsPath === workspaceConfigPath.fsPath) { + return this.reload(); + } + + this._workspaceConfigPath = workspaceConfigPath; + + this._workspaceConfigurationWatcherDisposables = dispose(this._workspaceConfigurationWatcherDisposables); + return new TPromise((c, e) => { + this._workspaceConfigurationWatcher = new ConfigWatcher(this._workspaceConfigPath.fsPath, { + changeBufferDelay: 300, + onError: error => errors.onUnexpectedError(error), + defaultConfig: new WorkspaceConfigurationModel(JSON.stringify({ folders: [] } as IStoredWorkspace, null, '\t'), this._workspaceConfigPath.fsPath), + parse: (content: string, parseErrors: any[]) => { + const workspaceConfigurationModel = new WorkspaceConfigurationModel(content, this._workspaceConfigPath.fsPath); + parseErrors = [...workspaceConfigurationModel.errors]; + return workspaceConfigurationModel; + }, initCallback: () => c(null) + }); + this._workspaceConfigurationWatcherDisposables.push(this._workspaceConfigurationWatcher); + this._workspaceConfigurationWatcher.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire(), this, this._workspaceConfigurationWatcherDisposables); + }); + } + + private get workspaceConfigurationModel(): WorkspaceConfigurationModel { + return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModel(); + } + + reload(): TPromise { + return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => c(null))); + } + + getFolders(): IStoredWorkspaceFolder[] { + return this.workspaceConfigurationModel.folders; + } + + setFolders(folders: IStoredWorkspaceFolder[], jsonEditingService: JSONEditingService): TPromise { + return jsonEditingService.write(this._workspaceConfigPath, { key: 'folders', value: folders }, true) + .then(() => this.reload()); + } + + getConfiguration(): ConfigurationModel { + return this.workspaceConfigurationModel.workspaceConfiguration; + } + + dispose(): void { + dispose(this._workspaceConfigurationWatcherDisposables); + super.dispose(); + } +} + +export class FolderConfiguration extends Disposable { + + private static RELOAD_CONFIGURATION_DELAY = 50; + + private bulkFetchFromWorkspacePromise: TPromise; + private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise }; + + private reloadConfigurationScheduler: RunOnceScheduler; + private reloadConfigurationEventEmitter: Emitter = new Emitter(); + + constructor(private folder: URI, private configFolderRelativePath: string, private scope: ConfigurationScope) { + super(); + + this.workspaceFilePathToConfiguration = Object.create(null); + this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.loadConfiguration().then(configuration => this.reloadConfigurationEventEmitter.fire(configuration), errors.onUnexpectedError), FolderConfiguration.RELOAD_CONFIGURATION_DELAY)); + } + + loadConfiguration(): TPromise { + // Load workspace locals + return this.loadWorkspaceConfigFiles().then(workspaceConfigFiles => { + // Consolidate (support *.json files in the workspace settings folder) + const workspaceSettingsConfig = workspaceConfigFiles[WORKSPACE_CONFIG_DEFAULT_PATH] || new FolderSettingsModel(null); + const otherConfigModels = Object.keys(workspaceConfigFiles).filter(key => key !== WORKSPACE_CONFIG_DEFAULT_PATH).map(key => workspaceConfigFiles[key]); + return new FolderConfigurationModel(workspaceSettingsConfig, otherConfigModels, this.scope); + }); + } + + private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModel }> { + // once: when invoked for the first time we fetch json files that contribute settings + if (!this.bulkFetchFromWorkspacePromise) { + this.bulkFetchFromWorkspacePromise = resolveStat(this.toResource(this.configFolderRelativePath)).then(stat => { + if (!stat.isDirectory) { + return TPromise.as([]); + } + + return resolveContents(stat.children.filter(stat => { + const isJson = paths.extname(stat.resource.fsPath) === '.json'; + if (!isJson) { + return false; // only JSON files + } + + return this.isWorkspaceConfigurationFile(this.toFolderRelativePath(stat.resource)); // only workspace config files + }).map(stat => stat.resource)); + }, err => [] /* never fail this call */) + .then((contents: IContent[]) => { + contents.forEach(content => this.workspaceFilePathToConfiguration[this.toFolderRelativePath(content.resource)] = TPromise.as(this.createConfigModel(content))); + }, errors.onUnexpectedError); + } + + // on change: join on *all* configuration file promises so that we can merge them into a single configuration object. this + // happens whenever a config file changes, is deleted, or added + return this.bulkFetchFromWorkspacePromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration)); + } + + public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { + const events = event.changes; + let affectedByChanges = false; + + // Find changes that affect workspace configuration files + for (let i = 0, len = events.length; i < len; i++) { + const resource = events[i].resource; + const isJson = paths.extname(resource.fsPath) === '.json'; + const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && paths.isEqual(paths.basename(resource.fsPath), this.configFolderRelativePath)); + if (!isJson && !isDeletedSettingsFolder) { + continue; // only JSON files or the actual settings folder + } + + const workspacePath = this.toFolderRelativePath(resource); + if (!workspacePath) { + continue; // event is not inside workspace + } + + // Handle case where ".vscode" got deleted + if (workspacePath === this.configFolderRelativePath && events[i].type === FileChangeType.DELETED) { + this.workspaceFilePathToConfiguration = Object.create(null); + affectedByChanges = true; + } + + // only valid workspace config files + if (!this.isWorkspaceConfigurationFile(workspacePath)) { + continue; + } + + // insert 'fetch-promises' for add and update events and + // remove promises for delete events + switch (events[i].type) { + case FileChangeType.DELETED: + affectedByChanges = collections.remove(this.workspaceFilePathToConfiguration, workspacePath); + break; + case FileChangeType.UPDATED: + case FileChangeType.ADDED: + this.workspaceFilePathToConfiguration[workspacePath] = resolveContent(resource).then(content => this.createConfigModel(content), errors.onUnexpectedError); + affectedByChanges = true; + } + } + + if (!affectedByChanges) { + return TPromise.as(null); + } + + return new TPromise((c, e) => { + let disposable = this.reloadConfigurationEventEmitter.event(configuration => { + disposable.dispose(); + c(configuration); + }); + // trigger reload of the configuration if we are affected by changes + if (!this.reloadConfigurationScheduler.isScheduled()) { + this.reloadConfigurationScheduler.schedule(); + } + }); + } + + private createConfigModel(content: IContent): ConfigurationModel { + const path = this.toFolderRelativePath(content.resource); + if (path === WORKSPACE_CONFIG_DEFAULT_PATH) { + return new FolderSettingsModel(content.value, content.resource.toString()); + } else { + const matches = /\/([^\.]*)*\.json/.exec(path); + if (matches && matches[1]) { + return new ScopedConfigurationModel(content.value, content.resource.toString(), matches[1]); + } + } + + return new CustomConfigurationModel(null); + } + + private isWorkspaceConfigurationFile(folderRelativePath: string): boolean { + return [WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY], WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY]].some(p => p === folderRelativePath); + } + + private toResource(folderRelativePath: string): URI { + if (typeof folderRelativePath === 'string') { + return URI.file(paths.join(this.folder.fsPath, folderRelativePath)); + } + + return null; + } + + private toFolderRelativePath(resource: URI, toOSPath?: boolean): string { + if (this.contains(resource)) { + return paths.normalize(paths.relative(this.folder.fsPath, resource.fsPath), toOSPath); + } + + return null; + } + + private contains(resource: URI): boolean { + if (resource) { + return paths.isEqualOrParent(resource.fsPath, this.folder.fsPath, !isLinux /* ignorecase */); + } + + return false; + } +} \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index edd6058936e..e56f27c9ca5 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -7,31 +7,28 @@ import URI from 'vs/base/common/uri'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; +import { dirname } from 'path'; import * as assert from 'vs/base/common/assert'; import Event, { Emitter } from 'vs/base/common/event'; import { StrictResourceMap } from 'vs/base/common/map'; -import * as errors from 'vs/base/common/errors'; import { equals } from 'vs/base/common/objects'; -import * as collections from 'vs/base/common/collections'; -import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { RunOnceScheduler } from 'vs/base/common/async'; -import { readFile, stat, writeFile } from 'vs/base/node/pfs'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { Queue } from 'vs/base/common/async'; +import { stat, writeFile } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import * as extfs from 'vs/base/node/extfs'; import { IWorkspaceContextService, Workspace, WorkbenchState, IWorkspaceFolder, toWorkspaceFolders, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; -import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; +import { FileChangesEvent } from 'vs/platform/files/common/files'; import { isLinux } from 'vs/base/common/platform'; -import { ConfigWatcher } from 'vs/base/node/config'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CustomConfigurationModel, ConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; +import { ConfigurationModel, ConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration'; -import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; -import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; +import { FolderConfigurationModel, Configuration, WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; +import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { ConfigurationService as GlobalConfigurationService } from 'vs/platform/configuration/node/configurationService'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationNode, IConfigurationRegistry, Extensions, ConfigurationScope, settingsSchema, resourceSettingsSchema } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; -import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspace } from 'vs/platform/workspaces/common/workspaces'; +import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -39,17 +36,10 @@ import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; - -interface IStat { - resource: URI; - isDirectory?: boolean; - children?: { resource: URI; }[]; -} - -interface IContent { - resource: URI; - value: string; -} +import { WorkspaceConfiguration, FolderConfiguration } from 'vs/workbench/services/configuration/node/configuration'; +import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; +import { Schemas } from 'vs/base/common/network'; +import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces'; export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { @@ -61,6 +51,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private workspaceConfiguration: WorkspaceConfiguration; private cachedFolderConfigs: StrictResourceMap; + private workspaceEditingQueue: Queue; + protected readonly _onDidChangeConfiguration: Emitter = this._register(new Emitter()); public readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; @@ -74,6 +66,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat public readonly onDidChangeWorkbenchState: Event = this._onDidChangeWorkbenchState.event; private configurationEditingService: ConfigurationEditingService; + private jsonEditingService: JSONEditingService; constructor(private environmentService: IEnvironmentService, private workspacesService: IWorkspacesService, private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME) { super(); @@ -84,6 +77,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService)); this._register(this.baseConfigurationService.onDidChangeConfiguration(e => this.onBaseConfigurationChanged(e))); this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(e => this.registerConfigurationSchemas())); + + this.workspaceEditingQueue = new Queue(); } // Workspace Context Service Impl @@ -111,6 +106,16 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.workspace.getFolder(resource); } + public addFolders(foldersToAdd: URI[]): TPromise { + assert.ok(this.jsonEditingService, 'Workbench is not initialized yet'); + return this.workspaceEditingQueue.queue(() => this.doAddFolders(foldersToAdd)); + } + + public removeFolders(foldersToRemove: URI[]): TPromise { + assert.ok(this.jsonEditingService, 'Workbench is not initialized yet'); + return this.workspaceEditingQueue.queue(() => this.doRemoveFolders(foldersToRemove)); + } + public isInsideWorkspace(resource: URI): boolean { return !!this.getWorkspaceFolder(resource); } @@ -125,6 +130,79 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return false; } + private doAddFolders(foldersToAdd: URI[]): TPromise { + if (this.getWorkbenchState() !== WorkbenchState.WORKSPACE) { + return TPromise.as(void 0); // we need a workspace to begin with + } + + const currentWorkspaceFolders = this.getWorkspace().folders; + const currentWorkspaceFolderUris = currentWorkspaceFolders.map(folder => folder.uri); + const currentStoredFolders = currentWorkspaceFolders.map(folder => folder.raw); + + const storedFoldersToAdd: IStoredWorkspaceFolder[] = []; + + const workspaceConfigFolder = dirname(this.getWorkspace().configuration.fsPath); + + foldersToAdd.forEach(folderToAdd => { + if (this.contains(currentWorkspaceFolderUris, folderToAdd)) { + return; // already existing + } + + // File resource: use "path" property + if (folderToAdd.scheme === Schemas.file) { + storedFoldersToAdd.push({ + path: massageFolderPathForWorkspace(folderToAdd.fsPath, workspaceConfigFolder, currentStoredFolders) + }); + } + + // Any other resource: use "uri" property + else { + storedFoldersToAdd.push({ + uri: folderToAdd.toString(true) + }); + } + }); + + if (storedFoldersToAdd.length > 0) { + return this.workspaceConfiguration.setFolders([...currentStoredFolders, ...storedFoldersToAdd], this.jsonEditingService); + } + + return TPromise.as(void 0); + } + + private doRemoveFolders(foldersToRemove: URI[]): TPromise { + if (this.getWorkbenchState() !== WorkbenchState.WORKSPACE) { + return TPromise.as(void 0); // we need a workspace to begin with + } + + const currentWorkspaceFolders = this.getWorkspace().folders; + const currentStoredFolders = currentWorkspaceFolders.map(folder => folder.raw); + + const newStoredFolders: IStoredWorkspaceFolder[] = currentStoredFolders.filter((folder, index) => { + if (!isStoredWorkspaceFolder(folder)) { + return true; // keep entries which are unrelated + } + + return !this.contains(foldersToRemove, currentWorkspaceFolders[index].uri); // keep entries which are unrelated + }); + + if (newStoredFolders.length !== currentStoredFolders.length) { + return this.workspaceConfiguration.setFolders(newStoredFolders, this.jsonEditingService); + } + + return TPromise.as(void 0); + } + + private contains(resources: URI[], toCheck: URI): boolean { + return resources.some(resource => { + if (isLinux) { + return resource.toString() === toCheck.toString(); + } + + return resource.toString().toLowerCase() === toCheck.toString().toLowerCase(); + }); + } + // Workspace Configuration Service Impl getConfigurationData(): IConfigurationData { @@ -198,6 +276,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat setInstantiationService(instantiationService: IInstantiationService): void { this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService); + this.jsonEditingService = instantiationService.createInstance(JSONEditingService); } handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { @@ -226,8 +305,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat const workspaceConfigPath = URI.file(workspaceIdentifier.configPath); return this.workspaceConfiguration.load(workspaceConfigPath) .then(() => { - const workspaceConfigurationModel = this.workspaceConfiguration.workspaceConfigurationModel; - const workspaceFolders = toWorkspaceFolders(workspaceConfigurationModel.folders, URI.file(paths.dirname(workspaceConfigPath.fsPath))); + const workspaceFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), URI.file(paths.dirname(workspaceConfigPath.fsPath))); const workspaceId = workspaceIdentifier.id; const workspaceName = getWorkspaceLabel({ id: workspaceId, configPath: workspaceConfigPath.fsPath }, this.environmentService); return new Workspace(workspaceId, workspaceName, workspaceFolders, workspaceConfigPath); @@ -341,7 +419,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat case WorkbenchState.FOLDER: return folderConfigurations[0]; case WorkbenchState.WORKSPACE: - return this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration; + return this.workspaceConfiguration.getConfiguration(); default: return new ConfigurationModel(); } @@ -378,8 +456,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private onWorkspaceConfigurationChanged(): TPromise { if (this.workspace && this.workspace.configuration && this._configuration) { - const workspaceConfigurationChangeEvent = this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration); - let configuredFolders = toWorkspaceFolders(this.workspaceConfiguration.workspaceConfigurationModel.folders, URI.file(paths.dirname(this.workspace.configuration.fsPath))); + const workspaceConfigurationChangeEvent = this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.getConfiguration()); + let configuredFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), URI.file(paths.dirname(this.workspace.configuration.fsPath))); const changes = this.compareFolders(this.workspace.folders, configuredFolders); if (changes.added.length || changes.removed.length || changes.changed.length) { this.workspace.folders = configuredFolders; @@ -557,244 +635,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } } -class WorkspaceConfiguration extends Disposable { - - private _workspaceConfigPath: URI; - private _workspaceConfigurationWatcher: ConfigWatcher; - private _workspaceConfigurationWatcherDisposables: IDisposable[] = []; - - private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); - public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; - - load(workspaceConfigPath: URI): TPromise { - if (this._workspaceConfigPath && this._workspaceConfigPath.fsPath === workspaceConfigPath.fsPath) { - return this.reload(); - } - - this._workspaceConfigPath = workspaceConfigPath; - - this._workspaceConfigurationWatcherDisposables = dispose(this._workspaceConfigurationWatcherDisposables); - return new TPromise((c, e) => { - this._workspaceConfigurationWatcher = new ConfigWatcher(this._workspaceConfigPath.fsPath, { - changeBufferDelay: 300, - onError: error => errors.onUnexpectedError(error), - defaultConfig: new WorkspaceConfigurationModel(JSON.stringify({ folders: [] } as IStoredWorkspace, null, '\t'), this._workspaceConfigPath.fsPath), - parse: (content: string, parseErrors: any[]) => { - const workspaceConfigurationModel = new WorkspaceConfigurationModel(content, this._workspaceConfigPath.fsPath); - parseErrors = [...workspaceConfigurationModel.errors]; - return workspaceConfigurationModel; - }, initCallback: () => c(null) - }); - this._workspaceConfigurationWatcherDisposables.push(this._workspaceConfigurationWatcher); - this._workspaceConfigurationWatcher.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire(), this, this._workspaceConfigurationWatcherDisposables); - }); - } - - get workspaceConfigurationModel(): WorkspaceConfigurationModel { - return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModel(); - } - - reload(): TPromise { - return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => c(null))); - } - - dispose(): void { - dispose(this._workspaceConfigurationWatcherDisposables); - super.dispose(); - } -} - -class FolderConfiguration extends Disposable { - - private static RELOAD_CONFIGURATION_DELAY = 50; - - private bulkFetchFromWorkspacePromise: TPromise; - private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise }; - - private reloadConfigurationScheduler: RunOnceScheduler; - private reloadConfigurationEventEmitter: Emitter = new Emitter(); - - constructor(private folder: URI, private configFolderRelativePath: string, private scope: ConfigurationScope) { - super(); - - this.workspaceFilePathToConfiguration = Object.create(null); - this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.loadConfiguration().then(configuration => this.reloadConfigurationEventEmitter.fire(configuration), errors.onUnexpectedError), FolderConfiguration.RELOAD_CONFIGURATION_DELAY)); - } - - loadConfiguration(): TPromise { - // Load workspace locals - return this.loadWorkspaceConfigFiles().then(workspaceConfigFiles => { - // Consolidate (support *.json files in the workspace settings folder) - const workspaceSettingsConfig = workspaceConfigFiles[WORKSPACE_CONFIG_DEFAULT_PATH] || new FolderSettingsModel(null); - const otherConfigModels = Object.keys(workspaceConfigFiles).filter(key => key !== WORKSPACE_CONFIG_DEFAULT_PATH).map(key => workspaceConfigFiles[key]); - return new FolderConfigurationModel(workspaceSettingsConfig, otherConfigModels, this.scope); - }); - } - - private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModel }> { - // once: when invoked for the first time we fetch json files that contribute settings - if (!this.bulkFetchFromWorkspacePromise) { - this.bulkFetchFromWorkspacePromise = resolveStat(this.toResource(this.configFolderRelativePath)).then(stat => { - if (!stat.isDirectory) { - return TPromise.as([]); - } - - return resolveContents(stat.children.filter(stat => { - const isJson = paths.extname(stat.resource.fsPath) === '.json'; - if (!isJson) { - return false; // only JSON files - } - - return this.isWorkspaceConfigurationFile(this.toFolderRelativePath(stat.resource)); // only workspace config files - }).map(stat => stat.resource)); - }, err => [] /* never fail this call */) - .then((contents: IContent[]) => { - contents.forEach(content => this.workspaceFilePathToConfiguration[this.toFolderRelativePath(content.resource)] = TPromise.as(this.createConfigModel(content))); - }, errors.onUnexpectedError); - } - - // on change: join on *all* configuration file promises so that we can merge them into a single configuration object. this - // happens whenever a config file changes, is deleted, or added - return this.bulkFetchFromWorkspacePromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration)); - } - - public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { - const events = event.changes; - let affectedByChanges = false; - - // Find changes that affect workspace configuration files - for (let i = 0, len = events.length; i < len; i++) { - const resource = events[i].resource; - const isJson = paths.extname(resource.fsPath) === '.json'; - const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && paths.isEqual(paths.basename(resource.fsPath), this.configFolderRelativePath)); - if (!isJson && !isDeletedSettingsFolder) { - continue; // only JSON files or the actual settings folder - } - - const workspacePath = this.toFolderRelativePath(resource); - if (!workspacePath) { - continue; // event is not inside workspace - } - - // Handle case where ".vscode" got deleted - if (workspacePath === this.configFolderRelativePath && events[i].type === FileChangeType.DELETED) { - this.workspaceFilePathToConfiguration = Object.create(null); - affectedByChanges = true; - } - - // only valid workspace config files - if (!this.isWorkspaceConfigurationFile(workspacePath)) { - continue; - } - - // insert 'fetch-promises' for add and update events and - // remove promises for delete events - switch (events[i].type) { - case FileChangeType.DELETED: - affectedByChanges = collections.remove(this.workspaceFilePathToConfiguration, workspacePath); - break; - case FileChangeType.UPDATED: - case FileChangeType.ADDED: - this.workspaceFilePathToConfiguration[workspacePath] = resolveContent(resource).then(content => this.createConfigModel(content), errors.onUnexpectedError); - affectedByChanges = true; - } - } - - if (!affectedByChanges) { - return TPromise.as(null); - } - - return new TPromise((c, e) => { - let disposable = this.reloadConfigurationEventEmitter.event(configuration => { - disposable.dispose(); - c(configuration); - }); - // trigger reload of the configuration if we are affected by changes - if (!this.reloadConfigurationScheduler.isScheduled()) { - this.reloadConfigurationScheduler.schedule(); - } - }); - } - - private createConfigModel(content: IContent): ConfigurationModel { - const path = this.toFolderRelativePath(content.resource); - if (path === WORKSPACE_CONFIG_DEFAULT_PATH) { - return new FolderSettingsModel(content.value, content.resource.toString()); - } else { - const matches = /\/([^\.]*)*\.json/.exec(path); - if (matches && matches[1]) { - return new ScopedConfigurationModel(content.value, content.resource.toString(), matches[1]); - } - } - - return new CustomConfigurationModel(null); - } - - private isWorkspaceConfigurationFile(folderRelativePath: string): boolean { - return [WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY], WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY]].some(p => p === folderRelativePath); - } - - private toResource(folderRelativePath: string): URI { - if (typeof folderRelativePath === 'string') { - return URI.file(paths.join(this.folder.fsPath, folderRelativePath)); - } - - return null; - } - - private toFolderRelativePath(resource: URI, toOSPath?: boolean): string { - if (this.contains(resource)) { - return paths.normalize(paths.relative(this.folder.fsPath, resource.fsPath), toOSPath); - } - - return null; - } - - private contains(resource: URI): boolean { - if (resource) { - return paths.isEqualOrParent(resource.fsPath, this.folder.fsPath, !isLinux /* ignorecase */); - } - - return false; - } -} - -// node.hs helper functions - -function resolveContents(resources: URI[]): TPromise { - const contents: IContent[] = []; - - return TPromise.join(resources.map(resource => { - return resolveContent(resource).then(content => { - contents.push(content); - }); - })).then(() => contents); -} - -function resolveContent(resource: URI): TPromise { - return readFile(resource.fsPath).then(contents => ({ resource, value: contents.toString() })); -} - -function resolveStat(resource: URI): TPromise { - return new TPromise((c, e) => { - extfs.readdir(resource.fsPath, (error, children) => { - if (error) { - if ((error).code === 'ENOTDIR') { - c({ resource }); - } else { - e(error); - } - } else { - c({ - resource, - isDirectory: true, - children: children.map(child => { return { resource: URI.file(paths.join(resource.fsPath, child)) }; }) - }); - } - }); - }); -} - interface IExportedConfigurationNode { name: string; description: string; diff --git a/src/vs/workbench/services/workspace/common/workspaceEditing.ts b/src/vs/workbench/services/workspace/common/workspaceEditing.ts index 56f6b473db2..8f5e6cd634d 100644 --- a/src/vs/workbench/services/workspace/common/workspaceEditing.ts +++ b/src/vs/workbench/services/workspace/common/workspaceEditing.ts @@ -5,7 +5,6 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import URI from 'vs/base/common/uri'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; @@ -15,16 +14,6 @@ export interface IWorkspaceEditingService { _serviceBrand: ServiceIdentifier; - /** - * add folders to the existing workspace - */ - addFolders(folders: URI[]): TPromise; - - /** - * remove folders from the existing workspace - */ - removeFolders(folders: URI[]): TPromise; - /** * creates a new workspace with the provided folders and opens it. if path is provided * the workspace will be saved into that location. diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index dfe723df71c..f5711bdfb21 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -9,14 +9,10 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IWindowsService, IWindowService, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IWindowService, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; -import { IWorkspacesService, IStoredWorkspaceFolder, IWorkspaceIdentifier, isStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; -import { dirname } from 'path'; +import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces'; -import { isLinux } from 'vs/base/common/platform'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { migrateStorageToMultiRootWorkspace } from 'vs/platform/storage/common/migration'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -26,7 +22,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; -import { Schemas } from 'vs/base/common/network'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -35,10 +30,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { constructor( @IJSONEditingService private jsonEditingService: IJSONEditingService, @IWorkspaceContextService private contextService: WorkspaceService, - @IEnvironmentService private environmentService: IEnvironmentService, - @IWindowsService private windowsService: IWindowsService, @IWindowService private windowService: IWindowService, - @IWorkspacesService private workspacesService: IWorkspacesService, @IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService, @IStorageService private storageService: IStorageService, @IExtensionService private extensionService: IExtensionService, @@ -46,89 +38,6 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { ) { } - public addFolders(foldersToAdd: URI[]): TPromise { - if (!this.isSupported()) { - return TPromise.as(void 0); // we need a workspace to begin with - } - - const currentWorkspaceFolders = this.contextService.getWorkspace().folders; - const currentWorkspaceFolderUris = currentWorkspaceFolders.map(folder => folder.uri); - const currentStoredFolders = currentWorkspaceFolders.map(folder => folder.raw); - - const storedFoldersToAdd: IStoredWorkspaceFolder[] = []; - - const workspaceConfigFolder = dirname(this.contextService.getWorkspace().configuration.fsPath); - - foldersToAdd.forEach(folderToAdd => { - if (this.contains(currentWorkspaceFolderUris, folderToAdd)) { - return; // already existing - } - - // File resource: use "path" property - if (folderToAdd.scheme === Schemas.file) { - storedFoldersToAdd.push({ - path: massageFolderPathForWorkspace(folderToAdd.fsPath, workspaceConfigFolder, currentStoredFolders) - }); - } - - // Any other resource: use "uri" property - else { - storedFoldersToAdd.push({ - uri: folderToAdd.toString(true) - }); - } - }); - - if (storedFoldersToAdd.length > 0) { - return this.doSetFolders([...currentStoredFolders, ...storedFoldersToAdd]); - } - - return TPromise.as(void 0); - } - - public removeFolders(foldersToRemove: URI[]): TPromise { - if (!this.isSupported()) { - return TPromise.as(void 0); // we need a workspace to begin with - } - - const currentWorkspaceFolders = this.contextService.getWorkspace().folders; - const currentStoredFolders = currentWorkspaceFolders.map(folder => folder.raw); - - const newStoredFolders: IStoredWorkspaceFolder[] = currentStoredFolders.filter((folder, index) => { - if (!isStoredWorkspaceFolder(folder)) { - return true; // keep entries which are unrelated - } - - return !this.contains(foldersToRemove, currentWorkspaceFolders[index].uri); // keep entries which are unrelated - }); - - if (newStoredFolders.length !== currentStoredFolders.length) { - return this.doSetFolders(newStoredFolders); - } - - return TPromise.as(void 0); - } - - private doSetFolders(folders: IStoredWorkspaceFolder[]): TPromise { - const workspace = this.contextService.getWorkspace(); - - return this.jsonEditingService.write(workspace.configuration, { key: 'folders', value: folders }, true); - } - - private isSupported(): boolean { - return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE; // we need a multi folder workspace to begin with; - } - - private contains(resources: URI[], toCheck: URI): boolean { - return resources.some(resource => { - if (isLinux) { - return resource.toString() === toCheck.toString(); - } - - return resource.toString().toLowerCase() === toCheck.toString().toLowerCase(); - }); - } - public createAndEnterWorkspace(folderPaths?: string[], path?: string): TPromise { return this.doEnterWorkspace(() => this.windowService.createAndEnterWorkspace(folderPaths, path)); } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 0340fff3501..6c20a16bf44 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -118,6 +118,14 @@ export class TestContextService implements IWorkspaceContextService { return this.workspace; } + public addFolders(foldersToAdd: URI[]): TPromise { + return TPromise.as(void 0); + } + + public removeFolders(foldersToRemove: URI[]): TPromise { + return TPromise.as(void 0); + } + public getWorkspaceFolder(resource: URI): IWorkspaceFolder { return this.isInsideWorkspace(resource) ? this.workspace.folders[0] : null; } From 3571c35c2db55b94766fc323d5e8659759c8f218 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Oct 2017 22:54:47 +0200 Subject: [PATCH 276/394] [folding] refactor fold/unfold (remove CollapsibleRegionsHierarchies) --- .../editor/contrib/folding/browser/folding.ts | 47 ++++-- .../contrib/folding/common/foldingModel.ts | 143 ++---------------- .../contrib/folding/test/foldingModel.test.ts | 107 ++++++++++++- 3 files changed, 151 insertions(+), 146 deletions(-) diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 08cc9c3645d..105e2b4f679 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -17,7 +17,7 @@ import { ICommonCodeEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; -import { FoldingModel, setCollapseStateAtLevel, setCollapseStateRecursivly, fold, unfold, CollapseState } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingModel, setCollapseStateAtLevel, setCollapseStateDown, CollapseState, setCollapseStateLevelsDown, setCollapseStateLevelsUp } from 'vs/editor/contrib/folding/common/foldingModel'; import { computeRanges, limitByIndent } from 'vs/editor/contrib/folding/common/indentFoldStrategy'; import { FoldingDecorationProvider } from './foldingDecorations'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -318,6 +318,13 @@ abstract class FoldingAction extends EditorAction { return editor.getSelections().map(s => s.startLineNumber); } + protected getLineNumbers(args: FoldingArguments, editor: ICommonCodeEditor) { + if (args && args.selectionLines) { + return args.selectionLines.map(l => l + 1); // to 0-bases line numbers + } + return this.getSelectedLines(editor); + } + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { } } @@ -325,6 +332,7 @@ abstract class FoldingAction extends EditorAction { interface FoldingArguments { levels?: number; direction?: 'up' | 'down'; + selectionLines?: number[]; } function foldingArgumentsConstraint(args: any) { @@ -339,6 +347,9 @@ function foldingArgumentsConstraint(args: any) { if (!types.isUndefined(foldingArgs.direction) && !types.isString(foldingArgs.direction)) { return false; } + if (!types.isUndefined(foldingArgs.selectionLines) && (!types.isArray(foldingArgs.selectionLines) || !foldingArgs.selectionLines.every(types.isNumber))) { + return false; + } } return true; } @@ -365,7 +376,9 @@ class UnfoldAction extends FoldingAction { { name: 'Unfold editor argument', description: `Property-value pairs that can be passed through this argument: - * 'level': Number of levels to unfold + * 'levels': Number of levels to unfold. If not set, defaults to 1. + * 'direction': If 'up', unfold given number of levels up otherwise unfolds down + * 'selectionLines': The start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used. `, constraint: foldingArgumentsConstraint } @@ -375,7 +388,13 @@ class UnfoldAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: FoldingArguments): void { - unfold(foldingModel, args ? args.levels || 1 : 1, this.getSelectedLines(editor)); + let levels = args && args.levels || 1; + let lineNumbers = this.getLineNumbers(args, editor); + if (args && args.direction === 'up') { + setCollapseStateLevelsUp(foldingModel, levels, false, lineNumbers); + } else { + setCollapseStateLevelsDown(foldingModel, levels, false, lineNumbers); + } } } @@ -396,7 +415,7 @@ class UnFoldRecursivelyAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: any): void { - setCollapseStateRecursivly(foldingModel, false, this.getSelectedLines(editor)); + setCollapseStateDown(foldingModel, false, this.getSelectedLines(editor)); } } @@ -422,8 +441,9 @@ class FoldAction extends FoldingAction { { name: 'Fold editor argument', description: `Property-value pairs that can be passed through this argument: - * 'levels': Number of levels to fold - * 'up': If 'true', folds given number of levels up otherwise folds down + * 'levels': Number of levels to fold. Defauts to 1 + * 'direction': If 'up', folds given number of levels up otherwise folds down + * 'selectionLines': The start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used. `, constraint: foldingArgumentsConstraint } @@ -433,8 +453,13 @@ class FoldAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor, args: FoldingArguments): void { - args = args ? args : { levels: 1, direction: 'up' }; - fold(foldingModel, args.levels || 1, args.direction === 'up', this.getSelectedLines(editor)); + let levels = args && args.levels || 1; + let lineNumbers = this.getLineNumbers(args, editor); + if (args && args.direction === 'up') { + setCollapseStateLevelsUp(foldingModel, levels, true, lineNumbers); + } else { + setCollapseStateLevelsDown(foldingModel, levels, true, lineNumbers); + } } } @@ -456,7 +481,7 @@ class FoldRecursivelyAction extends FoldingAction { invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { let selectedLines = this.getSelectedLines(editor); - setCollapseStateRecursivly(foldingModel, true, selectedLines); + setCollapseStateDown(foldingModel, true, selectedLines); if (selectedLines.length > 0) { foldingController.reveal(selectedLines[0]); } @@ -481,7 +506,7 @@ class FoldAllAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { - setCollapseStateRecursivly(foldingModel, true); + setCollapseStateDown(foldingModel, true); } } @@ -502,7 +527,7 @@ class UnfoldAllAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICommonCodeEditor): void { - setCollapseStateRecursivly(foldingModel, false); + setCollapseStateDown(foldingModel, false); } } diff --git a/src/vs/editor/contrib/folding/common/foldingModel.ts b/src/vs/editor/contrib/folding/common/foldingModel.ts index cf942cff7a3..182c95ab761 100644 --- a/src/vs/editor/contrib/folding/common/foldingModel.ts +++ b/src/vs/editor/contrib/folding/common/foldingModel.ts @@ -290,27 +290,31 @@ export class FoldingRegion { } } -export function unfold(foldingModel: FoldingModel, levels: number, lineNumbers: number[]): void { +export function setCollapseStateLevelsDown(foldingModel: FoldingModel, levels: number, doCollapse: boolean, lineNumbers?: number[]) { let toToggle = []; for (let lineNumber of lineNumbers) { - let regionsAtLine = getCollapsibleRegionsToUnfoldAtLine(foldingModel, lineNumber, levels); - if (regionsAtLine.length > 0) { - for (let region of regionsAtLine) { - if (region.isCollapsed) { + let region = foldingModel.getRegionAtLine(lineNumber); + if (region) { + if (levels === 1) { + if (region.isCollapsed !== doCollapse) { toToggle.push(region); } + } else { + let regionsInside = foldingModel.getRegionsInside(region.range, (r, level) => r.isCollapsed !== doCollapse && level <= levels); + toToggle.push(...regionsInside); } } - }; + } foldingModel.toggleCollapseState(toToggle); } -export function fold(foldingModel: FoldingModel, levels: number, up: boolean, lineNumbers: number[]): void { +export function setCollapseStateLevelsUp(foldingModel: FoldingModel, levels: number, doCollapse: boolean, lineNumbers?: number[]) { let toToggle = []; for (let lineNumber of lineNumbers) { - let regionsAtLine = getCollapsibleRegionsToFoldAtLine(foldingModel, lineNumber, levels, up); - for (let region of regionsAtLine) { - if (region.isCollapsed) { + let regions = foldingModel.getAllRegionsAtLine(lineNumber); + for (let i = 0; i < levels && regions.length > 0; i++) { + let region = regions.pop(); + if (region.isCollapsed !== doCollapse) { toToggle.push(region); } } @@ -323,7 +327,7 @@ export function fold(foldingModel: FoldingModel, levels: number, up: boolean, li * @param doCollapse Wheter to collase or expand * @param lineNumbers the regions to fold, or if not set all regions in the model. */ -export function setCollapseStateRecursivly(foldingModel: FoldingModel, doCollapse: boolean, lineNumbers?: number[]): void { +export function setCollapseStateDown(foldingModel: FoldingModel, doCollapse: boolean, lineNumbers?: number[]): void { let toToggle = []; if (!lineNumbers) { toToggle = foldingModel.regions.filter(region => region.isCollapsed !== doCollapse); @@ -349,121 +353,4 @@ export function setCollapseStateAtLevel(foldingModel: FoldingModel, foldLevel: n let filter = (region, level) => level === foldLevel && region.isCollapsed !== doCollapse && !blockedLineNumbers.some(line => region.containsLine(line)); let toToggle = foldingModel.getRegionsInside({ startLineNumber: 1, endLineNumber: Number.MAX_VALUE }, filter); foldingModel.toggleCollapseState(toToggle); -} - - - -// old - -export function getCollapsibleRegionsToFoldAtLine(model: FoldingModel, lineNumber: number, levels: number, up: boolean): FoldingRegion[] { - let surroundingRegion: FoldingRegion = model.getRegionAtLine(lineNumber); - if (!surroundingRegion) { - return []; - } - if (levels === 1) { - return [surroundingRegion]; - } - let result = getCollapsibleRegionsFor(model, surroundingRegion, levels, up); - return result.filter(collapsibleRegion => !collapsibleRegion.isCollapsed); -} - -export function getCollapsibleRegionsToUnfoldAtLine(model: FoldingModel, lineNumber: number, levels: number): FoldingRegion[] { - let surroundingRegion: FoldingRegion = model.getRegionAtLine(lineNumber); - if (!surroundingRegion) { - return []; - } - if (levels === 1) { - let regionToUnfold = surroundingRegion.isCollapsed ? surroundingRegion : getFoldedCollapsibleRegionAfterLine(model, surroundingRegion, lineNumber); - return regionToUnfold ? [regionToUnfold] : []; - } - let result = getCollapsibleRegionsFor(model, surroundingRegion, levels, false); - return result.filter(collapsibleRegion => collapsibleRegion.isCollapsed); -} - - -function getFoldedCollapsibleRegionAfterLine(model: FoldingModel, surroundingRegion: FoldingRegion, lineNumber: number): FoldingRegion { - let allRegions = model.regions; - let index = allRegions.indexOf(surroundingRegion); - for (let i = index + 1; i < allRegions.length; i++) { - let region = allRegions[i]; - if (region.isAfterLine(lineNumber)) { - if (!surroundingRegion.contains(region.range)) { - return null; - } - if (region.isCollapsed) { - return region; - } - } - } - return null; -} - -function getCollapsibleRegionsFor(model: FoldingModel, surroundingRegion: FoldingRegion, levels: number, up: boolean): FoldingRegion[] { - let collapsibleRegionsHierarchy: CollapsibleRegionsHierarchy = up ? new CollapsibleRegionsParentHierarchy(model, surroundingRegion) : new CollapsibleRegionsChildrenHierarchy(model, surroundingRegion); - return collapsibleRegionsHierarchy.getRegionsTill(levels); -} - -interface CollapsibleRegionsHierarchy { - getRegionsTill(level: number): FoldingRegion[]; -} - -class CollapsibleRegionsChildrenHierarchy implements CollapsibleRegionsHierarchy { - - children: CollapsibleRegionsChildrenHierarchy[] = []; - lastChildIndex: number; - - constructor(model: FoldingModel, private region: FoldingRegion) { - let allRegions = model.regions; - for (let index = allRegions.indexOf(region) + 1; index < allRegions.length; index++) { - let curr = allRegions[index]; - if (curr.contains(region.range)) { - index = this.processChildRegion(model, curr, index); - } - if (curr.isAfterLine(region.range.endLineNumber)) { - break; - } - } - } - - private processChildRegion(model: FoldingModel, dec: FoldingRegion, index: number): number { - let childRegion = new CollapsibleRegionsChildrenHierarchy(model, dec); - this.children.push(childRegion); - this.lastChildIndex = index; - return childRegion.children.length > 0 ? childRegion.lastChildIndex : index; - } - - public getRegionsTill(level: number): FoldingRegion[] { - let result = [this.region]; - if (level > 1) { - this.children.forEach(region => result = result.concat(region.getRegionsTill(level - 1))); - } - return result; - } -} -class CollapsibleRegionsParentHierarchy implements CollapsibleRegionsHierarchy { - - parent: CollapsibleRegionsParentHierarchy; - lastChildIndex: number; - - constructor(model: FoldingModel, private region: FoldingRegion) { - let allRegions = model.regions; - for (let index = allRegions.indexOf(region) - 1; index >= 0; index--) { - let curr = allRegions[index]; - if (curr.contains(region.range)) { - this.parent = new CollapsibleRegionsParentHierarchy(model, curr); - break; - } - if (curr.isBeforeLine(region.range.endLineNumber)) { - break; - } - } - } - - public getRegionsTill(level: number): FoldingRegion[] { - let result = [this.region]; - if (this.parent && level > 1) { - result = result.concat(this.parent.getRegionsTill(level - 1)); - } - return result; - } } \ No newline at end of file diff --git a/src/vs/editor/contrib/folding/test/foldingModel.test.ts b/src/vs/editor/contrib/folding/test/foldingModel.test.ts index f6a787c2840..f0c89473edf 100644 --- a/src/vs/editor/contrib/folding/test/foldingModel.test.ts +++ b/src/vs/editor/contrib/folding/test/foldingModel.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { FoldingModel, FoldingRegion, setCollapseStateRecursivly, setCollapseStateAtLevel } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingModel, FoldingRegion, setCollapseStateDown, setCollapseStateAtLevel, setCollapseStateLevelsDown, setCollapseStateLevelsUp } from 'vs/editor/contrib/folding/common/foldingModel'; import { Model } from 'vs/editor/common/model/model'; import { computeRanges } from 'vs/editor/common/model/indentRanges'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; @@ -299,22 +299,22 @@ suite('Folding Model', () => { let r5 = r(9, 10, false); assertRegions(foldingModel.regions, [r1, r2, r3, r4, r5]); - setCollapseStateRecursivly(foldingModel, true, [4]); + setCollapseStateDown(foldingModel, true, [4]); assertFoldedRegions(foldingModel, [r3, r4, r5], '1'); - setCollapseStateRecursivly(foldingModel, false, [8]); + setCollapseStateDown(foldingModel, false, [8]); assertFoldedRegions(foldingModel, [], '2'); - setCollapseStateRecursivly(foldingModel, true, [12]); + setCollapseStateDown(foldingModel, true, [12]); assertFoldedRegions(foldingModel, [r2, r3, r4, r5], '1'); - setCollapseStateRecursivly(foldingModel, false, [7]); + setCollapseStateDown(foldingModel, false, [7]); assertFoldedRegions(foldingModel, [r2], '1'); - setCollapseStateRecursivly(foldingModel, false); + setCollapseStateDown(foldingModel, false); assertFoldedRegions(foldingModel, [], '1'); - setCollapseStateRecursivly(foldingModel, true); + setCollapseStateDown(foldingModel, true); assertFoldedRegions(foldingModel, [r1, r2, r3, r4, r5], '1'); }); @@ -368,4 +368,97 @@ suite('Folding Model', () => { }); + test('setCollapseStateLevelsDown', () => { + let lines = [ + /* 1*/ '//#region', + /* 2*/ '//#endregion', + /* 3*/ 'class A {', + /* 4*/ ' void foo() {', + /* 5*/ ' if (true) {', + /* 6*/ ' return;', + /* 7*/ ' }', + /* 8*/ '', + /* 9*/ ' if (true) {', + /* 10*/ ' return;', + /* 11*/ ' }', + /* 12*/ ' }', + /* 13*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ }); + foldingModel.update(ranges); + + let r1 = r(1, 2, false); + let r2 = r(3, 12, false); + let r3 = r(4, 11, false); + let r4 = r(5, 6, false); + let r5 = r(9, 10, false); + assertRegions(foldingModel.regions, [r1, r2, r3, r4, r5]); + + setCollapseStateLevelsDown(foldingModel, 1, true, [4]); + assertFoldedRegions(foldingModel, [r3], '1'); + + setCollapseStateLevelsDown(foldingModel, 2, true, [4]); + assertFoldedRegions(foldingModel, [r3, r4, r5], '2'); + + setCollapseStateLevelsDown(foldingModel, 2, false, [3]); + assertFoldedRegions(foldingModel, [r4, r5], '3'); + + setCollapseStateLevelsDown(foldingModel, 2, false, [2]); + assertFoldedRegions(foldingModel, [r4, r5], '4'); + + setCollapseStateLevelsDown(foldingModel, 4, true, [2]); + assertFoldedRegions(foldingModel, [r1, r4, r5], '5'); + + setCollapseStateLevelsDown(foldingModel, 4, false, [2, 3]); + assertFoldedRegions(foldingModel, [], '6'); + + }); + + test('setCollapseStateLevelsUp', () => { + let lines = [ + /* 1*/ '//#region', + /* 2*/ '//#endregion', + /* 3*/ 'class A {', + /* 4*/ ' void foo() {', + /* 5*/ ' if (true) {', + /* 6*/ ' return;', + /* 7*/ ' }', + /* 8*/ '', + /* 9*/ ' if (true) {', + /* 10*/ ' return;', + /* 11*/ ' }', + /* 12*/ ' }', + /* 13*/ '}']; + + let textModel = Model.createFromString(lines.join('\n')); + let foldingModel = new FoldingModel(textModel, new TestDecorationProvider()); + + let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ }); + foldingModel.update(ranges); + + let r1 = r(1, 2, false); + let r2 = r(3, 12, false); + let r3 = r(4, 11, false); + let r4 = r(5, 6, false); + let r5 = r(9, 10, false); + assertRegions(foldingModel.regions, [r1, r2, r3, r4, r5]); + + setCollapseStateLevelsUp(foldingModel, 1, true, [4]); + assertFoldedRegions(foldingModel, [r3], '1'); + + setCollapseStateLevelsUp(foldingModel, 2, true, [4]); + assertFoldedRegions(foldingModel, [r2, r3], '2'); + + setCollapseStateLevelsUp(foldingModel, 4, false, [1, 3, 4]); + assertFoldedRegions(foldingModel, [], '3'); + + setCollapseStateLevelsUp(foldingModel, 2, true, [10]); + assertFoldedRegions(foldingModel, [r3, r5], '4'); + + + }); + }); \ No newline at end of file From 424e4e0f83cf893c4d16ceaf8f45316ead6625b1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 19 Oct 2017 23:03:07 +0200 Subject: [PATCH 277/394] Tests for #33323 --- .../configuration/node/configuration.ts | 20 +++- .../node/configurationService.ts | 9 +- .../test/node/configurationService.test.ts | 95 ++++++++++++++++++- 3 files changed, 114 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 23a4fa18b23..f19c0052711 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -86,7 +86,7 @@ export class WorkspaceConfiguration extends Disposable { this._workspaceConfigPath = workspaceConfigPath; - this._workspaceConfigurationWatcherDisposables = dispose(this._workspaceConfigurationWatcherDisposables); + this.stopListeningToWatcher(); return new TPromise((c, e) => { this._workspaceConfigurationWatcher = new ConfigWatcher(this._workspaceConfigPath.fsPath, { changeBufferDelay: 300, @@ -98,8 +98,7 @@ export class WorkspaceConfiguration extends Disposable { return workspaceConfigurationModel; }, initCallback: () => c(null) }); - this._workspaceConfigurationWatcherDisposables.push(this._workspaceConfigurationWatcher); - this._workspaceConfigurationWatcher.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire(), this, this._workspaceConfigurationWatcherDisposables); + this.listenToWatcher(); }); } @@ -108,7 +107,11 @@ export class WorkspaceConfiguration extends Disposable { } reload(): TPromise { - return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => c(null))); + this.stopListeningToWatcher(); + return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => { + this.listenToWatcher(); + c(null); + })); } getFolders(): IStoredWorkspaceFolder[] { @@ -124,6 +127,15 @@ export class WorkspaceConfiguration extends Disposable { return this.workspaceConfigurationModel.workspaceConfiguration; } + private listenToWatcher() { + this._workspaceConfigurationWatcherDisposables.push(this._workspaceConfigurationWatcher); + this._workspaceConfigurationWatcher.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire(), this, this._workspaceConfigurationWatcherDisposables); + } + + private stopListeningToWatcher() { + this._workspaceConfigurationWatcherDisposables = dispose(this._workspaceConfigurationWatcherDisposables); + } + dispose(): void { dispose(this._workspaceConfigurationWatcherDisposables); super.dispose(); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index e56f27c9ca5..d2a28dd40b2 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -164,7 +164,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat }); if (storedFoldersToAdd.length > 0) { - return this.workspaceConfiguration.setFolders([...currentStoredFolders, ...storedFoldersToAdd], this.jsonEditingService); + return this.setFolders([...currentStoredFolders, ...storedFoldersToAdd]); } return TPromise.as(void 0); @@ -187,12 +187,17 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat }); if (newStoredFolders.length !== currentStoredFolders.length) { - return this.workspaceConfiguration.setFolders(newStoredFolders, this.jsonEditingService); + return this.setFolders(newStoredFolders); } return TPromise.as(void 0); } + private setFolders(folders: IStoredWorkspaceFolder[]): TPromise { + return this.workspaceConfiguration.setFolders(folders, this.jsonEditingService) + .then(() => this.onWorkspaceConfigurationChanged()); + } + private contains(resources: URI[], toCheck: URI): boolean { return resources.some(resource => { if (isLinux) { diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index 390f2140053..178de894bdd 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -5,11 +5,11 @@ 'use strict'; -import assert = require('assert'); -import os = require('os'); -import path = require('path'); -import fs = require('fs'); +import * as assert from 'assert'; import * as sinon from 'sinon'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -144,6 +144,93 @@ suite('WorkspaceContextService - Folder', () => { }); }); +suite('WorkspaceContextService - Workspace', () => { + + let parentResource: string, testObject: IWorkspaceContextService; + + setup(() => { + return setUpWorkspace(['a', 'b']) + .then(({ parentDir, configPath }) => { + + parentResource = parentDir; + + const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, path.join(parentDir, 'settings.json')); + const workspaceService = new WorkspaceService(environmentService, null); + + const instantiationService = workbenchInstantiationService(); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + + return workspaceService.initialize({ id: configPath, configPath }).then(() => { + + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), workspaceService, { disableWatcher: true })); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.setInstantiationService(instantiationService); + + testObject = workspaceService; + }); + }); + }); + + teardown(done => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + extfs.del(parentResource, os.tmpdir(), () => { }, done); + } + }); + + test('workspace folders', () => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 2); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + }); + + test('add folders', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([URI.file(path.join(workspaceDir, 'd')), URI.file(path.join(workspaceDir, 'c'))]) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + assert.equal(path.basename(actual[2].uri.fsPath), 'd'); + assert.equal(path.basename(actual[3].uri.fsPath), 'c'); + }); + }); + + test('add folders triggers change event', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([URI.file(path.join(workspaceDir, 'd')), URI.file(path.join(workspaceDir, 'c'))]) + .then(() => assert.ok(target.called)); + }); + + test('remove folders', () => { + return testObject.removeFolders([testObject.getWorkspace().folders[0].uri]) + .then(() => { + const actual = testObject.getWorkspace().folders; + assert.equal(actual.length, 1); + assert.equal(path.basename(actual[0].uri.fsPath), 'b'); + }); + }); + + test('remove folders triggers change event', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + return testObject.removeFolders([testObject.getWorkspace().folders[0].uri]) + .then(() => assert.ok(target.called)); + }); + +}); + suite('WorkspaceConfigurationService - Folder', () => { let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string; From d6e8af6c0c687ed662e13ed258f95cb5cc5ac8e1 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 19 Oct 2017 23:11:30 +0200 Subject: [PATCH 278/394] [foldig] fix for restoring folding --- src/vs/editor/contrib/folding/common/foldingModel.ts | 2 +- src/vs/editor/contrib/folding/common/hiddenRangeModel.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/folding/common/foldingModel.ts b/src/vs/editor/contrib/folding/common/foldingModel.ts index 182c95ab761..08f77e32227 100644 --- a/src/vs/editor/contrib/folding/common/foldingModel.ts +++ b/src/vs/editor/contrib/folding/common/foldingModel.ts @@ -146,7 +146,7 @@ export class FoldingModel { let range = this._textModel.getDecorationRange(region.editorDecorationId); if (range) { let startLineNumber = range.startLineNumber; - let endLineNumber = range.endLineNumber + region.range.endLineNumber + region.range.startLineNumber; + let endLineNumber = range.endLineNumber + region.range.endLineNumber - region.range.startLineNumber; collapsedRanges.push({ startLineNumber, endLineNumber }); } } diff --git a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts index 38131fb6ef6..2d199a6ff86 100644 --- a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts +++ b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts @@ -65,7 +65,7 @@ export class HiddenRangeModel { if (!r.startLineNumber || !r.endLineNumber) { return false; } - hiddenRanges.push(new Range(r.startLineNumber, 1, r.endLineNumber, 1)); + hiddenRanges.push(new Range(r.startLineNumber + 1, 1, r.endLineNumber, 1)); } this.applyHiddenRanges(hiddenRanges); return true; From 82dcf9835265cd0a45ec135587ae2a82673f1c8f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 19 Oct 2017 19:52:02 -0700 Subject: [PATCH 279/394] Add support for localizing ts errors (#36451) * Pick up typescript 2.6.1-insiders.20171019 * Add support for localizing ts errors. Fixes #18634 --- extensions/npm-shrinkwrap.json | 6 +++--- extensions/package.json | 2 +- extensions/typescript/package.json | 9 +++++++++ extensions/typescript/package.nls.json | 3 ++- extensions/typescript/src/typescriptMain.ts | 4 +++- .../typescript/src/typescriptServiceClient.ts | 15 ++++++++++++++- extensions/typescript/src/utils/api.ts | 4 ++++ extensions/typescript/src/utils/configuration.ts | 9 ++++++++- 8 files changed, 44 insertions(+), 8 deletions(-) diff --git a/extensions/npm-shrinkwrap.json b/extensions/npm-shrinkwrap.json index 6241de07cd9..004d491bbe7 100644 --- a/extensions/npm-shrinkwrap.json +++ b/extensions/npm-shrinkwrap.json @@ -3,9 +3,9 @@ "version": "0.0.1", "dependencies": { "typescript": { - "version": "2.6.1-insiders.20171016", - "from": "typescript@2.6.1-insiders.20171016", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1-insiders.20171016.tgz" + "version": "2.6.1-insiders.20171019", + "from": "typescript@2.6.1-insiders.20171019", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1-insiders.20171019.tgz" } } } diff --git a/extensions/package.json b/extensions/package.json index bcf3e8b0dc8..1e3f4a31a5d 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "2.6.1-insiders.20171016" + "typescript": "^2.6.1-insiders.20171019" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/typescript/package.json b/extensions/typescript/package.json index 3062949aad7..ea920c7f29f 100644 --- a/extensions/typescript/package.json +++ b/extensions/typescript/package.json @@ -399,6 +399,15 @@ "default": true, "description": "%typescript.quickSuggestionsForPaths%", "scope": "resource" + }, + "typescript.locale": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "%typescript.locale%", + "scope": "window" } } }, diff --git a/extensions/typescript/package.nls.json b/extensions/typescript/package.nls.json index 39725205f50..284db837016 100644 --- a/extensions/typescript/package.nls.json +++ b/extensions/typescript/package.nls.json @@ -42,5 +42,6 @@ "typescript.tsc.autoDetect": "Controls auto detection of tsc tasks. 'off' disables this feature. 'build' only creates single run compile tasks. 'watch' only creates compile and watch tasks. 'on' creates both build and watch tasks. Default is 'on'.", "typescript.problemMatchers.tsc.label": "TypeScript problems", "typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)", - "typescript.quickSuggestionsForPaths": "Enable/disable quick suggestions when typing out an import path." + "typescript.quickSuggestionsForPaths": "Enable/disable quick suggestions when typing out an import path.", + "typescript.locale": "Sets the locale used to report TypeScript errors. Requires TypeScript >= 2.6.0. Default of 'null' uses VS Code's locale for TypeScript errors." } diff --git a/extensions/typescript/src/typescriptMain.ts b/extensions/typescript/src/typescriptMain.ts index b4bd55a6357..99e6f08e734 100644 --- a/extensions/typescript/src/typescriptMain.ts +++ b/extensions/typescript/src/typescriptMain.ts @@ -690,7 +690,9 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost { const converted = new Diagnostic(range, text); converted.severity = this.getDiagnosticSeverity(diagnostic); converted.source = diagnostic.source || source; - converted.code = '' + diagnostic.code; + if (diagnostic.code) { + converted.code = diagnostic.code; + } result.push(converted); } return result; diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index bd5936aa22c..8163808609d 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -11,7 +11,7 @@ import * as os from 'os'; import * as electron from './utils/electron'; import { Reader } from './utils/wireProtocol'; -import { workspace, window, Uri, CancellationToken, Disposable, Memento, MessageItem, EventEmitter, Event, commands } from 'vscode'; +import { workspace, window, Uri, CancellationToken, Disposable, Memento, MessageItem, EventEmitter, Event, commands, env } from 'vscode'; import * as Proto from './protocol'; import { ITypescriptServiceClient, ITypescriptServiceClientHost } from './typescriptService'; import { TypeScriptServerPlugin } from './utils/plugins'; @@ -381,6 +381,13 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient } } + if (this.apiVersion.has260Features()) { + const tsLocale = getTsLocale(this.configuration); + if (tsLocale) { + args.push('--locale', tsLocale); + } + } + electron.fork(currentVersion.tsServerPath, args, options, this.logger, (err: any, childProcess: cp.ChildProcess) => { if (err) { this.lastError = err; @@ -862,3 +869,9 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient this.logTelemetry(telemetryData.telemetryEventName, properties); } } + + +const getTsLocale = (configuration: TypeScriptServiceConfiguration): string | undefined => + (configuration.locale + ? configuration.locale + : env.language); \ No newline at end of file diff --git a/extensions/typescript/src/utils/api.ts b/extensions/typescript/src/utils/api.ts index 91888a52f58..69307cad289 100644 --- a/extensions/typescript/src/utils/api.ts +++ b/extensions/typescript/src/utils/api.ts @@ -69,4 +69,8 @@ export default class API { public has250Features(): boolean { return semver.gte(this.version, '2.5.0'); } + + public has260Features(): boolean { + return semver.gte(this.version, '2.6.0'); + } } \ No newline at end of file diff --git a/extensions/typescript/src/utils/configuration.ts b/extensions/typescript/src/utils/configuration.ts index 4a759024dd5..52792e4c73a 100644 --- a/extensions/typescript/src/utils/configuration.ts +++ b/extensions/typescript/src/utils/configuration.ts @@ -42,6 +42,7 @@ export namespace TsServerLogLevel { } export class TypeScriptServiceConfiguration { + public readonly locale: string | null; public readonly globalTsdk: string | null; public readonly localTsdk: string | null; public readonly npmLocation: string | null; @@ -56,6 +57,7 @@ export class TypeScriptServiceConfiguration { private constructor() { const configuration = workspace.getConfiguration(); + this.locale = TypeScriptServiceConfiguration.extractLocale(configuration); this.globalTsdk = TypeScriptServiceConfiguration.extractGlobalTsdk(configuration); this.localTsdk = TypeScriptServiceConfiguration.extractLocalTsdk(configuration); this.npmLocation = TypeScriptServiceConfiguration.readNpmLocation(configuration); @@ -65,7 +67,8 @@ export class TypeScriptServiceConfiguration { } public isEqualTo(other: TypeScriptServiceConfiguration): boolean { - return this.globalTsdk === other.globalTsdk + return this.locale === other.locale + && this.globalTsdk === other.globalTsdk && this.localTsdk === other.localTsdk && this.npmLocation === other.npmLocation && this.tsServerLogLevel === other.tsServerLogLevel @@ -105,4 +108,8 @@ export class TypeScriptServiceConfiguration { private static readDisableAutomaticTypeAcquisition(configuration: WorkspaceConfiguration): boolean { return configuration.get('typescript.disableAutomaticTypeAcquisition', false); } + + private static extractLocale(configuration: WorkspaceConfiguration): string | null { + return configuration.get('typescript.locale', null); + } } From 49f58653bd5ae68eb0ab1680049c779fffe293c7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 08:13:24 +0200 Subject: [PATCH 280/394] :lipstick: add type --- src/vs/workbench/browser/parts/titlebar/titlebarPart.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index fd748603dc6..9a3ec23a52f 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -33,6 +33,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_BACKGROUND, TITLE_BAR_BORDER } from 'vs/workbench/common/theme'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { isMacintosh } from 'vs/base/common/platform'; +import URI from 'vs/base/common/uri'; export class TitlebarPart extends Part implements ITitleService { @@ -178,7 +179,7 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace(); - let root; + let root: URI; if (workspace.configuration) { root = workspace.configuration; } else if (workspace.folders.length) { From 30e2d204a0def86f644dc59401b8cefed30c0fbb Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 08:43:45 +0200 Subject: [PATCH 281/394] Move getAllOverviewRulerDecorations to IViewModelLinesCollection --- .../decorationsOverviewRuler2.ts | 50 ++---- .../common/viewModel/splitLinesCollection.ts | 156 +++++++++++++++++- src/vs/editor/common/viewModel/viewModel.ts | 17 +- .../common/viewModel/viewModelDecorations.ts | 11 -- .../editor/common/viewModel/viewModelImpl.ts | 17 +- 5 files changed, 193 insertions(+), 58 deletions(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts index 3586b00f799..98c23749c30 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts @@ -14,9 +14,8 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { editorOverviewRulerBorder, editorCursorForeground } from 'vs/editor/common/view/editorColorRegistry'; import { Color } from 'vs/base/common/color'; -import { ITheme, ThemeColor } from 'vs/platform/theme/common/themeService'; +import { ITheme } from 'vs/platform/theme/common/themeService'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; -import { ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations'; class Settings { @@ -275,12 +274,7 @@ export class DecorationsOverviewRuler2 extends ViewPart { } public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean { // invalidate color cache - const decorations = this._context.model.getAllOverviewRulerDecorations(); - for (let i = 0, len = decorations.length; i < len; i++) { - const decoration = decorations[i]; - const opts = decoration.source.options.overviewRuler; - opts._resolvedColor = null; - } + this._context.model.invalidateOverviewRulerColorCache(); return this._updateSettings(false); } @@ -303,10 +297,9 @@ export class DecorationsOverviewRuler2 extends ViewPart { const canvasHeight = this._settings.canvasHeight; const lineHeight = this._settings.lineHeight; const viewLayout = this._context.viewLayout; - const theme = this._context.theme; const outerHeight = this._context.viewLayout.getScrollHeight(); const heightRatio = canvasHeight / outerHeight; - const decorations = this._context.model.getAllOverviewRulerDecorations(); + const decorations = this._context.model.getAllOverviewRulerDecorations(this._context.theme); const minDecorationHeight = (Constants.MIN_DECORATION_HEIGHT * this._settings.pixelRatio) | 0; const halfMinDecorationHeight = (minDecorationHeight / 2) | 0; @@ -322,17 +315,12 @@ export class DecorationsOverviewRuler2 extends ViewPart { const paintQueue = new PaintQueue(canvasCtx, this._settings.x, this._settings.w); for (let i = 0, len = decorations.length; i < len; i++) { const decoration = decorations[i]; - const opts = decoration.source.options.overviewRuler; - const lane = opts.position; - if (lane === 0) { + if (decoration.lane === 0) { continue; } - const startLineNumber = decoration.range.startLineNumber; - const endLineNumber = decoration.range.endLineNumber; - const color = resolveColor(opts, theme); - let y1 = (viewLayout.getVerticalOffsetForLineNumber(startLineNumber) * heightRatio) | 0; - let y2 = ((viewLayout.getVerticalOffsetForLineNumber(endLineNumber) + lineHeight) * heightRatio) | 0; + let y1 = (viewLayout.getVerticalOffsetForLineNumber(decoration.startLineNumber) * heightRatio) | 0; + let y2 = ((viewLayout.getVerticalOffsetForLineNumber(decoration.endLineNumber) + lineHeight) * heightRatio) | 0; let height = y2 - y1; if (height < minDecorationHeight) { let yCenter = ((y1 + y2) / 2) | 0; @@ -345,7 +333,7 @@ export class DecorationsOverviewRuler2 extends ViewPart { y2 = yCenter + halfMinDecorationHeight; } - paintQueueAccept(paintQueue, color, y1, y2, lane); + paintQueueAccept(paintQueue, decoration.color, y1, y2, decoration.lane); } for (let i = 0, len = paintQueue.req.length; i < len; i++) { paintQueueFlush(paintQueue, paintQueue.req[i]); @@ -448,7 +436,9 @@ function paintQueueAccept(Q: PaintQueue, color: string, y1: number, y2: number, if (result !== null) { // there is already an ongoing request for this color & lane // => simply merge into it - result.y2 = y2; + if (y2 > result.y2) { + result.y2 = y2; + } return; } @@ -466,23 +456,3 @@ function paintQueueFlush(Q: PaintQueue, req: PaintRequest): void { Q.ctx.fillStyle = req.color; Q.ctx.fillRect(Q.x[req.lane], req.y1, Q.w[req.lane], req.y2 - req.y1); } - -function resolveColor(opts: ModelDecorationOverviewRulerOptions, theme: ITheme): string { - if (!opts._resolvedColor) { - const themeType = theme.type; - const color = (themeType === 'dark' ? opts.darkColor : themeType === 'light' ? opts.color : opts.hcColor); - opts._resolvedColor = resolveRulerColor(color, theme); - } - return opts._resolvedColor; -} - -function resolveRulerColor(color: string | ThemeColor, theme: ITheme): string { - if (typeof color === 'string') { - return color; - } - let c = color ? theme.getColor(color.id) : null; - if (!c) { - c = Color.transparent; - } - return c.toString(); -} diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 5cf9d2c728a..78bc73c82ee 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -10,10 +10,12 @@ import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; import { PrefixSumComputerWithCache } from 'vs/editor/common/viewModel/prefixSumComputer'; -import { ViewLineData, ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel'; +import { ViewLineData, ICoordinatesConverter, OverviewRulerDecoration } from 'vs/editor/common/viewModel/viewModel'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { WrappingIndent } from 'vs/editor/common/config/editorOptions'; -import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { ThemeColor, ITheme } from 'vs/platform/theme/common/themeService'; +import { Color } from 'vs/base/common/color'; export class OutputPosition { _outputPositionBrand: void; @@ -57,6 +59,7 @@ export interface ISplitLine { getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number; getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position; + getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number; } export interface IViewModelLinesCollection { @@ -82,6 +85,8 @@ export interface IViewModelLinesCollection { getViewLineMaxColumn(viewLineNumber: number): number; getViewLineData(viewLineNumber: number): ViewLineData; getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): ViewLineData[]; + + getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[]; } export class CoordinatesConverter implements ICoordinatesConverter { @@ -650,6 +655,42 @@ export class SplitLinesCollection implements IViewModelLinesCollection { // console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + r.lineNumber + ',' + r); return r; } + + private _getViewLineNumberForModelPosition(inputLineNumber: number, inputColumn: number): number { + let lineIndex = inputLineNumber - 1; + if (this.lines[lineIndex].isVisible()) { + // this model line is visible + const deltaLineNumber = 1 + (lineIndex === 0 ? 0 : this.prefixSumComputer.getAccumulatedValue(lineIndex - 1)); + return this.lines[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, inputColumn); + } + + // this model line is not visible + while (lineIndex > 0 && !this.lines[lineIndex].isVisible()) { + lineIndex--; + } + if (lineIndex === 0 && !this.lines[lineIndex].isVisible()) { + // Could not reach a real line + return 1; + } + const deltaLineNumber = 1 + (lineIndex === 0 ? 0 : this.prefixSumComputer.getAccumulatedValue(lineIndex - 1)); + return this.lines[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1)); + } + + public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[] { + const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation); + const result = new OverviewRulerDecorations(); + for (let i = 0, len = decorations.length; i < len; i++) { + const decoration = decorations[i]; + const opts = decoration.options.overviewRuler; + const lane = opts.position; + const color = resolveColor(opts, theme); + const viewStartLineNumber = this._getViewLineNumberForModelPosition(decoration.range.startLineNumber, decoration.range.startColumn); + const viewEndLineNumber = this._getViewLineNumberForModelPosition(decoration.range.endLineNumber, decoration.range.endColumn); + + result.accept(color, viewStartLineNumber, viewEndLineNumber, lane); + } + return result.result; + } } class VisibleIdentitySplitLine implements ISplitLine { @@ -711,6 +752,10 @@ class VisibleIdentitySplitLine implements ISplitLine { public getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position { return new Position(deltaLineNumber, inputColumn); } + + public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number { + return deltaLineNumber; + } } class InvisibleIdentitySplitLine implements ISplitLine { @@ -761,6 +806,10 @@ class InvisibleIdentitySplitLine implements ISplitLine { public getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position { throw new Error('Not supported'); } + + public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number { + throw new Error('Not supported'); + } } export class SplitLine implements ISplitLine { @@ -914,6 +963,14 @@ export class SplitLine implements ISplitLine { // console.log('in -> out ' + deltaLineNumber + ',' + inputColumn + ' ===> ' + (deltaLineNumber+outputLineIndex) + ',' + outputColumn); return new Position(deltaLineNumber + outputLineIndex, outputColumn); } + + public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number { + if (!this._isVisible) { + throw new Error('Not supported'); + } + const r = this.positionMapper.getOutputPositionOfInputOffset(inputColumn - 1); + return (deltaLineNumber + r.outputLineIndex); + } } function createSplitLine(linePositionMapperFactory: ILineMapperFactory, text: string, tabSize: number, wrappingColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent, isVisible: boolean): ISplitLine { @@ -1093,4 +1150,99 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { return result; } + + public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[] { + const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation); + const result = new OverviewRulerDecorations(); + for (let i = 0, len = decorations.length; i < len; i++) { + const decoration = decorations[i]; + const opts = decoration.options.overviewRuler; + const lane = opts.position; + const color = resolveColor(opts, theme); + const viewStartLineNumber = decoration.range.startLineNumber; + const viewEndLineNumber = decoration.range.endLineNumber; + + result.accept(color, viewStartLineNumber, viewEndLineNumber, lane); + } + result.flushAll(); + return result.result; + } +} + +class OverviewRulerDecorations { + + readonly req: OverviewRulerDecoration[] = []; + readonly result: OverviewRulerDecoration[] = []; + + constructor() { + } + + public accept(color: string, startLineNumber: number, endLineNumber: number, lane: number): void { + let result: OverviewRulerDecoration = null; + for (let i = 0, len = this.req.length; i < len; i++) { + const req = this.req[i]; + if (req.endLineNumber < startLineNumber) { + this._flush(req); + + if (i + 1 === len) { + // last element + this.req.pop(); + break; + } else { + this.req[i] = this.req.pop(); + len--; + i--; + continue; + } + } + + if (req.lane === lane && req.color === color) { + result = req; + break; + } + } + + if (result !== null) { + // there is already an ongoing request for this color & lane + // => simply merge into it + if (endLineNumber > result.endLineNumber) { + result.endLineNumber = endLineNumber; + } + return; + } + + result = new OverviewRulerDecoration(startLineNumber, endLineNumber, lane, color); + this.req.push(result); + } + + public flushAll(): void { + for (let i = 0, len = this.req.length; i < len; i++) { + this._flush(this.req[i]); + } + } + + private _flush(element: OverviewRulerDecoration): void { + this.result.push(element); + } +} + + +function resolveColor(opts: ModelDecorationOverviewRulerOptions, theme: ITheme): string { + if (!opts._resolvedColor) { + const themeType = theme.type; + const color = (themeType === 'dark' ? opts.darkColor : themeType === 'light' ? opts.color : opts.hcColor); + opts._resolvedColor = resolveRulerColor(color, theme); + } + return opts._resolvedColor; +} + +function resolveRulerColor(color: string | ThemeColor, theme: ITheme): string { + if (typeof color === 'string') { + return color; + } + let c = color ? theme.getColor(color.id) : null; + if (!c) { + c = Color.transparent; + } + return c.toString(); } diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index 2890bf9314f..ac489285266 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState } from 'vs/editor/common/editorCommon'; +import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState, OverviewRulerLane } from 'vs/editor/common/editorCommon'; import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; @@ -14,6 +14,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { Scrollable, IScrollPosition } from 'vs/base/common/scrollable'; import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer'; +import { ITheme } from 'vs/platform/theme/common/themeService'; export interface IViewWhitespaceViewportData { readonly id: number; @@ -138,7 +139,8 @@ export interface IViewModel { getLineMaxColumn(lineNumber: number): number; getLineFirstNonWhitespaceColumn(lineNumber: number): number; getLineLastNonWhitespaceColumn(lineNumber: number): number; - getAllOverviewRulerDecorations(): ViewModelDecoration[]; + getAllOverviewRulerDecorations(theme: ITheme): OverviewRulerDecoration[]; + invalidateOverviewRulerColorCache(): void; getValueInRange(range: Range, eol: EndOfLinePreference): string; getModelLineMaxColumn(modelLineNumber: number): number; @@ -276,6 +278,17 @@ export class ViewModelDecoration { } } +export class OverviewRulerDecoration { + _overviewRulerDecorationBrand: void; + + constructor( + public readonly startLineNumber: number, + public endLineNumber: number, + public readonly lane: OverviewRulerLane, + public readonly color: string + ) { } +} + export class ViewEventsCollector { private _events: ViewEvent[]; diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index be7a324004a..e1bcdeda1a3 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -88,17 +88,6 @@ export class ViewModelDecorations implements IDisposable { return r; } - public getAllOverviewRulerDecorations(): ViewModelDecoration[] { - let modelDecorations = this.model.getOverviewRulerDecorations(this.editorId, this.configuration.editor.readOnly); - let result: ViewModelDecoration[] = [], resultLen = 0; - for (let i = 0, len = modelDecorations.length; i < len; i++) { - let modelDecoration = modelDecorations[i]; - let viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration); - result[resultLen++] = viewModelDecoration; - } - return result; - } - public getDecorationsViewportData(viewRange: Range): IDecorationsViewportData { var cacheIsValid = true; cacheIsValid = cacheIsValid && (this._cachedModelDecorationsResolver !== null); diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 68cdaf1ccbc..8eb47ab129f 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -12,7 +12,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { TokenizationRegistry, ColorId, LanguageId } from 'vs/editor/common/modes'; import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer'; import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations'; -import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, ViewEventsCollector } from 'vs/editor/common/viewModel/viewModel'; +import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, ViewEventsCollector, OverviewRulerDecoration } from 'vs/editor/common/viewModel/viewModel'; import { SplitLinesCollection, IViewModelLinesCollection, IdentityLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { MinimapTokensColorTracker } from 'vs/editor/common/view/minimapCharRenderer'; @@ -22,6 +22,8 @@ import { CharacterHardWrappingLineMapperFactory } from 'vs/editor/common/viewMod import { ViewLayout } from 'vs/editor/common/viewLayout/viewLayout'; import { Color } from 'vs/base/common/color'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { ITheme } from 'vs/platform/theme/common/themeService'; +import { ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations'; const USE_IDENTITY_LINES_COLLECTION = true; @@ -428,8 +430,17 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ); } - public getAllOverviewRulerDecorations(): ViewModelDecoration[] { - return this.decorations.getAllOverviewRulerDecorations(); + public getAllOverviewRulerDecorations(theme: ITheme): OverviewRulerDecoration[] { + return this.lines.getAllOverviewRulerDecorations(this.editorId, this.configuration.editor.readOnly, theme); + } + + public invalidateOverviewRulerColorCache(): void { + const decorations = this.model.getOverviewRulerDecorations(); + for (let i = 0, len = decorations.length; i < len; i++) { + const decoration = decorations[i]; + const opts = decoration.options.overviewRuler; + opts._resolvedColor = null; + } } public getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference): string { From b6d492b4469aa236d7ca087f2587ba19e5775d2f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 09:18:34 +0200 Subject: [PATCH 282/394] Encode overview ruler decorations in a number array --- .../decorationsOverviewRuler2.ts | 144 +++++------------- .../common/viewModel/splitLinesCollection.ts | 71 +++------ src/vs/editor/common/viewModel/viewModel.ts | 21 ++- .../editor/common/viewModel/viewModelImpl.ts | 4 +- 4 files changed, 78 insertions(+), 162 deletions(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts index 98c23749c30..a6933438dba 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts @@ -312,31 +312,51 @@ export class DecorationsOverviewRuler2 extends ViewPart { canvasCtx.fillRect(0, 0, canvasWidth, canvasHeight); } - const paintQueue = new PaintQueue(canvasCtx, this._settings.x, this._settings.w); - for (let i = 0, len = decorations.length; i < len; i++) { - const decoration = decorations[i]; - if (decoration.lane === 0) { - continue; - } + const x = this._settings.x; + const w = this._settings.w; + for (let color in decorations) { + const colorDecorations = decorations[color]; - let y1 = (viewLayout.getVerticalOffsetForLineNumber(decoration.startLineNumber) * heightRatio) | 0; - let y2 = ((viewLayout.getVerticalOffsetForLineNumber(decoration.endLineNumber) + lineHeight) * heightRatio) | 0; - let height = y2 - y1; - if (height < minDecorationHeight) { - let yCenter = ((y1 + y2) / 2) | 0; - if (yCenter < halfMinDecorationHeight) { - yCenter = halfMinDecorationHeight; - } else if (yCenter + halfMinDecorationHeight > canvasHeight) { - yCenter = canvasHeight - halfMinDecorationHeight; + canvasCtx.fillStyle = color; + + let prevLane = 0; + let prevY1 = 0; + let prevY2 = 0; + for (let i = 0, len = colorDecorations.length; i < len; i++) { + const lane = colorDecorations[3 * i]; + const startLineNumber = colorDecorations[3 * i + 1]; + const endLineNumber = colorDecorations[3 * i + 2]; + + let y1 = (viewLayout.getVerticalOffsetForLineNumber(startLineNumber) * heightRatio) | 0; + let y2 = ((viewLayout.getVerticalOffsetForLineNumber(endLineNumber) + lineHeight) * heightRatio) | 0; + let height = y2 - y1; + if (height < minDecorationHeight) { + let yCenter = ((y1 + y2) / 2) | 0; + if (yCenter < halfMinDecorationHeight) { + yCenter = halfMinDecorationHeight; + } else if (yCenter + halfMinDecorationHeight > canvasHeight) { + yCenter = canvasHeight - halfMinDecorationHeight; + } + y1 = yCenter - halfMinDecorationHeight; + y2 = yCenter + halfMinDecorationHeight; } - y1 = yCenter - halfMinDecorationHeight; - y2 = yCenter + halfMinDecorationHeight; - } - paintQueueAccept(paintQueue, decoration.color, y1, y2, decoration.lane); - } - for (let i = 0, len = paintQueue.req.length; i < len; i++) { - paintQueueFlush(paintQueue, paintQueue.req[i]); + if (y1 > prevY2 || lane !== prevLane) { + // flush prev + if (i !== 0) { + canvasCtx.fillRect(x[prevLane], prevY1, w[prevLane], prevY2 - prevY1); + } + prevLane = lane; + prevY1 = y1; + prevY2 = y2; + } else { + // can merge into prev + if (y2 > prevY2) { + prevY2 = y2; + } + } + } + canvasCtx.fillRect(x[prevLane], prevY1, w[prevLane], prevY2 - prevY1); } // Draw cursors @@ -376,83 +396,3 @@ export class DecorationsOverviewRuler2 extends ViewPart { } } -class PaintRequest { - public color: string; - public y1: number; - public y2: number; - public lane: number; - - public init(color: string, y1: number, y2: number, lane: number): void { - this.color = color; - this.y1 = y1; - this.y2 = y2; - this.lane = lane; - } -} - -class PaintQueue { - readonly ctx: CanvasRenderingContext2D; - - readonly x: number[]; - readonly w: number[]; - - readonly req: PaintRequest[] = []; - readonly pool: PaintRequest[] = []; - - constructor(ctx: CanvasRenderingContext2D, x: number[], w: number[]) { - this.ctx = ctx; - this.x = x; - this.w = w; - } -} - -function paintQueueAccept(Q: PaintQueue, color: string, y1: number, y2: number, lane: number): void { - let result: PaintRequest = null; - for (let i = 0, len = Q.req.length; i < len; i++) { - const req = Q.req[i]; - if (req.y2 < y1) { - paintQueueFlush(Q, req); - - if (i + 1 === len) { - // last element - Q.req.pop(); - Q.pool.push(req); - break; - } else { - Q.req[i] = Q.req.pop(); - len--; - Q.pool.push(req); - i--; - continue; - } - } - - if (req.lane === lane && req.color === color) { - result = req; - break; - } - } - - if (result !== null) { - // there is already an ongoing request for this color & lane - // => simply merge into it - if (y2 > result.y2) { - result.y2 = y2; - } - return; - } - - if (Q.pool.length > 0) { - result = Q.pool.pop(); - } else { - result = new PaintRequest(); - } - - result.init(color, y1, y2, lane); - Q.req.push(result); -} - -function paintQueueFlush(Q: PaintQueue, req: PaintRequest): void { - Q.ctx.fillStyle = req.color; - Q.ctx.fillRect(Q.x[req.lane], req.y1, Q.w[req.lane], req.y2 - req.y1); -} diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 78bc73c82ee..5531f419ef2 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -10,7 +10,7 @@ import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { LineTokens } from 'vs/editor/common/core/lineTokens'; import { PrefixSumComputerWithCache } from 'vs/editor/common/viewModel/prefixSumComputer'; -import { ViewLineData, ICoordinatesConverter, OverviewRulerDecoration } from 'vs/editor/common/viewModel/viewModel'; +import { ViewLineData, ICoordinatesConverter, IOverviewRulerDecorations } from 'vs/editor/common/viewModel/viewModel'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { WrappingIndent } from 'vs/editor/common/config/editorOptions'; import { ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations'; @@ -86,7 +86,7 @@ export interface IViewModelLinesCollection { getViewLineData(viewLineNumber: number): ViewLineData; getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): ViewLineData[]; - getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[]; + getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations; } export class CoordinatesConverter implements ICoordinatesConverter { @@ -676,13 +676,16 @@ export class SplitLinesCollection implements IViewModelLinesCollection { return this.lines[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1)); } - public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[] { + public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations { const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation); const result = new OverviewRulerDecorations(); for (let i = 0, len = decorations.length; i < len; i++) { const decoration = decorations[i]; const opts = decoration.options.overviewRuler; const lane = opts.position; + if (lane === 0) { + continue; + } const color = resolveColor(opts, theme); const viewStartLineNumber = this._getViewLineNumberForModelPosition(decoration.range.startLineNumber, decoration.range.startColumn); const viewEndLineNumber = this._getViewLineNumberForModelPosition(decoration.range.endLineNumber, decoration.range.endColumn); @@ -1151,78 +1154,52 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { return result; } - public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[] { + public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations { const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation); const result = new OverviewRulerDecorations(); for (let i = 0, len = decorations.length; i < len; i++) { const decoration = decorations[i]; const opts = decoration.options.overviewRuler; const lane = opts.position; + if (lane === 0) { + continue; + } const color = resolveColor(opts, theme); const viewStartLineNumber = decoration.range.startLineNumber; const viewEndLineNumber = decoration.range.endLineNumber; result.accept(color, viewStartLineNumber, viewEndLineNumber, lane); } - result.flushAll(); return result.result; } } class OverviewRulerDecorations { - readonly req: OverviewRulerDecoration[] = []; - readonly result: OverviewRulerDecoration[] = []; + readonly result: IOverviewRulerDecorations = Object.create(null); constructor() { } public accept(color: string, startLineNumber: number, endLineNumber: number, lane: number): void { - let result: OverviewRulerDecoration = null; - for (let i = 0, len = this.req.length; i < len; i++) { - const req = this.req[i]; - if (req.endLineNumber < startLineNumber) { - this._flush(req); + let prev = this.result[color]; - if (i + 1 === len) { - // last element - this.req.pop(); - break; - } else { - this.req[i] = this.req.pop(); - len--; - i--; - continue; + if (prev) { + const prevLane = prev[prev.length - 3]; + const prevEndLineNumber = prev[prev.length - 1]; + if (prevLane === lane && prevEndLineNumber >= startLineNumber) { + // merge into prev + if (endLineNumber > prevEndLineNumber) { + prev[prev.length - 1] = endLineNumber; } + return; } - if (req.lane === lane && req.color === color) { - result = req; - break; - } + // push + prev.push(lane, startLineNumber, endLineNumber); + } else { + this.result[color] = [lane, startLineNumber, endLineNumber]; } - - if (result !== null) { - // there is already an ongoing request for this color & lane - // => simply merge into it - if (endLineNumber > result.endLineNumber) { - result.endLineNumber = endLineNumber; - } - return; - } - - result = new OverviewRulerDecoration(startLineNumber, endLineNumber, lane, color); - this.req.push(result); - } - - public flushAll(): void { - for (let i = 0, len = this.req.length; i < len; i++) { - this._flush(this.req[i]); - } - } - - private _flush(element: OverviewRulerDecoration): void { - this.result.push(element); } } diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index ac489285266..cd4ea6a28b8 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState, OverviewRulerLane } from 'vs/editor/common/editorCommon'; +import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState } from 'vs/editor/common/editorCommon'; import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; @@ -139,7 +139,7 @@ export interface IViewModel { getLineMaxColumn(lineNumber: number): number; getLineFirstNonWhitespaceColumn(lineNumber: number): number; getLineLastNonWhitespaceColumn(lineNumber: number): number; - getAllOverviewRulerDecorations(theme: ITheme): OverviewRulerDecoration[]; + getAllOverviewRulerDecorations(theme: ITheme): IOverviewRulerDecorations; invalidateOverviewRulerColorCache(): void; getValueInRange(range: Range, eol: EndOfLinePreference): string; @@ -278,15 +278,14 @@ export class ViewModelDecoration { } } -export class OverviewRulerDecoration { - _overviewRulerDecorationBrand: void; - - constructor( - public readonly startLineNumber: number, - public endLineNumber: number, - public readonly lane: OverviewRulerLane, - public readonly color: string - ) { } +/** + * Decorations are encoded in a number array using the following scheme: + * - 3*i = lane + * - 3*i+1 = startLineNumber + * - 3*i+2 = endLineNumber + */ +export interface IOverviewRulerDecorations { + [color: string]: number[]; } export class ViewEventsCollector { diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 8eb47ab129f..d316d894d62 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -12,7 +12,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { TokenizationRegistry, ColorId, LanguageId } from 'vs/editor/common/modes'; import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer'; import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations'; -import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, ViewEventsCollector, OverviewRulerDecoration } from 'vs/editor/common/viewModel/viewModel'; +import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, ViewEventsCollector, IOverviewRulerDecorations } from 'vs/editor/common/viewModel/viewModel'; import { SplitLinesCollection, IViewModelLinesCollection, IdentityLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { MinimapTokensColorTracker } from 'vs/editor/common/view/minimapCharRenderer'; @@ -430,7 +430,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ); } - public getAllOverviewRulerDecorations(theme: ITheme): OverviewRulerDecoration[] { + public getAllOverviewRulerDecorations(theme: ITheme): IOverviewRulerDecorations { return this.lines.getAllOverviewRulerDecorations(this.editorId, this.configuration.editor.readOnly, theme); } From 69ab7b140e8a5a8615edfd63bdc38e14c2d99ffd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 09:26:01 +0200 Subject: [PATCH 283/394] More aggressive merging of overview ruler decorations --- .../viewParts/overviewRuler/decorationsOverviewRuler2.ts | 4 ++-- src/vs/editor/common/viewModel/splitLinesCollection.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts index a6933438dba..288c6803f2b 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts @@ -341,7 +341,7 @@ export class DecorationsOverviewRuler2 extends ViewPart { y2 = yCenter + halfMinDecorationHeight; } - if (y1 > prevY2 || lane !== prevLane) { + if (y1 > prevY2 + 1 || lane !== prevLane) { // flush prev if (i !== 0) { canvasCtx.fillRect(x[prevLane], prevY1, w[prevLane], prevY2 - prevY1); @@ -350,7 +350,7 @@ export class DecorationsOverviewRuler2 extends ViewPart { prevY1 = y1; prevY2 = y2; } else { - // can merge into prev + // merge into prev if (y2 > prevY2) { prevY2 = y2; } diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 5531f419ef2..501001f4b95 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -1187,7 +1187,7 @@ class OverviewRulerDecorations { if (prev) { const prevLane = prev[prev.length - 3]; const prevEndLineNumber = prev[prev.length - 1]; - if (prevLane === lane && prevEndLineNumber >= startLineNumber) { + if (prevLane === lane && prevEndLineNumber + 1 >= startLineNumber) { // merge into prev if (endLineNumber > prevEndLineNumber) { prev[prev.length - 1] = endLineNumber; From 34e74ba1578fe105afc8ca26615f45f9397bdd96 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 09:38:09 +0200 Subject: [PATCH 284/394] Tweak the way find decorations are managed --- .../contrib/find/common/findDecorations.ts | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findDecorations.ts b/src/vs/editor/contrib/find/common/findDecorations.ts index 4a59a7b7e56..20db13e30ca 100644 --- a/src/vs/editor/contrib/find/common/findDecorations.ts +++ b/src/vs/editor/contrib/find/common/findDecorations.ts @@ -132,29 +132,32 @@ export class FindDecorations implements IDisposable { } public set(findMatches: editorCommon.FindMatch[], findScope: Range): void { - let newDecorations: editorCommon.IModelDeltaDecoration[] = new Array(findMatches.length); - for (let i = 0, len = findMatches.length; i < len; i++) { - newDecorations[i] = { - range: findMatches[i].range, - options: FindDecorations._FIND_MATCH_DECORATION - }; - } - if (findScope) { - newDecorations.unshift({ - range: findScope, - options: FindDecorations._FIND_SCOPE_DECORATION - }); - } - let tmpDecorations = this._editor.deltaDecorations(this._allDecorations(), newDecorations); + this._editor.changeDecorations((accessor) => { + // Find matches + let newFindMatchesDecorations: editorCommon.IModelDeltaDecoration[] = new Array(findMatches.length); + for (let i = 0, len = findMatches.length; i < len; i++) { + newFindMatchesDecorations[i] = { + range: findMatches[i].range, + options: FindDecorations._FIND_MATCH_DECORATION + }; + } + this._decorations = accessor.deltaDecorations(this._decorations, newFindMatchesDecorations); - if (findScope) { - this._findScopeDecorationId = tmpDecorations.shift(); - } else { - this._findScopeDecorationId = null; - } - this._decorations = tmpDecorations; - this._rangeHighlightDecorationId = null; - this._highlightedDecorationId = null; + // Range highlight + if (this._rangeHighlightDecorationId) { + accessor.removeDecoration(this._rangeHighlightDecorationId); + this._rangeHighlightDecorationId = null; + } + + // Find scope + if (this._findScopeDecorationId) { + accessor.removeDecoration(this._findScopeDecorationId); + this._findScopeDecorationId = null; + } + if (findScope) { + this._findScopeDecorationId = accessor.addDecoration(findScope, FindDecorations._FIND_SCOPE_DECORATION); + } + }); } private _allDecorations(): string[] { From c01d8c1ac13be3ef3058a9ac7635eb0c2f5f1f7a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 10:07:37 +0200 Subject: [PATCH 285/394] Approximate find matches in the overview ruler if there are a high number of results --- .../contrib/find/common/findDecorations.ts | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/find/common/findDecorations.ts b/src/vs/editor/contrib/find/common/findDecorations.ts index 20db13e30ca..09cb7eb07d0 100644 --- a/src/vs/editor/contrib/find/common/findDecorations.ts +++ b/src/vs/editor/contrib/find/common/findDecorations.ts @@ -16,6 +16,7 @@ export class FindDecorations implements IDisposable { private _editor: editorCommon.ICommonCodeEditor; private _decorations: string[]; + private _overviewRulerApproximateDecorations: string[]; private _findScopeDecorationId: string; private _rangeHighlightDecorationId: string; private _highlightedDecorationId: string; @@ -24,6 +25,7 @@ export class FindDecorations implements IDisposable { constructor(editor: editorCommon.ICommonCodeEditor) { this._editor = editor; this._decorations = []; + this._overviewRulerApproximateDecorations = []; this._findScopeDecorationId = null; this._rangeHighlightDecorationId = null; this._highlightedDecorationId = null; @@ -35,6 +37,7 @@ export class FindDecorations implements IDisposable { this._editor = null; this._decorations = []; + this._overviewRulerApproximateDecorations = []; this._findScopeDecorationId = null; this._rangeHighlightDecorationId = null; this._highlightedDecorationId = null; @@ -43,6 +46,7 @@ export class FindDecorations implements IDisposable { public reset(): void { this._decorations = []; + this._overviewRulerApproximateDecorations = []; this._findScopeDecorationId = null; this._rangeHighlightDecorationId = null; this._highlightedDecorationId = null; @@ -133,16 +137,59 @@ export class FindDecorations implements IDisposable { public set(findMatches: editorCommon.FindMatch[], findScope: Range): void { this._editor.changeDecorations((accessor) => { + + let findMatchesOptions: ModelDecorationOptions = FindDecorations._FIND_MATCH_DECORATION; + let newOverviewRulerApproximateDecorations: editorCommon.IModelDeltaDecoration[] = []; + + if (findMatches.length > 1000) { + // we go into a mode where the overview ruler gets "approximate" decorations + // the reason is that the overview ruler paints all the decorations in the file and we don't want to cause freezes + findMatchesOptions = FindDecorations._FIND_MATCH_NO_OVERVIEW_DECORATION; + + // approximate a distance in lines where matches should be merged + const lineCount = this._editor.getModel().getLineCount(); + const height = this._editor.getLayoutInfo().height; + const approxPixelsPerLine = height / lineCount; + const mergeLinesDelta = Math.max(2, Math.ceil(3 / approxPixelsPerLine)); + + // merge decorations as much as possible + let prevStartLineNumber = findMatches[0].range.startLineNumber; + let prevEndLineNumber = findMatches[0].range.endLineNumber; + for (let i = 1, len = findMatches.length; i < len; i++) { + const range = findMatches[i].range; + if (prevEndLineNumber + mergeLinesDelta >= range.startLineNumber) { + if (range.endLineNumber > prevEndLineNumber) { + prevEndLineNumber = range.endLineNumber; + } + } else { + newOverviewRulerApproximateDecorations.push({ + range: new Range(prevStartLineNumber, 1, prevEndLineNumber, 1), + options: FindDecorations._FIND_MATCH_ONLY_OVERVIEW_DECORATION + }); + prevStartLineNumber = range.startLineNumber; + prevEndLineNumber = range.endLineNumber; + } + } + + newOverviewRulerApproximateDecorations.push({ + range: new Range(prevStartLineNumber, 1, prevEndLineNumber, 1), + options: FindDecorations._FIND_MATCH_ONLY_OVERVIEW_DECORATION + }); + } + // Find matches let newFindMatchesDecorations: editorCommon.IModelDeltaDecoration[] = new Array(findMatches.length); for (let i = 0, len = findMatches.length; i < len; i++) { newFindMatchesDecorations[i] = { range: findMatches[i].range, - options: FindDecorations._FIND_MATCH_DECORATION + options: findMatchesOptions }; } this._decorations = accessor.deltaDecorations(this._decorations, newFindMatchesDecorations); + // Overview ruler approximate decorations + this._overviewRulerApproximateDecorations = accessor.deltaDecorations(this._overviewRulerApproximateDecorations, newOverviewRulerApproximateDecorations); + // Range highlight if (this._rangeHighlightDecorationId) { accessor.removeDecoration(this._rangeHighlightDecorationId); @@ -163,6 +210,7 @@ export class FindDecorations implements IDisposable { private _allDecorations(): string[] { let result: string[] = []; result = result.concat(this._decorations); + result = result.concat(this._overviewRulerApproximateDecorations); if (this._findScopeDecorationId) { result.push(this._findScopeDecorationId); } @@ -194,6 +242,21 @@ export class FindDecorations implements IDisposable { } }); + private static _FIND_MATCH_NO_OVERVIEW_DECORATION = ModelDecorationOptions.register({ + stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + className: 'findMatch', + showIfCollapsed: true + }); + + private static _FIND_MATCH_ONLY_OVERVIEW_DECORATION = ModelDecorationOptions.register({ + stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + overviewRuler: { + color: themeColorFromId(editorFindMatchHighlight), + darkColor: themeColorFromId(editorFindMatchHighlight), + position: editorCommon.OverviewRulerLane.Center + } + }); + private static _RANGE_HIGHLIGHT_DECORATION = ModelDecorationOptions.register({ stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, className: 'rangeHighlight', From bb74340d4cf5982ce81fc7911e5efa45415fdff2 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 10:28:30 +0200 Subject: [PATCH 286/394] CompositeBar: respect icon setting in CompositeActionItem fixes #36618 --- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 2 +- .../browser/parts/compositebar/compositeBarActions.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 6f0ca9a6f33..3b3a8c1570a 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -327,7 +327,7 @@ export class CompositeBar implements ICompositeBar { const compositeActivityAction = this.options.getActivityAction(compositeId); const pinnedAction = this.options.getCompositePinnedAction(compositeId); - this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this.options.colors, this); + this.compositeIdToActionItems[compositeId] = this.instantiationService.createInstance(CompositeActionItem, compositeActivityAction, pinnedAction, this.options.colors, this.options.icon, this); this.compositeIdToActions[compositeId] = compositeActivityAction; return compositeActivityAction; diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 415f8c9daa1..5971250d6ff 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -381,13 +381,14 @@ export class CompositeActionItem extends ActivityActionItem { private compositeActivityAction: ActivityAction, private toggleCompositePinnedAction: Action, colors: ICompositeBarColors, + icon: boolean, private compositeBar: ICompositeBar, @IContextMenuService private contextMenuService: IContextMenuService, @IKeybindingService private keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService ) { - super(compositeActivityAction, { draggable: true, colors }, themeService); + super(compositeActivityAction, { draggable: true, colors, icon }, themeService); this.cssClass = compositeActivityAction.class; From c45ca4efee787f3ca16f7c3defffc238df769285 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 20 Oct 2017 11:03:24 +0200 Subject: [PATCH 287/394] use SetupMutex fixes #36545 --- build/win32/code.iss | 1 + 1 file changed, 1 insertion(+) diff --git a/build/win32/code.iss b/build/win32/code.iss index 73b031fe643..409bae2c2f5 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -19,6 +19,7 @@ OutputBaseFilename=VSCodeSetup Compression=lzma SolidCompression=yes AppMutex={#AppMutex} +SetupMutex={#AppMutex}setup WizardImageFile={#RepoDir}\resources\win32\inno-big.bmp WizardSmallImageFile={#RepoDir}\resources\win32\inno-small.bmp SetupIconFile={#RepoDir}\resources\win32\code.ico From 5b4c9d25345f04e06ae22c939cbffdf471b9edb3 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 11:10:00 +0200 Subject: [PATCH 288/394] explorerModel: better isDirectory setting --- .../parts/files/common/explorerModel.ts | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index e20b9c1921e..33f96015590 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -77,7 +77,7 @@ export class FileStat implements IFileStat { public name: string; public mtime: number; public etag: string; - public isDirectory: boolean; + private _isDirectory: boolean; public hasChildren: boolean; public children: FileStat[]; public parent: FileStat; @@ -92,10 +92,6 @@ export class FileStat implements IFileStat { this.etag = etag; this.mtime = mtime; - // Prepare child stat array - if (this.isDirectory) { - this.children = []; - } if (!this.root) { this.root = this; } @@ -103,6 +99,22 @@ export class FileStat implements IFileStat { this.isDirectoryResolved = false; } + public get isDirectory(): boolean { + return this._isDirectory; + } + + public set isDirectory(value: boolean) { + if (value !== this._isDirectory) { + this._isDirectory = value; + if (this._isDirectory) { + this.children = []; + } else { + this.children = undefined; + } + } + + } + public get nonexistentRoot(): boolean { return this.isRoot && !this.isDirectoryResolved; } From 9146ff33522d7f6b1e134b6893ca8cb6bd91f64d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 11:18:01 +0200 Subject: [PATCH 289/394] Query model for decorations only for visible model lines in the viewport (in contiguos visible model lines batches) --- .../common/viewModel/splitLinesCollection.ts | 43 +++++++++++++++++++ .../common/viewModel/viewModelDecorations.ts | 12 +++--- .../editor/common/viewModel/viewModelImpl.ts | 2 +- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 501001f4b95..f57572f1e38 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -87,6 +87,7 @@ export interface IViewModelLinesCollection { getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): ViewLineData[]; getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations; + getDecorationsInRange(range: Range, ownerId: number, filterOutValidation: boolean): editorCommon.IModelDecoration[]; } export class CoordinatesConverter implements ICoordinatesConverter { @@ -694,6 +695,44 @@ export class SplitLinesCollection implements IViewModelLinesCollection { } return result.result; } + + public getDecorationsInRange(range: Range, ownerId: number, filterOutValidation: boolean): editorCommon.IModelDecoration[] { + const modelStart = this.convertViewPositionToModelPosition(range.startLineNumber, range.startColumn); + const modelEnd = this.convertViewPositionToModelPosition(range.endLineNumber, range.endColumn); + + if (modelEnd.lineNumber - modelStart.lineNumber <= range.endLineNumber - range.startLineNumber) { + // most likely there are no hidden lines => fast path + return this.model.getDecorationsInRange(new Range(modelStart.lineNumber, modelStart.column, modelEnd.lineNumber, modelEnd.column), ownerId, filterOutValidation); + } + + let result: editorCommon.IModelDecoration[] = []; + const modelStartLineIndex = modelStart.lineNumber - 1; + const modelEndLineIndex = modelEnd.lineNumber - 1; + + let reqStart: Position = null; + for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) { + const line = this.lines[modelLineIndex]; + if (line.isVisible()) { + // merge into previous request + if (reqStart === null) { + reqStart = new Position(modelLineIndex + 1, modelLineIndex === modelStartLineIndex ? modelStart.column : 1); + } + } else { + // hit invisible line => flush request + if (reqStart !== null) { + result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelLineIndex + 1, 1))); + reqStart = null; + } + } + } + + if (reqStart !== null) { + result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelEnd.lineNumber, modelEnd.column))); + reqStart = null; + } + + return result; + } } class VisibleIdentitySplitLine implements ISplitLine { @@ -1172,6 +1211,10 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { } return result.result; } + + public getDecorationsInRange(range: Range, ownerId: number, filterOutValidation: boolean): editorCommon.IModelDecoration[] { + return this.model.getDecorationsInRange(range, ownerId, filterOutValidation); + } } class OverviewRulerDecorations { diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index e1bcdeda1a3..f468105a4bf 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -9,6 +9,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Position } from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { InlineDecoration, ViewModelDecoration, ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel'; +import { IViewModelLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection'; export interface IDecorationsViewportData { /** @@ -26,6 +27,7 @@ export class ViewModelDecorations implements IDisposable { private readonly editorId: number; private readonly model: editorCommon.IModel; private readonly configuration: editorCommon.IConfiguration; + private readonly _linesCollection: IViewModelLinesCollection; private readonly _coordinatesConverter: ICoordinatesConverter; private _decorationsCache: { [decorationId: string]: ViewModelDecoration; }; @@ -33,10 +35,11 @@ export class ViewModelDecorations implements IDisposable { private _cachedModelDecorationsResolver: IDecorationsViewportData; private _cachedModelDecorationsResolverViewRange: Range; - constructor(editorId: number, model: editorCommon.IModel, configuration: editorCommon.IConfiguration, coordinatesConverter: ICoordinatesConverter) { + constructor(editorId: number, model: editorCommon.IModel, configuration: editorCommon.IConfiguration, linesCollection: IViewModelLinesCollection, coordinatesConverter: ICoordinatesConverter) { this.editorId = editorId; this.model = model; this.configuration = configuration; + this._linesCollection = linesCollection; this._coordinatesConverter = coordinatesConverter; this._decorationsCache = Object.create(null); this._clearCachedModelDecorationsResolver(); @@ -100,10 +103,9 @@ export class ViewModelDecorations implements IDisposable { } private _getDecorationsViewportData(viewportRange: Range): IDecorationsViewportData { - let viewportModelRange = this._coordinatesConverter.convertViewRangeToModelRange(viewportRange); - let startLineNumber = viewportRange.startLineNumber; - let endLineNumber = viewportRange.endLineNumber; - let modelDecorations = this.model.getDecorationsInRange(viewportModelRange, this.editorId, this.configuration.editor.readOnly); + const modelDecorations = this._linesCollection.getDecorationsInRange(viewportRange, this.editorId, this.configuration.editor.readOnly); + const startLineNumber = viewportRange.startLineNumber; + const endLineNumber = viewportRange.endLineNumber; let decorationsInViewport: ViewModelDecoration[] = [], decorationsInViewportLen = 0; let inlineDecorations: InlineDecoration[][] = []; diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index d316d894d62..25a52e2f2b9 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -82,7 +82,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel this._isDisposing = false; this._centeredViewLine = -1; - this.decorations = new ViewModelDecorations(this.editorId, this.model, this.configuration, this.coordinatesConverter); + this.decorations = new ViewModelDecorations(this.editorId, this.model, this.configuration, this.lines, this.coordinatesConverter); this._register(this.model.addBulkListener((events: EmitterEvent[]) => { if (this._isDisposing) { From 819c00594eef41d96182fb92be0ca8c8b94a60aa Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 11:33:14 +0200 Subject: [PATCH 290/394] Simplify ViewModelDecoration --- .../viewParts/decorations/decorations.ts | 16 +++++------ .../viewParts/glyphMargin/glyphMargin.ts | 2 +- .../linesDecorations/linesDecorations.ts | 2 +- .../marginDecorations/marginDecorations.ts | 2 +- src/vs/editor/common/viewModel/viewModel.ts | 12 ++++---- .../common/viewModel/viewModelDecorations.ts | 20 ++++++------- .../viewModel/viewModelDecorations.test.ts | 28 +++++++++---------- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/vs/editor/browser/viewParts/decorations/decorations.ts b/src/vs/editor/browser/viewParts/decorations/decorations.ts index 2cc107d4037..dc63ec06edc 100644 --- a/src/vs/editor/browser/viewParts/decorations/decorations.ts +++ b/src/vs/editor/browser/viewParts/decorations/decorations.ts @@ -78,15 +78,15 @@ export class DecorationsOverlay extends DynamicViewOverlay { let decorations: ViewModelDecoration[] = [], decorationsLen = 0; for (let i = 0, len = _decorations.length; i < len; i++) { let d = _decorations[i]; - if (d.source.options.className) { + if (d.options.className) { decorations[decorationsLen++] = d; } } // Sort decorations for consistent render output decorations = decorations.sort((a, b) => { - let aClassName = a.source.options.className; - let bClassName = b.source.options.className; + let aClassName = a.options.className; + let bClassName = b.options.className; if (aClassName < bClassName) { return -1; @@ -120,13 +120,13 @@ export class DecorationsOverlay extends DynamicViewOverlay { for (let i = 0, lenI = decorations.length; i < lenI; i++) { let d = decorations[i]; - if (!d.source.options.isWholeLine) { + if (!d.options.isWholeLine) { continue; } let decorationOutput = ( '
' @@ -148,12 +148,12 @@ export class DecorationsOverlay extends DynamicViewOverlay { for (let i = 0, lenI = decorations.length; i < lenI; i++) { const d = decorations[i]; - if (d.source.options.isWholeLine) { + if (d.options.isWholeLine) { continue; } - const className = d.source.options.className; - const showIfCollapsed = d.source.options.showIfCollapsed; + const className = d.options.className; + const showIfCollapsed = d.options.showIfCollapsed; let range = d.range; if (showIfCollapsed && range.endColumn === 1 && range.endLineNumber !== range.startLineNumber) { diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index 33874c27b51..757305ebc08 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -145,7 +145,7 @@ export class GlyphMarginOverlay extends DedupOverlay { let r: DecorationToRender[] = [], rLen = 0; for (let i = 0, len = decorations.length; i < len; i++) { let d = decorations[i]; - let glyphMarginClassName = d.source.options.glyphMarginClassName; + let glyphMarginClassName = d.options.glyphMarginClassName; if (glyphMarginClassName) { r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, glyphMarginClassName); } diff --git a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts index 3a143124040..43767788096 100644 --- a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts +++ b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts @@ -73,7 +73,7 @@ export class LinesDecorationsOverlay extends DedupOverlay { let r: DecorationToRender[] = [], rLen = 0; for (let i = 0, len = decorations.length; i < len; i++) { let d = decorations[i]; - let linesDecorationsClassName = d.source.options.linesDecorationsClassName; + let linesDecorationsClassName = d.options.linesDecorationsClassName; if (linesDecorationsClassName) { r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, linesDecorationsClassName); } diff --git a/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts b/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts index b83c9faa123..75ff0a0e3ed 100644 --- a/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts +++ b/src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts @@ -63,7 +63,7 @@ export class MarginViewLineDecorationsOverlay extends DedupOverlay { let r: DecorationToRender[] = [], rLen = 0; for (let i = 0, len = decorations.length; i < len; i++) { let d = decorations[i]; - let marginClassName = d.source.options.marginClassName; + let marginClassName = d.options.marginClassName; if (marginClassName) { r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, marginClassName); } diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index cd4ea6a28b8..88787418a97 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState } from 'vs/editor/common/editorCommon'; +import { INewScrollPosition, EndOfLinePreference, IViewState, IModelDecorationOptions } from 'vs/editor/common/editorCommon'; import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; @@ -269,12 +269,12 @@ export class InlineDecoration { export class ViewModelDecoration { _viewModelDecorationBrand: void; - public range: Range; - public readonly source: IModelDecoration; + public readonly range: Range; + public readonly options: IModelDecorationOptions; - constructor(source: IModelDecoration) { - this.range = null; - this.source = source; + constructor(range: Range, options: IModelDecorationOptions) { + this.range = range; + this.options = options; } } diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index f468105a4bf..b5c6aa4b5ba 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -72,21 +72,21 @@ export class ViewModelDecorations implements IDisposable { } private _getOrCreateViewModelDecoration(modelDecoration: editorCommon.IModelDecoration): ViewModelDecoration { - let id = modelDecoration.id; + const id = modelDecoration.id; let r = this._decorationsCache[id]; if (!r) { - r = new ViewModelDecoration(modelDecoration); - this._decorationsCache[id] = r; - } - if (r.range === null) { const modelRange = modelDecoration.range; - if (modelDecoration.options.isWholeLine) { - let start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1)); - let end = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber))); - r.range = new Range(start.lineNumber, start.column, end.lineNumber, end.column); + const options = modelDecoration.options; + let viewRange: Range; + if (options.isWholeLine) { + const start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1)); + const end = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber))); + viewRange = new Range(start.lineNumber, start.column, end.lineNumber, end.column); } else { - r.range = this._coordinatesConverter.convertModelRangeToViewRange(modelRange); + viewRange = this._coordinatesConverter.convertModelRangeToViewRange(modelRange); } + r = new ViewModelDecoration(viewRange, options); + this._decorationsCache[id] = r; } return r; } diff --git a/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts b/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts index 0f52c5129c3..20bbda92be7 100644 --- a/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts +++ b/src/vs/editor/test/common/viewModel/viewModelDecorations.test.ts @@ -91,23 +91,23 @@ suite('ViewModelDecorations', () => { let actualDecorations = viewModel.getDecorationsInViewport( new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)) ).map((dec) => { - return dec.source.id; + return dec.options.className; }); assert.deepEqual(actualDecorations, [ - dec2, - dec3, - dec4, - dec5, - dec6, - dec7, - dec8, - dec9, - dec10, - dec11, - dec12, - dec13, - dec14, + 'dec2', + 'dec3', + 'dec4', + 'dec5', + 'dec6', + 'dec7', + 'dec8', + 'dec9', + 'dec10', + 'dec11', + 'dec12', + 'dec13', + 'dec14', ]); let inlineDecorations1 = viewModel.getViewLineRenderingData( From 9d40f0c647bf1de0aaa813e6519b85a24e98da14 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 11:47:48 +0200 Subject: [PATCH 291/394] tweak scoring to prevent match scattering --- .../parts/quickopen/common/quickOpenScorer.ts | 302 ++++++++++-------- .../test/common/quickOpenScorer.test.ts | 95 +++++- 2 files changed, 263 insertions(+), 134 deletions(-) diff --git a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts index a479c16aa0a..7667f60d43d 100644 --- a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts +++ b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts @@ -14,180 +14,218 @@ import { stripWildcards } from 'vs/base/common/strings'; export type Score = [number /* score */, number[] /* match positions */]; export type ScorerCache = { [key: string]: IItemScore }; -const NO_SCORE: Score = [0, []]; +const NO_MATCH = 0; +const NO_SCORE: Score = [NO_MATCH, []]; -export function _doScore(target: string, query: string, queryLower: string, fuzzy: boolean): Score { +// const DEBUG = false; +// const DEBUG_MATRIX = false; + +export function score(target: string, query: string, queryLower: string, fuzzy: boolean): Score { if (!target || !query) { return NO_SCORE; // return early if target or query are undefined } - if (target.length < query.length) { + const targetLength = target.length; + const queryLength = query.length; + + if (targetLength < queryLength) { return NO_SCORE; // impossible for query to be contained in target } - // console.group(`Target: ${target}, Query: ${query}`); + // if (DEBUG) { + // console.group(`Target: ${target}, Query: ${query}`); + // } - const queryLen = query.length; const targetLower = target.toLowerCase(); - let res = NO_SCORE; - // When not searching fuzzy, we require the query to be contained fully - // in the target string. We set the offset to search from to that location. + // in the target string contiguously. if (!fuzzy) { const indexOfQueryInTarget = targetLower.indexOf(queryLower); if (indexOfQueryInTarget === -1) { - // console.log(`Characters not matching consecutively ${queryLower} within ${targetLower}`); + // if (DEBUG) { + // console.log(`Characters not matching consecutively ${queryLower} within ${targetLower}`); + // } return NO_SCORE; } - - res = _doScoreFromOffset(target, query, targetLower, queryLower, queryLen, indexOfQueryInTarget); } - // When searching fuzzy we run the scorer for each location of the first query - // character so that we can produce better results in case the pattern matches - // multiple times on the target (prevent scattering of matching positions). + // When searching fuzzy, we require the query to be contained fully + // in the target string as separate substrings else { - const queryFirstCharacter = queryLower[0]; + let targetOffset = 0; + for (let queryIndex = 0; queryIndex < queryLength; queryIndex++) { + targetOffset = targetLower.indexOf(queryLower[queryIndex], targetOffset); + if (targetOffset === -1) { + return NO_SCORE; + } + } + } - let offset = 0; - while ((offset = targetLower.indexOf(queryFirstCharacter, offset)) !== -1) { - const scoreFromOffset = _doScoreFromOffset(target, query, targetLower, queryLower, queryLen, offset); - if (isBetterScore(res, scoreFromOffset)) { - res = scoreFromOffset; + const res = doScore(query, queryLower, queryLength, target, targetLower, targetLength); + + // if (DEBUG) { + // console.log(`%cFinal Score: ${res[0]}`, 'font-weight: bold'); + // console.groupEnd(); + // } + + return res; +} + +function doScore(query: string, queryLower: string, queryLength: number, target: string, targetLower: string, targetLength: number): [number, number[]] { + const scores = []; + const matches = []; + + // + // Build Scorer Matrix + // The matrix is composed of query q and target t. For each index we score + // q[i] with t[i] and compare that with the previous score. If the score is + // equal or larger, we keep the match. In addition to the score, we also keep + // the length of the consecutive matches to use as boost for the score. + // + // t a r g e t + // q + // u + // e + // r + // y + // + for (let queryIndex = 0; queryIndex < queryLength; queryIndex++) { + for (let targetIndex = 0; targetIndex < targetLength; targetIndex++) { + const currentIndex = queryIndex * targetLength + targetIndex; + const leftIndex = currentIndex - 1; + const diagIndex = (queryIndex - 1) * targetLength + targetIndex - 1; + + const leftScore = targetIndex > 0 ? scores[leftIndex] : 0; + const diagScore = queryIndex > 0 && targetIndex > 0 ? scores[diagIndex] : 0; + + const matchesSequenceLength = queryIndex > 0 && targetIndex > 0 ? matches[diagIndex] : 0; + + const score = computeCharScore(query, queryLower, queryIndex, target, targetLower, targetIndex, matchesSequenceLength); + + // We have a score and its equal or larger than the left score + // Match: sequence continues growing from previous diag value + // Score: increases by diag score value + if (score && diagScore + score >= leftScore) { + matches[currentIndex] = matchesSequenceLength + 1; + scores[currentIndex] = diagScore + score; } - offset++; + // We either have no score or the score is lower than the left score + // Match: reset to 0 + // Score: pick up from left hand side + else { + matches[currentIndex] = NO_MATCH; + scores[currentIndex] = leftScore; + } } } - // console.log(`%cFinal Score: ${score}`, 'font-weight: bold'); - // console.groupEnd(); + // Restore Positions (starting from bottom right of matrix) + const positions = []; + let queryIndex = queryLength - 1; + let targetIndex = targetLength - 1; + while (queryIndex >= 0 && targetIndex >= 0) { + const currentIndex = queryIndex * targetLength + targetIndex; + const match = matches[currentIndex]; + if (match === NO_MATCH) { + targetIndex--; // go left + } else { + positions.push(targetIndex); - return res; + // go up and left + queryIndex--; + targetIndex--; + } + } + + // Print matrix + // if (DEBUG_MATRIX) { + // printMatrix(query, target, matches, scores); + // } + + return [scores[queryLength * targetLength - 1], positions.reverse()]; } -function isBetterScore(score: Score, candidate: Score): boolean { - if (candidate[0] > score[0]) { - return true; // candidate has higher score - } - - if (score[0] > candidate[0]) { - return false; // candidate has lower score - } - - // Score is the same, check by match compactness - const matchStart = score[1][0]; - const matchEnd = score[1][score[1].length - 1]; - const matchLength = matchEnd - matchStart; - - const candidateMatchStart = candidate[1][0]; - const candidateMatchEnd = candidate[1][candidate[1].length - 1]; - const candidateMatchLength = candidateMatchEnd - candidateMatchStart; - - if (candidateMatchLength < matchLength) { - return true; // candidate has more compact matches - } - - return false; -} - -// Based on material from: -/*! -BEGIN THIRD PARTY -*/ -/*! -* string_score.js: String Scoring Algorithm 0.1.22 -* -* http://joshaven.com/string_score -* https://github.com/joshaven/string_score -* -* Copyright (C) 2009-2014 Joshaven Potter -* Special thanks to all of the contributors listed here https://github.com/joshaven/string_score -* MIT License: http://opensource.org/licenses/MIT -* -* Date: Tue Mar 1 2011 -* Updated: Tue Mar 10 2015 -*/ -function _doScoreFromOffset(target: string, query: string, targetLower: string, queryLower: string, queryLen: number, offset: number): Score { - const matchingPositions: number[] = []; - - let targetIndex = offset; - let queryIndex = 0; +function computeCharScore(query: string, queryLower: string, queryIndex: number, target: string, targetLower: string, targetIndex: number, matchesSequenceLength: number): number { let score = 0; - while (queryIndex < queryLen) { - // Check for query character being contained in target - const indexOfQueryInTarget = targetLower.indexOf(queryLower[queryIndex], targetIndex); + if (queryLower[queryIndex] !== targetLower[targetIndex]) { + return score; // no match of characters + } - if (indexOfQueryInTarget < 0) { - // console.log(`Character not part of target ${query[index]}`); + // Character match bonus + score += 1; - score = 0; - break; - } + // if (DEBUG) { + // console.groupCollapsed(`%cCharacter match bonus: +1 (char: ${queryLower[queryIndex]} at index ${targetIndex}, total score: ${score})`, 'font-weight: normal'); + // } - // Fill into positions array - matchingPositions.push(indexOfQueryInTarget); + // Consecutive match bonus + if (matchesSequenceLength > 0) { + score += (matchesSequenceLength * 5); - // Character match bonus + // if (DEBUG) { + // console.log('Consecutive match bonus: ' + (matchesSequenceLength * 5)); + // } + } + + // Same case bonus + if (query[queryIndex] === target[targetIndex]) { score += 1; - // console.groupCollapsed(`%cCharacter match bonus: +1 (char: ${query[index]} at index ${indexOf}, total score: ${score})`, 'font-weight: normal'); - - // Consecutive match bonus - if (targetIndex === indexOfQueryInTarget && queryIndex > 0) { - score += 5; - - // console.log('Consecutive match bonus: +5'); - } - - // Same case bonus - if (target[indexOfQueryInTarget] === query[queryIndex]) { - score += 1; - - // console.log('Same case bonus: +1'); - } - - // Start of word bonus - if (indexOfQueryInTarget === 0) { - score += 8; - - // console.log('Start of word bonus: +8'); - } - - // After separator bonus - else if (isSeparatorAtPos(target, indexOfQueryInTarget - 1)) { - score += 7; - - // console.log('After separtor bonus: +7'); - } - - // Inside word upper case bonus - else if (isUpper(target.charCodeAt(indexOfQueryInTarget))) { - score += 1; - - // console.log('Inside word upper case bonus: +1'); - } - - // console.groupEnd(); - - targetIndex = indexOfQueryInTarget + 1; - queryIndex++; + // if (DEBUG) { + // console.log('Same case bonus: +1'); + // } } - const res: Score = (score > 0) ? [score, matchingPositions] : NO_SCORE; + // Start of word bonus + if (targetIndex === 0) { + score += 8; - // console.log(`%cFinal Score: ${score}`, 'font-weight: bold'); - // console.groupEnd(); + // if (DEBUG) { + // console.log('Start of word bonus: +8'); + // } + } - return res; + // After separator bonus + else if (isSeparatorAtPos(target, targetIndex - 1)) { + score += 4; + + // if (DEBUG) { + // console.log('After separtor bonus: +4'); + // } + } + + // Inside word upper case bonus + else if (isUpper(target.charCodeAt(targetIndex))) { + score += 1; + + // if (DEBUG) { + // console.log('Inside word upper case bonus: +1'); + // } + } + + // if (DEBUG) { + // console.groupEnd(); + // } + + return score; } -/*! -END THIRD PARTY -*/ +// function printMatrix(query: string, target: string, matches: number[], scores: number[]): void { +// console.log('\t' + target.split('').join('\t')); +// for (let queryIndex = 0; queryIndex < query.length; queryIndex++) { +// let line = query[queryIndex] + '\t'; +// for (let targetIndex = 0; targetIndex < target.length; targetIndex++) { +// const currentIndex = queryIndex * target.length + targetIndex; +// line = line + 'M' + matches[currentIndex] + '/' + 'S' + scores[currentIndex] + '\t'; +// } + +// console.log(line); +// } +// } /** * Scoring on structural items that have a label and optional description. @@ -315,7 +353,7 @@ function doScoreItem(label: string, description: string, path: string, query: } // 4.) prefer scores on the label if any - const [labelScore, labelPositions] = _doScore(label, query.value, query.lowercase, fuzzy); + const [labelScore, labelPositions] = score(label, query.value, query.lowercase, fuzzy); if (labelScore) { return { score: labelScore + LABEL_SCORE_THRESHOLD, labelMatch: createMatches(labelPositions) }; } @@ -331,7 +369,7 @@ function doScoreItem(label: string, description: string, path: string, query: const descriptionPrefixLength = descriptionPrefix.length; const descriptionAndLabel = `${descriptionPrefix}${label}`; - const [labelDescriptionScore, labelDescriptionPositions] = _doScore(descriptionAndLabel, query.value, query.lowercase, fuzzy); + const [labelDescriptionScore, labelDescriptionPositions] = score(descriptionAndLabel, query.value, query.lowercase, fuzzy); if (labelDescriptionScore) { const labelDescriptionMatches = createMatches(labelDescriptionPositions); const labelMatch: IMatch[] = []; diff --git a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts index 877f8a0caa0..b8b1fc11ca9 100644 --- a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts +++ b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts @@ -44,7 +44,7 @@ class NullAccessorClass implements scorer.IItemAccessor { } function _doScore(target: string, query: string, fuzzy: boolean): scorer.Score { - return scorer._doScore(target, query, query.toLowerCase(), fuzzy); + return scorer.score(target, query, query.toLowerCase(), fuzzy); } function scoreItem(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache): scorer.IItemScore { @@ -209,6 +209,18 @@ suite('Quick Open Scorer', () => { assert.equal(pathRes.descriptionMatch[0].end, 26); }); + test('scoreItem - avoid match scattering (bug #36119)', function () { + const resource = URI.file('projects/ui/cula/ats/target.mk');; + + const pathRes = scoreItem(resource, 'tcltarget.mk', true, ResourceAccessor, cache); + assert.ok(pathRes.score); + assert.ok(pathRes.descriptionMatch); + assert.ok(pathRes.labelMatch); + assert.equal(pathRes.labelMatch.length, 1); + assert.equal(pathRes.labelMatch[0].start, 0); + assert.equal(pathRes.labelMatch[0].end, 9); + }); + test('scoreItem - prefers more compact matches', function () { const resource = URI.file('/1a111d1/11a1d1/something.txt'); @@ -541,13 +553,19 @@ suite('Quick Open Scorer', () => { let res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceC); + res = [resourceC, resourceB, resourceA, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceC); + query = isWindows ? 'un1\\index.js' : 'un1/index.js'; res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); + + res = [resourceC, resourceB, resourceA, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); }); - test('compareFilesByScore - avoid match scattering (bug #21019)', function () { + test('compareFilesByScore - avoid match scattering (bug #21019 1.)', function () { const resourceA = URI.file('app/containers/Services/NetworkData/ServiceDetails/ServiceLoad/index.js'); const resourceB = URI.file('app/containers/Services/NetworkData/ServiceDetails/ServiceDistribution/index.js'); const resourceC = URI.file('app/containers/Services/NetworkData/ServiceDetailTabs/ServiceTabs/StatVideo/index.js'); @@ -556,6 +574,22 @@ suite('Quick Open Scorer', () => { let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceC); + + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceC); + }); + + test('compareFilesByScore - avoid match scattering (bug #21019 2.)', function () { + const resourceA = URI.file('src/build-helper/store/redux.ts'); + const resourceB = URI.file('src/repository/store/redux.ts'); + + let query = 'reproreduxts'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); }); test('compareFilesByScore - avoid match scattering (bug #26649)', function () { @@ -567,6 +601,9 @@ suite('Quick Open Scorer', () => { let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceC); + + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceC); }); test('compareFilesByScore - avoid match scattering (bug #33247)', function () { @@ -577,6 +614,9 @@ suite('Quick Open Scorer', () => { let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); }); test('compareFilesByScore - avoid match scattering (bug #33247 comment)', function () { @@ -587,6 +627,40 @@ suite('Quick Open Scorer', () => { let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + + test('compareFilesByScore - avoid match scattering (bug #36166)', function () { + const resourceA = URI.file('django/contrib/sites/locale/ga/LC_MESSAGES/django.mo'); + const resourceB = URI.file('django/core/signals.py'); + + let query = 'djancosig'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + + test('compareFilesByScore - avoid match scattering (bug #32918)', function () { + const resourceA = URI.file('adsys/protected/config.php'); + const resourceB = URI.file('adsys/protected/framework/smarty/sysplugins/smarty_internal_config.php'); + const resourceC = URI.file('duowanVideo/wap/protected/config.php'); + + let query = 'protectedconfig.php'; + + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceA); + assert.equal(res[1], resourceC); + assert.equal(res[2], resourceB); + + res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceA); + assert.equal(res[1], resourceC); + assert.equal(res[2], resourceB); }); test('compareFilesByScore - prefer shorter hit (bug #20546)', function () { @@ -597,6 +671,23 @@ suite('Quick Open Scorer', () => { let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + + test('compareFilesByScore - avoid match scattering (bug #12095)', function () { + const resourceA = URI.file('src/vs/workbench/parts/files/common/explorerViewModel.ts'); + const resourceB = URI.file('src/vs/workbench/parts/files/browser/views/explorerView.ts'); + const resourceC = URI.file('src/vs/workbench/parts/files/browser/views/explorerViewer.ts'); + + let query = 'filesexplorerview.ts'; + + let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceA, resourceC, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); }); test('prepareSearchForScoring', function () { From aadf9940769a6a4725f2c4bd4891ee5bc66d0325 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 11:54:16 +0200 Subject: [PATCH 292/394] remove unused file --- src/vs/base/common/OSSREADME.json | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 src/vs/base/common/OSSREADME.json diff --git a/src/vs/base/common/OSSREADME.json b/src/vs/base/common/OSSREADME.json deleted file mode 100644 index e6948b8a57b..00000000000 --- a/src/vs/base/common/OSSREADME.json +++ /dev/null @@ -1,30 +0,0 @@ -// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS: -[{ - "name": "string_scorer", - "version": "0.1.20", - "license": "MIT", - "repositoryURL": "https://github.com/joshaven/string_score", - "description": "The file quickOpenScorer.ts was inspired by the string_score algorithm from Joshaven Potter.", - "licenseDetail": [ - "This software is released under the MIT license:", - "", - "Copyright (c) Joshaven Potter", - "", - "Permission is hereby granted, free of charge, to any person obtaining a copy of", - "this software and associated documentation files (the \"Software\"), to deal in", - "the Software without restriction, including without limitation the rights to", - "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of", - "the Software, and to permit persons to whom the Software is furnished to do so,", - "subject to the following conditions:", - "", - "The above copyright notice and this permission notice shall be included in all", - "copies or substantial portions of the Software.", - "", - "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", - "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS", - "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR", - "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER", - "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", - "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." - ] -}] From d796f8e9613078a0d7f770a0261ae9aed3d8c641 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 12:02:13 +0200 Subject: [PATCH 293/394] composite bar: fix drag and drop colors --- .../parts/compositebar/compositeBarActions.ts | 2 +- src/vs/workbench/common/theme.ts | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 5971250d6ff..ff0a1d4422b 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -130,7 +130,7 @@ export class ActivityActionItem extends BaseActionItem { const theme = this.themeService.getTheme(); // Label - if (this.$label) { + if (this.$label && this.options.icon) { const background = theme.getColor(this.options.colors.backgroundColor); this.$label.style('background-color', background ? background.toString() : null); diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 8bfcf69c9fe..7aaa6c71af5 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -108,12 +108,6 @@ export const EDITOR_DRAG_AND_DROP_BACKGROUND = registerColor('editorGroup.dropBa // < --- Panels --- > -const DRAG_AND_DROP_BACKGROUND = { - dark: Color.white.transparent(0.12), - light: Color.white.transparent(0.12), - hc: Color.white.transparent(0.12), -}; - export const PANEL_BACKGROUND = registerColor('panel.background', { dark: editorBackground, light: editorBackground, @@ -144,7 +138,11 @@ export const PANEL_ACTIVE_TITLE_BORDER = registerColor('panelTitle.activeBorder' hc: contrastBorder }, nls.localize('panelActiveTitleBorder', "Border color for the active panel title. Panels are shown below the editor area and contain views like output and integrated terminal.")); -export const PANEL_DRAG_AND_DROP_BACKGROUND = registerColor('panel.dropBackground', DRAG_AND_DROP_BACKGROUND, nls.localize('panelDragAndDropBackground', "Drag and drop feedback color for the panel title items. The color should have transparency so that the panel entries can still shine through. Panels are shown below the editor area and contain views like output and integrated terminal.")); +export const PANEL_DRAG_AND_DROP_BACKGROUND = registerColor('panel.dropBackground', { + dark: Color.white.transparent(0.12), + light: Color.fromHex('#3399FF').transparent(0.18), + hc: Color.white.transparent(0.12) +}, nls.localize('panelDragAndDropBackground', "Drag and drop feedback color for the panel title items. The color should have transparency so that the panel entries can still shine through. Panels are shown below the editor area and contain views like output and integrated terminal.")); // < --- Status --- > @@ -232,7 +230,11 @@ export const ACTIVITY_BAR_BORDER = registerColor('activityBar.border', { }, nls.localize('activityBarBorder', "Activity bar border color separating to the side bar. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); -export const ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND = registerColor('activityBar.dropBackground', DRAG_AND_DROP_BACKGROUND, nls.localize('activityBarDragAndDropBackground', "Drag and drop feedback color for the activity bar items. The color should have transparency so that the activity bar entries can still shine through. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); +export const ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND = registerColor('activityBar.dropBackground', { + dark: Color.white.transparent(0.12), + light: Color.white.transparent(0.12), + hc: Color.white.transparent(0.12), +}, nls.localize('activityBarDragAndDropBackground', "Drag and drop feedback color for the activity bar items. The color should have transparency so that the activity bar entries can still shine through. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); export const ACTIVITY_BAR_BADGE_BACKGROUND = registerColor('activityBarBadge.background', { dark: '#007ACC', From 6bd308077f777fb78cbed66fe98e77628627b289 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Oct 2017 12:01:32 +0200 Subject: [PATCH 294/394] Tests for #36625 --- .../test/common/configurationModels.test.ts | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/vs/platform/configuration/test/common/configurationModels.test.ts b/src/vs/platform/configuration/test/common/configurationModels.test.ts index 598b7d6d616..eadf6dd928e 100644 --- a/src/vs/platform/configuration/test/common/configurationModels.test.ts +++ b/src/vs/platform/configuration/test/common/configurationModels.test.ts @@ -198,47 +198,44 @@ suite('ConfigurationModel', () => { }); test('simple merge', () => { - let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); - let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); + let base = new ConfigurationModel({ 'a': 1, 'b': 2 }, ['a', 'b']); + let add = new ConfigurationModel({ 'a': 3, 'c': 4 }, ['a', 'c']); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 }); + assert.deepEqual(result.keys, ['a', 'b', 'c']); }); test('recursive merge', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }); + let base = new ConfigurationModel({ 'a': { 'b': 1 } }, ['a.b']); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, ['a.b']); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); assert.deepEqual(result.getSectionContents('a'), { 'b': 2 }); + assert.deepEqual(result.keys, ['a.b']); }); test('simple merge overrides', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 } }, [], [{ identifiers: ['c'], contents: { 'a': 2 } }]); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'b': 2 } }]); + let base = new ConfigurationModel({ 'a': { 'b': 1 } }, ['a.b'], [{ identifiers: ['c'], contents: { 'a': 2 } }]); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, ['a.b'], [{ identifiers: ['c'], contents: { 'b': 2 } }]); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': { 'b': 2 } }); assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': 2, 'b': 2 } }]); assert.deepEqual(result.override('c').contents, { 'a': 2, 'b': 2 }); + assert.deepEqual(result.keys, ['a.b']); }); test('recursive merge overrides', () => { - let base = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, [], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); - let add = new ConfigurationModel({ 'a': { 'b': 2 } }, [], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]); + let base = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, ['a.b', 'f'], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]); + let add = new ConfigurationModel({ 'a': { 'b': 2 } }, ['a.b'], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]); let result = base.merge(add); assert.deepEqual(result.contents, { 'a': { 'b': 2 }, 'f': 1 }); assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': { 'd': 1, 'e': 2 } } }]); assert.deepEqual(result.override('c').contents, { 'a': { 'b': 2, 'd': 1, 'e': 2 }, 'f': 1 }); - }); - - test('merge ignore keys', () => { - let base = new ConfigurationModel({ 'a': 1, 'b': 2 }); - let add = new ConfigurationModel({ 'a': 3, 'c': 4 }); - let result = base.merge(add); - assert.deepEqual(result.keys, []); + assert.deepEqual(result.keys, ['a.b', 'f']); }); test('Test contents while getting an existing property', () => { @@ -466,6 +463,35 @@ suite('ConfigurationChangeEvent', () => { assert.ok(!testObject.affectsConfiguration('files', URI.file('file2'))); }); + test('merging change events', () => { + let event1 = new ConfigurationChangeEvent().change(['window.zoomLevel', 'files']); + let event2 = new ConfigurationChangeEvent().change(['window.title'], URI.file('file1')).change(['[markdown]']); + + let actual = event1.change(event2); + + assert.deepEqual(actual.affectedKeys, ['window.zoomLevel', 'files', '[markdown]', 'window.title']); + + assert.ok(actual.affectsConfiguration('window.zoomLevel')); + assert.ok(actual.affectsConfiguration('window.zoomLevel', URI.file('file1'))); + assert.ok(actual.affectsConfiguration('window.zoomLevel', URI.file('file2'))); + + assert.ok(actual.affectsConfiguration('window')); + assert.ok(actual.affectsConfiguration('window', URI.file('file1'))); + assert.ok(actual.affectsConfiguration('window', URI.file('file2'))); + + assert.ok(actual.affectsConfiguration('files')); + assert.ok(actual.affectsConfiguration('files', URI.file('file1'))); + assert.ok(actual.affectsConfiguration('files', URI.file('file2'))); + + assert.ok(actual.affectsConfiguration('window.title')); + assert.ok(actual.affectsConfiguration('window.title', URI.file('file1'))); + assert.ok(!actual.affectsConfiguration('window.title', URI.file('file2'))); + + assert.ok(actual.affectsConfiguration('[markdown]')); + assert.ok(actual.affectsConfiguration('[markdown]', URI.file('file1'))); + assert.ok(actual.affectsConfiguration('[markdown]', URI.file('file2'))); + }); + }); suite('AllKeysConfigurationChangeEvent', () => { From a1fcd4acfc0b4eae83c3508390c542baa9efeba3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Oct 2017 12:02:41 +0200 Subject: [PATCH 295/394] Fix #36625 --- src/vs/platform/configuration/common/configurationModels.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index f8c58ea3689..98a195affaa 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -104,6 +104,7 @@ export class ConfigurationModel implements IConfigurationModel { } } source._overrides = overrides; + source._keys = arrays.distinct([...source._keys, ...target.keys]); } private getContentsForOverrideIdentifer(identifier: string): any { @@ -534,7 +535,7 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i change(arg1: any, arg2?: any): ConfigurationChangeEvent { if (arg1 instanceof ConfigurationChangeEvent) { this._changedConfiguration = this._changedConfiguration.merge(arg1._changedConfiguration); - for (const resource of this.changedConfigurationByResource.keys()) { + for (const resource of arg1._changedConfigurationByResource.keys()) { let changedConfigurationByResource = this.getOrSetChangedConfigurationForResource(resource); changedConfigurationByResource = changedConfigurationByResource.merge(arg1._changedConfigurationByResource.get(resource)); this._changedConfigurationByResource.set(resource, changedConfigurationByResource); From bd7334b008461011af7cd89fe4144b288d8c81a0 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 12:13:37 +0200 Subject: [PATCH 296/394] CompositeBar: fix ellipses in the dark theme --- src/vs/workbench/browser/parts/panel/media/panelpart.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index 6861914b5c2..5c8a810d556 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -107,4 +107,9 @@ .vs-dark .monaco-workbench .hide-panel-action, .hc-black .monaco-workbench .hide-panel-action { background: url('close-inverse.svg') center center no-repeat; -} \ No newline at end of file +} + +.vs-dark .monaco-workbench > .part.panel .composite-bar > .monaco-action-bar .action-label.toggle-more, +.hc-black .monaco-workbench > .part.panel .composite-bar > .monaco-action-bar .action-label.toggle-more { + background: url('ellipsis-inverse.svg') center center no-repeat; +} From 8ce940f33d35c737e1a4f07af0579f9722f65b8a Mon Sep 17 00:00:00 2001 From: Brandon Bloom Date: Fri, 20 Oct 2017 03:18:51 -0700 Subject: [PATCH 297/394] Fixes #36544. (#36578) --- src/vs/workbench/services/history/browser/history.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 6b3a56407ef..96778df112d 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -572,15 +572,16 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic this.stack = this.stack.slice(0, this.index + 1); } - this.setIndex(this.index + 1); - this.stack.splice(this.index, 0, entry); + this.stack.splice(this.index + 1, 0, entry); // Check for limit if (this.stack.length > HistoryService.MAX_STACK_ITEMS) { this.stack.shift(); // remove first and dispose - if (this.index > 0) { - this.setIndex(this.index - 1); + if (this.lastIndex >= 0) { + this.lastIndex--; } + } else { + this.setIndex(this.index + 1); } } From 33eb2e7644c1d63a01b08f5e60053d89070ef3d5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 12:31:07 +0200 Subject: [PATCH 298/394] set files.useExperimentalFileWatcher to true by default --- src/vs/workbench/parts/files/browser/files.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/browser/files.contribution.ts b/src/vs/workbench/parts/files/browser/files.contribution.ts index 878dea1810b..12d38ec1aa7 100644 --- a/src/vs/workbench/parts/files/browser/files.contribution.ts +++ b/src/vs/workbench/parts/files/browser/files.contribution.ts @@ -276,7 +276,7 @@ configurationRegistry.registerConfiguration({ }, 'files.useExperimentalFileWatcher': { 'type': 'boolean', - 'default': false, + 'default': true, 'description': nls.localize('useExperimentalFileWatcher', "Use the new experimental file watcher.") }, 'files.defaultLanguage': { From f2d47bcc49f69310f5b27e0419a69409a3cc0e9a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 13:07:50 +0200 Subject: [PATCH 299/394] Improve message --- src/vs/editor/contrib/find/browser/findWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index 726c2451eef..7cb6a00b5f0 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -48,7 +48,7 @@ const NLS_REPLACE_INPUT_PLACEHOLDER = nls.localize('placeholder.replace', "Repla const NLS_REPLACE_BTN_LABEL = nls.localize('label.replaceButton', "Replace"); const NLS_REPLACE_ALL_BTN_LABEL = nls.localize('label.replaceAllButton', "Replace All"); const NLS_TOGGLE_REPLACE_MODE_BTN_LABEL = nls.localize('label.toggleReplaceButton', "Toggle Replace mode"); -const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Only the first 999 results are highlighted, but all find operations work on the entire text."); +const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Only the first {0} results are highlighted, but all find operations work on the entire text.", MATCHES_LIMIT); const NLS_MATCHES_LOCATION = nls.localize('label.matchesLocation', "{0} of {1}"); const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results"); From 9073cc1c4d13059ef7b18a91c64cbb41022c3644 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 13:10:03 +0200 Subject: [PATCH 300/394] Bump find limit to 20k given all the perf work around decorations --- src/vs/editor/contrib/find/common/findModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 1816df33d59..dda6ca2f533 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -67,7 +67,7 @@ export const FIND_IDS = { ShowNextFindTermAction: 'find.history.showNext' }; -export const MATCHES_LIMIT = 999; +export const MATCHES_LIMIT = 19999; export class FindModelBoundToEditorModel { From 93157c291bc55e901c81e05dc1d8e93fad9104a7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 13:26:22 +0200 Subject: [PATCH 301/394] Avoid flickering by painting the overview ruler with colors in the same order --- .../viewParts/overviewRuler/decorationsOverviewRuler2.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts index 288c6803f2b..1ed0e160f44 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts @@ -314,7 +314,13 @@ export class DecorationsOverviewRuler2 extends ViewPart { const x = this._settings.x; const w = this._settings.w; - for (let color in decorations) { + // Avoid flickering by always rendering the colors in the same order + // colors that don't use transparency will be sorted last (they start with #) + const colors = Object.keys(decorations); + colors.sort(); + for (let cIndex = 0, cLen = colors.length; cIndex < cLen; cIndex++) { + const color = colors[cIndex]; + const colorDecorations = decorations[color]; canvasCtx.fillStyle = color; From b45c8b857898fee4422a730f840caaa1452e8e93 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 13:27:53 +0200 Subject: [PATCH 302/394] Renames --- src/vs/editor/browser/view/viewImpl.ts | 4 ++-- ...corationsOverviewRuler2.ts => decorationsOverviewRuler.ts} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/vs/editor/browser/viewParts/overviewRuler/{decorationsOverviewRuler2.ts => decorationsOverviewRuler.ts} (99%) diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 8e14fe9b1ff..1a53e3d9814 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -30,7 +30,7 @@ import { Margin } from 'vs/editor/browser/viewParts/margin/margin'; import { LinesDecorationsOverlay } from 'vs/editor/browser/viewParts/linesDecorations/linesDecorations'; import { MarginViewLineDecorationsOverlay } from 'vs/editor/browser/viewParts/marginDecorations/marginDecorations'; import { ViewOverlayWidgets } from 'vs/editor/browser/viewParts/overlayWidgets/overlayWidgets'; -import { DecorationsOverviewRuler2 } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2'; +import { DecorationsOverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler'; import { OverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/overviewRuler'; import { Rulers } from 'vs/editor/browser/viewParts/rulers/rulers'; import { ScrollDecorationViewPart } from 'vs/editor/browser/viewParts/scrollDecoration/scrollDecoration'; @@ -170,7 +170,7 @@ export class View extends ViewEventHandler { this.viewParts.push(this.viewZones); // Decorations overview ruler - let decorationsOverviewRuler = new DecorationsOverviewRuler2(this._context); + let decorationsOverviewRuler = new DecorationsOverviewRuler(this._context); this.viewParts.push(decorationsOverviewRuler); diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts similarity index 99% rename from src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts rename to src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 1ed0e160f44..5add770087e 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler2.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -193,7 +193,7 @@ const enum OverviewRulerLane { Full = 7 } -export class DecorationsOverviewRuler2 extends ViewPart { +export class DecorationsOverviewRuler extends ViewPart { private readonly _tokensColorTrackerListener: IDisposable; private readonly _domNode: FastDomNode; From 3c2db906995a6f982cc1fffcf3ff0ce8f8da49d4 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 13:31:49 +0200 Subject: [PATCH 303/394] More overflow checks --- src/vs/editor/common/model/intervalTree.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 8e5e123164a..676eaa9a309 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -69,6 +69,13 @@ const enum Constants { * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values */ MIN_SAFE_DELTA = -(1 << 30), + /** + * MAX SMI (SMall Integer) as defined in v8. + * one bit is lost for boxing/unboxing flag. + * one bit is lost for sign flag. + * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values + */ + MAX_SAFE_DELTA = 1 << 30, } function getNodeColor(node: IntervalNode): NodeColor { @@ -617,7 +624,7 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt node.start += editDelta; node.end += editDelta; node.delta += editDelta; - if (node.delta < Constants.MIN_SAFE_DELTA) { + if (node.delta < Constants.MIN_SAFE_DELTA || node.delta > Constants.MAX_SAFE_DELTA) { T.requestNormalizeDelta = true; } // cover case a) from above @@ -1025,7 +1032,7 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { // x's delta is no longer influenced by z's delta x.delta += z.delta; - if (x.delta < Constants.MIN_SAFE_DELTA) { + if (x.delta < Constants.MIN_SAFE_DELTA || x.delta > Constants.MAX_SAFE_DELTA) { T.requestNormalizeDelta = true; } x.start += z.delta; @@ -1045,14 +1052,14 @@ function rbTreeDelete(T: IntervalTree, z: IntervalNode): void { x.start += y.delta; x.end += y.delta; x.delta += y.delta; - if (x.delta < Constants.MIN_SAFE_DELTA) { + if (x.delta < Constants.MIN_SAFE_DELTA || x.delta > Constants.MAX_SAFE_DELTA) { T.requestNormalizeDelta = true; } y.start += z.delta; y.end += z.delta; y.delta = z.delta; - if (y.delta < Constants.MIN_SAFE_DELTA) { + if (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) { T.requestNormalizeDelta = true; } } @@ -1215,7 +1222,7 @@ function leftRotate(T: IntervalTree, x: IntervalNode): void { const y = x.right; // set y. y.delta += x.delta; // y's delta is no longer influenced by x's delta - if (y.delta < Constants.MIN_SAFE_DELTA) { + if (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) { T.requestNormalizeDelta = true; } y.start += x.delta; @@ -1245,7 +1252,7 @@ function rightRotate(T: IntervalTree, y: IntervalNode): void { const x = y.left; y.delta -= x.delta; - if (y.delta < Constants.MIN_SAFE_DELTA) { + if (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) { T.requestNormalizeDelta = true; } y.start -= x.delta; From a0982eb0713d3fd4a944401453ddfcf80071e6ac Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 13:33:25 +0200 Subject: [PATCH 304/394] Avoid needless checks --- src/vs/editor/common/model/intervalTree.ts | 32 ++++++---------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index 676eaa9a309..c07fdd33ba2 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -399,9 +399,7 @@ function normalizeDelta(T: IntervalTree): void { node = node.parent; } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); } //#endregion @@ -569,9 +567,7 @@ function searchForEditing(T: IntervalTree, start: number, end: number): Interval } } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); return result; } @@ -643,9 +639,7 @@ function noOverlapReplace(T: IntervalTree, start: number, end: number, textLengt } } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); } //#endregion @@ -681,9 +675,7 @@ function nodeCount(T: IntervalTree): number { } } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); return count; } @@ -721,9 +713,7 @@ function collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] } } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); return result; } @@ -758,9 +748,7 @@ function collectNodesPostOrder(T: IntervalTree): IntervalNode[] { setNodeIsVisited(node, true); } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); return result; } @@ -817,9 +805,7 @@ function search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boo } } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); return result; } @@ -906,9 +892,7 @@ function intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: num } } - if (T.root) { - setNodeIsVisited(T.root, false); - } + setNodeIsVisited(T.root, false); return result; } From 3212c452e4104d08889753a2399b72359f32d00f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 14:54:30 +0200 Subject: [PATCH 305/394] Increase slow test timeout --- src/vs/editor/test/common/controller/cursor.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index e21b52a667a..8b8a9bd46c4 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -1651,7 +1651,8 @@ suite('Editor Controller - Regression tests', () => { }); }); - test('issue #23913: Greater than 1000+ multi cursor typing replacement text appears inverted, lines begin to drop off selection', () => { + test('issue #23913: Greater than 1000+ multi cursor typing replacement text appears inverted, lines begin to drop off selection', function () { + this.timeout(10000); const LINE_CNT = 2000; let text = []; From f262248124179fbd8b0f701942e2a6f31aafca4e Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 13:00:28 +0200 Subject: [PATCH 306/394] CompositeBar: fix overflow math --- .../browser/parts/activitybar/activitybarPart.ts | 3 ++- .../browser/parts/compositebar/compositeBar.ts | 11 +++++++---- src/vs/workbench/browser/parts/panel/panelPart.ts | 3 ++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index efa7e390e64..0046b57dc47 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -75,7 +75,8 @@ export class ActivitybarPart extends Part { getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), hidePart: () => this.partService.setSideBarHidden(true), - colors: ActivitybarPart.COLORS + colors: ActivitybarPart.COLORS, + overflowActionSize: 50 }); this.registerListeners(); } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 3b3a8c1570a..ef058b5ca94 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -26,6 +26,7 @@ export interface ICompositeBarOptions { orientation: ActionsOrientation; composites: { id: string, name: string }[]; colors: ICompositeBarColors; + overflowActionSize: number; getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; getOnCompositeClickAction: (compositeId: string) => Action; @@ -36,7 +37,6 @@ export interface ICompositeBarOptions { export class CompositeBar implements ICompositeBar { - private static OVERFLOW_ACTION_SIZE = 50; private _onDidContextMenu: Emitter; private dimension: Dimension; @@ -220,9 +220,12 @@ export class CompositeBar implements ICompositeBar { } overflows = compositesToShow.length > maxVisible; - compositesToShow = compositesToShow.slice(0, maxVisible); - // Check if we need to make room for the overflow action - if (overflows && (size + CompositeBar.OVERFLOW_ACTION_SIZE - this.compositeSizeInBar.get(compositesToShow[maxVisible - 1]) - this.compositeSizeInBar.get(compositesToShow[maxVisible]) > limit)) { + if (overflows) { + size -= this.compositeSizeInBar.get(compositesToShow[maxVisible]); + compositesToShow = compositesToShow.slice(0, maxVisible); + } + // Check if we need to make extra room for the overflow action + if (overflows && (size + this.options.overflowActionSize > limit)) { compositesToShow.pop(); } } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 0cb16e61349..8905ae13f69 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -84,6 +84,7 @@ export class PanelPart extends CompositePart implements IPanelService { getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(OpenPanelAction, this.getPanel(compositeId)), getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), hidePart: () => this.partService.setPanelHidden(true), + overflowActionSize: 60, colors: { backgroundColor: PANEL_BACKGROUND, badgeBackground, @@ -207,7 +208,7 @@ export class PanelPart extends CompositePart implements IPanelService { // Pass to super const sizes = super.layout(dimension); - let availableWidth = dimension.width; + let availableWidth = dimension.width - 8; // take padding into account if (this.toolBar) { // adjust height for global actions showing availableWidth -= this.toolBar.getContainer().getHTMLElement().offsetWidth; From e10e99b007e2caff0dc24617f132c4bc670b0fd9 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 13:00:40 +0200 Subject: [PATCH 307/394] fix global action background color --- .../workbench/browser/parts/activitybar/activitybarActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 6b40f9a0937..a2b0e9c3711 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -99,7 +99,7 @@ export class GlobalActivityActionItem extends ActivityActionItem { @IThemeService themeService: IThemeService, @IContextMenuService protected contextMenuService: IContextMenuService ) { - super(action, { draggable: false, colors }, themeService); + super(action, { draggable: false, colors, icon: true }, themeService); } public render(container: HTMLElement): void { From 0f0d76bf236a5edd36e6d6d80af77d3c08e4fd02 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 20 Oct 2017 13:57:55 +0200 Subject: [PATCH 308/394] [folding] Cannot read property 'getCollapseState' of undefined --- .../editor/contrib/folding/browser/folding.ts | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 105e2b4f679..90c4ed1b900 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -101,7 +101,7 @@ export class FoldingController { */ public saveViewState(): { collapsedRegions?: CollapseState, lineCount?: number } { let model = this.editor.getModel(); - if (!model) { + if (!model || !this._isEnabled) { return {}; } return { collapsedRegions: this.foldingModel.getCollapseState(), lineCount: model.getLineCount() }; @@ -112,20 +112,19 @@ export class FoldingController { */ public restoreViewState(state: { collapsedRegions?: CollapseState, lineCount?: number }): void { let model = this.editor.getModel(); - if (!model) { - return; - } - if (!this._isEnabled) { + if (!model || !this._isEnabled) { return; } if (!state || !state.collapsedRegions || state.lineCount !== model.getLineCount()) { return; } - // set the hidden ranges right way, before waiting for the folding model. + // set the hidden ranges right away, before waiting for the folding model. if (this.hiddenRangeModel.applyCollapseState(state.collapsedRegions)) { this.getFoldingModel().then(foldingModel => { - foldingModel.applyCollapseState(state.collapsedRegions); + if (foldingModel) { + foldingModel.applyCollapseState(state.collapsedRegions); + } }); } } @@ -146,16 +145,24 @@ export class FoldingController { this.localToDispose.push(this.hiddenRangeModel.onDidChange(hr => this.onHiddenRangesChanges(hr))); this.updateScheduler = new Delayer(200); - this.localToDispose.push({ dispose: () => this.updateScheduler.cancel() }); this.cursorChangedScheduler = new RunOnceScheduler(() => this.revealCursor(), 200); this.localToDispose.push(this.cursorChangedScheduler); - this.localToDispose.push(this.editor.onDidChangeModelLanguageConfiguration(e => this.onModelContentChanged())); // also covers model language changes + this.localToDispose.push(this.editor.onDidChangeModelLanguageConfiguration(e => this.onModelContentChanged())); // covers model language changes as well this.localToDispose.push(this.editor.onDidChangeModelContent(e => this.onModelContentChanged())); this.localToDispose.push(this.editor.onDidChangeCursorPosition(e => this.onCursorPositionChanged())); this.localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e))); this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e))); - + this.localToDispose.push({ + dispose: () => { + this.updateScheduler.cancel(); + this.updateScheduler = null; + this.foldingModel = null; + this.foldingModelPromise = null; + this.hiddenRangeModel = null; + this.cursorChangedScheduler = null; + } + }); this.onModelContentChanged(); } @@ -176,7 +183,9 @@ export class FoldingController { private onModelContentChanged() { this.foldingModelPromise = this.updateScheduler.trigger(() => { - this.foldingModel.update(this.computeRanges()); + if (this.foldingModel) { // null if editor has been disposed, or folding turned off + this.foldingModel.update(this.computeRanges()); + } return this.foldingModel; }); } @@ -196,16 +205,19 @@ export class FoldingController { } private revealCursor() { - this.getFoldingModel().then(foldingModel => { - let selections = this.editor.getSelections(); - for (let selection of selections) { - let lineNumber = selection.selectionStartLineNumber; - if (this.hiddenRangeModel.isHidden(lineNumber)) { - let toToggle = foldingModel.getAllRegionsAtLine(lineNumber, r => r.isCollapsed && lineNumber > r.range.startLineNumber); - foldingModel.toggleCollapseState(toToggle); + this.getFoldingModel().then(foldingModel => { // null is returned if folding got disabled in the meantime + if (foldingModel) { + let selections = this.editor.getSelections(); + for (let selection of selections) { + let lineNumber = selection.selectionStartLineNumber; + if (this.hiddenRangeModel.isHidden(lineNumber)) { + let toToggle = foldingModel.getAllRegionsAtLine(lineNumber, r => r.isCollapsed && lineNumber > r.range.startLineNumber); + foldingModel.toggleCollapseState(toToggle); + } } } }); + } private mouseDownInfo: { lineNumber: number, iconClicked: boolean }; @@ -283,13 +295,14 @@ export class FoldingController { } this.getFoldingModel().then(foldingModel => { - let region = foldingModel.getRegionAtLine(lineNumber); - if (region) { - if (iconClicked || region.isCollapsed) { - foldingModel.toggleCollapseState([region]); - this.reveal(lineNumber); + if (foldingModel) { + let region = foldingModel.getRegionAtLine(lineNumber); + if (region) { + if (iconClicked || region.isCollapsed) { + foldingModel.toggleCollapseState([region]); + this.reveal(lineNumber); + } } - return; } }); } @@ -310,7 +323,9 @@ abstract class FoldingAction extends EditorAction { } this.reportTelemetry(accessor, editor); return foldingController.getFoldingModel().then(foldingModel => { - this.invoke(foldingController, foldingModel, editor, args); + if (foldingModel) { + this.invoke(foldingController, foldingModel, editor, args); + } }); } From c107b0865ee7b07fc8ff8679ac2c26e13f5f6578 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 20 Oct 2017 14:00:31 +0200 Subject: [PATCH 309/394] [folding] CollapseState -> CollapseMemento --- src/vs/editor/contrib/folding/browser/folding.ts | 12 ++++++------ src/vs/editor/contrib/folding/common/foldingModel.ts | 8 ++++---- .../contrib/folding/common/hiddenRangeModel.ts | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 90c4ed1b900..e9f50ac58f7 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -17,7 +17,7 @@ import { ICommonCodeEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { editorAction, ServicesAccessor, EditorAction, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; -import { FoldingModel, setCollapseStateAtLevel, setCollapseStateDown, CollapseState, setCollapseStateLevelsDown, setCollapseStateLevelsUp } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingModel, setCollapseStateAtLevel, setCollapseStateDown, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp } from 'vs/editor/contrib/folding/common/foldingModel'; import { computeRanges, limitByIndent } from 'vs/editor/contrib/folding/common/indentFoldStrategy'; import { FoldingDecorationProvider } from './foldingDecorations'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -99,18 +99,18 @@ export class FoldingController { /** * Store view state. */ - public saveViewState(): { collapsedRegions?: CollapseState, lineCount?: number } { + public saveViewState(): { collapsedRegions?: CollapseMemento, lineCount?: number } { let model = this.editor.getModel(); if (!model || !this._isEnabled) { return {}; } - return { collapsedRegions: this.foldingModel.getCollapseState(), lineCount: model.getLineCount() }; + return { collapsedRegions: this.foldingModel.getMemento(), lineCount: model.getLineCount() }; } /** * Restore view state. */ - public restoreViewState(state: { collapsedRegions?: CollapseState, lineCount?: number }): void { + public restoreViewState(state: { collapsedRegions?: CollapseMemento, lineCount?: number }): void { let model = this.editor.getModel(); if (!model || !this._isEnabled) { return; @@ -120,10 +120,10 @@ export class FoldingController { } // set the hidden ranges right away, before waiting for the folding model. - if (this.hiddenRangeModel.applyCollapseState(state.collapsedRegions)) { + if (this.hiddenRangeModel.applyMemento(state.collapsedRegions)) { this.getFoldingModel().then(foldingModel => { if (foldingModel) { - foldingModel.applyCollapseState(state.collapsedRegions); + foldingModel.applyMemento(state.collapsedRegions); } }); } diff --git a/src/vs/editor/contrib/folding/common/foldingModel.ts b/src/vs/editor/contrib/folding/common/foldingModel.ts index 08f77e32227..61429293e21 100644 --- a/src/vs/editor/contrib/folding/common/foldingModel.ts +++ b/src/vs/editor/contrib/folding/common/foldingModel.ts @@ -32,7 +32,7 @@ export interface FoldingModelChangeEvent { collapseStateChanged?: FoldingRegion[]; } -export type CollapseState = ILineRange[]; +export type CollapseMemento = ILineRange[]; export class FoldingModel { private _textModel: IModel; @@ -137,9 +137,9 @@ export class FoldingModel { } /** - * Collapse state, for persistence only + * Collapse state memento, for persistence only */ - public getCollapseState(): CollapseState { + public getMemento(): CollapseMemento { let collapsedRanges: ILineRange[] = []; for (let region of this._regions) { if (region.isCollapsed && region.editorDecorationId) { @@ -160,7 +160,7 @@ export class FoldingModel { /** * Apply persisted state, for persistence only */ - public applyCollapseState(state: CollapseState) { + public applyMemento(state: CollapseMemento) { if (!Array.isArray(state)) { return; } diff --git a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts index 2d199a6ff86..aee78bfc692 100644 --- a/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts +++ b/src/vs/editor/contrib/folding/common/hiddenRangeModel.ts @@ -5,7 +5,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Range, IRange } from 'vs/editor/common/core/range'; -import { FoldingRegion, FoldingModel, IFoldingRange, CollapseState } from 'vs/editor/contrib/folding/common/foldingModel'; +import { FoldingRegion, FoldingModel, IFoldingRange, CollapseMemento } from 'vs/editor/contrib/folding/common/foldingModel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Selection } from 'vs/editor/common/core/selection'; import { findFirst } from 'vs/base/common/arrays'; @@ -56,7 +56,7 @@ export class HiddenRangeModel { } } - public applyCollapseState(state: CollapseState): boolean { + public applyMemento(state: CollapseMemento): boolean { if (!Array.isArray(state) || state.length === 0) { return false; } From 057714ea5cd35d22b7c329eb34e4613adcb61f27 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 15:15:34 +0200 Subject: [PATCH 310/394] SelectionHighlighter should not highlight the exact same matches as the find widget --- .../contrib/find/common/findController.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 09536d1f5f8..43ea3992e68 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -1038,6 +1038,23 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd } } + // Return early if the find widget shows the exact same matches + if (findState.isRevealed) { + let findStateSearchString = findState.searchString; + if (!caseSensitive) { + findStateSearchString = findStateSearchString.toLowerCase(); + } + + let mySearchString = r.searchText; + if (!caseSensitive) { + mySearchString = mySearchString.toLowerCase(); + } + + if (findStateSearchString === mySearchString && r.matchCase === findState.matchCase && r.wholeWord === findState.wholeWord && !findState.isRegex) { + return null; + } + } + return new SelectionHighlighterState(lastWordUnderCursor, r.searchText, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null); } From 38a2154d777820ef4a307ada2290ce2d490f7f97 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 15:17:03 +0200 Subject: [PATCH 311/394] CompositeBar: Do not layout if not visible. Otherwise the size measurment would be computed wrongly --- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index ef058b5ca94..249698bbaee 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -424,6 +424,11 @@ export class CompositeBar implements ICompositeBar { public layout(dimension: Dimension): void { this.dimension = dimension; + if (dimension.height === 0 || dimension.width === 0) { + // Do not layout if not visible. Otherwise the size measurment would be computed wrongly + return; + } + if (this.compositeSizeInBar.size === 0) { // Compute size of each composite by getting the size from the css renderer // Size is later used for overflow computation From f53f4d9f17fe493e12d0446c906a26d96750575e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 15:22:41 +0200 Subject: [PATCH 312/394] introduce a new command for #26977 --- src/vs/workbench/browser/parts/quickopen/quickopen.ts | 9 +++++++++ .../terminal/electron-browser/terminal.contribution.ts | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/quickopen/quickopen.ts b/src/vs/workbench/browser/parts/quickopen/quickopen.ts index 4b0331d645c..9138bb4c03c 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickopen.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickopen.ts @@ -29,6 +29,15 @@ CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: Servic }); }); +export const QUICKOPEN_FOCUS_SECONDARY_ACTION_ID = 'workbench.action.quickOpenPreviousEditor'; +CommandsRegistry.registerCommand(QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, function (accessor: ServicesAccessor, prefix: string = null) { + const quickOpenService = accessor.get(IQuickOpenService); + + return quickOpenService.show(null, { autoFocus: { autoFocusSecondEntry: true } }).then(() => { + return void 0; + }); +}); + export class BaseQuickOpenNavigateAction extends Action { constructor( diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index 184802fb0da..d0771e15cb5 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -30,7 +30,7 @@ import { OpenNextRecentlyUsedEditorInGroupAction, OpenPreviousRecentlyUsedEditor import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { registerColors } from './terminalColorRegistry'; import { NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction } from 'vs/workbench/electron-browser/actions'; -import { QUICKOPEN_ACTION_ID, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen'; +import { QUICKOPEN_ACTION_ID, getQuickNavigateHandler, QUICKOPEN_FOCUS_SECONDARY_ACTION_ID } from 'vs/workbench/browser/parts/quickopen/quickopen'; import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -185,6 +185,7 @@ configurationRegistry.registerConfiguration({ ToggleTabFocusModeAction.ID, FocusActiveGroupAction.ID, QUICKOPEN_ACTION_ID, + QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, ShowAllCommandsAction.ID, CreateNewTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.ID, From 6186155cf280b9fc4aca76b20c6c323b70ecbca3 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 15:25:08 +0200 Subject: [PATCH 313/394] CompositeBar: relayout on panel open since different panels have different action bar width --- .../browser/parts/panel/panelPart.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 8905ae13f69..d614edb1810 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -41,6 +41,7 @@ export class PanelPart extends CompositePart implements IPanelService { private blockOpeningPanel: boolean; private compositeBar: CompositeBar; + private dimension: Dimension; constructor( id: string, @@ -100,7 +101,11 @@ export class PanelPart extends CompositePart implements IPanelService { private registerListeners(): void { // Activate panel action on opening of a panel - this.toUnbind.push(this.onDidPanelOpen(panel => this.compositeBar.activateComposite(panel.getId()))); + this.toUnbind.push(this.onDidPanelOpen(panel => { + this.compositeBar.activateComposite(panel.getId()); + // Need to relayout composite bar since different panels have different action bar width + this.layoutCompositeBar(); + })); // Deactivate panel action on close this.toUnbind.push(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId()))); @@ -208,14 +213,19 @@ export class PanelPart extends CompositePart implements IPanelService { // Pass to super const sizes = super.layout(dimension); - let availableWidth = dimension.width - 8; // take padding into account + this.dimension = dimension; + this.layoutCompositeBar(); + + return sizes; + } + + private layoutCompositeBar(): void { + let availableWidth = this.dimension.width - 8; // take padding into account if (this.toolBar) { // adjust height for global actions showing availableWidth -= this.toolBar.getContainer().getHTMLElement().offsetWidth; } - this.compositeBar.layout(new Dimension(availableWidth, dimension.height)); - - return sizes; + this.compositeBar.layout(new Dimension(availableWidth, this.dimension.height)); } public shutdown(): void { From 2e5f49fe671a0be482bd72e6040c7904239bbe1a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 15:33:34 +0200 Subject: [PATCH 314/394] fix npe --- src/vs/workbench/browser/labels.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 5c0a40f1752..bf7bf9f97d6 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -95,6 +95,7 @@ export class ResourceLabel extends IconLabel { if (!this.options || !this.label || !this.label.resource) { return; } + if (this.options.fileDecorations && e.affectsResource(this.label.resource)) { this.render(false); } @@ -164,8 +165,7 @@ export class ResourceLabel extends IconLabel { }; const resource = this.label.resource; - let label = this.label.name; - + const label = this.label.name; if (this.options && typeof this.options.title === 'string') { iconLabelOptions.title = this.options.title; @@ -182,14 +182,16 @@ export class ResourceLabel extends IconLabel { iconLabelOptions.extraClasses.push(...this.options.extraClasses); } - if (this.options && this.options.fileDecorations) { + if (this.options && this.options.fileDecorations && resource) { let deco = this.decorationsService.getDecoration( resource, this.options.fileKind !== FileKind.FILE ); + if (deco && this.options.fileDecorations.colors) { iconLabelOptions.extraClasses.push(deco.labelClassName); } + if (deco && deco.badgeClassName && this.options.fileDecorations.badges) { iconLabelOptions.badge = { title: deco.title, @@ -288,7 +290,6 @@ export function getIconClasses(modelService: IModelService, modeService: IModeSe // we always set these base classes even if we do not have a path const classes = fileKind === FileKind.ROOT_FOLDER ? ['rootfolder-icon'] : fileKind === FileKind.FOLDER ? ['folder-icon'] : ['file-icon']; - if (resource) { const name = cssEscape(resources.basenameOrAuthority(resource).toLowerCase()); @@ -318,6 +319,7 @@ export function getIconClasses(modelService: IModelService, modeService: IModeSe } } } + return classes; } From b01f60e7d8fb553e90b4bc4a08edbb0585bbabe8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 15:38:07 +0200 Subject: [PATCH 315/394] fix #36431 --- src/vs/code/electron-main/menus.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index df337ac6675..18e32ff6fd4 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -221,7 +221,7 @@ export class CodeMenu { this.closeWorkspace.visible = isInWorkspaceContext; this.closeFolder.visible = !isInWorkspaceContext; - this.closeFolder.enabled = isInFolderContext; + this.closeFolder.enabled = isInFolderContext || isLinux /* https://github.com/Microsoft/vscode/issues/36431 */; } private install(): void { From 089ea2dc2a562b04b2dc98e7c9e39b0558c1f150 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 15:34:46 +0200 Subject: [PATCH 316/394] panelPart: null guard --- src/vs/workbench/browser/parts/panel/panelPart.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index d614edb1810..049064989d2 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -220,12 +220,14 @@ export class PanelPart extends CompositePart implements IPanelService { } private layoutCompositeBar(): void { - let availableWidth = this.dimension.width - 8; // take padding into account - if (this.toolBar) { - // adjust height for global actions showing - availableWidth -= this.toolBar.getContainer().getHTMLElement().offsetWidth; + if (this.dimension) { + let availableWidth = this.dimension.width - 8; // take padding into account + if (this.toolBar) { + // adjust height for global actions showing + availableWidth -= this.toolBar.getContainer().getHTMLElement().offsetWidth; + } + this.compositeBar.layout(new Dimension(availableWidth, this.dimension.height)); } - this.compositeBar.layout(new Dimension(availableWidth, this.dimension.height)); } public shutdown(): void { From a65731b798de77bcc6d13490346344601d463d64 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 15:43:41 +0200 Subject: [PATCH 317/394] compositeBar: always show active one --- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 249698bbaee..df4ae59ddff 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -228,6 +228,10 @@ export class CompositeBar implements ICompositeBar { if (overflows && (size + this.options.overflowActionSize > limit)) { compositesToShow.pop(); } + if (this.activeCompositeId && compositesToShow.length && compositesToShow.indexOf(this.activeCompositeId) === -1) { + compositesToShow.pop(); + compositesToShow.push(this.activeCompositeId); + } } const visibleComposites = Object.keys(this.compositeIdToActions); From cf5ea02310ad778f97c54e685596b42f87e16857 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 15:49:14 +0200 Subject: [PATCH 318/394] decrease overflow width --- src/vs/workbench/browser/parts/panel/media/panelpart.css | 4 +++- src/vs/workbench/browser/parts/panel/panelPart.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index 5c8a810d556..f731fbb7dc1 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -32,11 +32,13 @@ /** Panel Switcher */ -.monaco-workbench > .part.panel .composite-bar > .monaco-action-bar .action-label.toggle-more { +.monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more { background: url('ellipsis.svg') center center no-repeat; display: block; height: 35px; min-width: 28px; + margin-left: 0px; + margin-right: 0px; } .monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar { diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 049064989d2..66485230cdf 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -85,7 +85,7 @@ export class PanelPart extends CompositePart implements IPanelService { getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(OpenPanelAction, this.getPanel(compositeId)), getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), hidePart: () => this.partService.setPanelHidden(true), - overflowActionSize: 60, + overflowActionSize: 28, colors: { backgroundColor: PANEL_BACKGROUND, badgeBackground, From 6e31f4ada264de806d80b76492b9bc9071d100f7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 15:49:33 +0200 Subject: [PATCH 319/394] Settings can be open more in more than one tab (fixes #36447) --- .../parts/preferences/common/preferencesContribution.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index f93a4021f38..665bb232104 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -69,6 +69,15 @@ export class PreferencesContribution implements IWorkbenchContribution { return; } + // If the file resource was already opened before in the group, do not prevent + // the opening of that resource. Otherwise we would have the same settings + // opened twice (https://github.com/Microsoft/vscode/issues/36447) + const stacks = this.editorGroupService.getStacksModel(); + const group = stacks.groupAt(event.position); + if (group && group.contains(event.input)) { + return; + } + // Global User Settings File if (resource.fsPath === this.environmentService.appSettingsPath) { return event.prevent(() => this.preferencesService.openGlobalSettings(event.options, event.position)); From 4bbd41a1c3fea31458ffc5d3deaa9ee82cb93ecd Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 15:56:07 +0200 Subject: [PATCH 320/394] composite bar fix icon --- src/vs/workbench/browser/parts/panel/media/panelpart.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index f731fbb7dc1..042d150e84f 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -111,7 +111,7 @@ background: url('close-inverse.svg') center center no-repeat; } -.vs-dark .monaco-workbench > .part.panel .composite-bar > .monaco-action-bar .action-label.toggle-more, -.hc-black .monaco-workbench > .part.panel .composite-bar > .monaco-action-bar .action-label.toggle-more { +.vs-dark .monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more, +.hc-black .monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more { background: url('ellipsis-inverse.svg') center center no-repeat; } From c43a3fa228171d744eb68a66693e696765e036c0 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 15:50:34 +0200 Subject: [PATCH 321/394] Merge cursor draw calls in the decorations overview ruler --- .../overviewRuler/decorationsOverviewRuler.ts | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 5add770087e..79e46980347 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -369,9 +369,12 @@ export class DecorationsOverviewRuler extends ViewPart { if (!this._settings.hideCursor) { const cursorHeight = (2 * this._settings.pixelRatio) | 0; const halfCursorHeight = (cursorHeight / 2) | 0; - const x = this._settings.x[OverviewRulerLane.Full]; - const w = this._settings.w[OverviewRulerLane.Full]; + const cursorX = this._settings.x[OverviewRulerLane.Full]; + const cursorW = this._settings.w[OverviewRulerLane.Full]; canvasCtx.fillStyle = this._settings.cursorColor; + + let prevY1 = -100; + let prevY2 = -100; for (let i = 0, len = this._cursorPositions.length; i < len; i++) { const cursor = this._cursorPositions[i]; @@ -382,9 +385,23 @@ export class DecorationsOverviewRuler extends ViewPart { yCenter = canvasHeight - halfCursorHeight; } const y1 = yCenter - halfCursorHeight; + const y2 = y1 + cursorHeight; - canvasCtx.fillRect(x, y1, w, cursorHeight); + if (y1 > prevY2 + 1) { + // flush prev + if (i !== 0) { + canvasCtx.fillRect(cursorX, prevY1, cursorW, prevY2 - prevY1); + } + prevY1 = y1; + prevY2 = y2; + } else { + // merge into prev + if (y2 > prevY2) { + prevY2 = y2; + } + } } + canvasCtx.fillRect(cursorX, prevY1, cursorW, prevY2 - prevY1); } if (this._settings.renderBorder && this._settings.borderColor && this._settings.overviewRulerLanes > 0) { From b8df0a3fe62a11eb70d353d0f2194986608694a7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 15:56:04 +0200 Subject: [PATCH 322/394] Fixes #5887: Remove limit for "Change/Select All Occurrences" --- .../contrib/find/common/findController.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 43ea3992e68..2c185f6f42d 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -25,6 +25,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { overviewRulerSelectionHighlightForeground } from 'vs/platform/theme/common/colorRegistry'; import { themeColorFromId } from 'vs/platform/theme/common/themeService'; +import { Constants } from 'vs/editor/common/core/uint'; export const enum FindStartFocusAction { NoFocusChange, @@ -801,21 +802,21 @@ export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMa export abstract class AbstractSelectHighlightsAction extends EditorAction { public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { - let controller = CommonFindController.get(editor); + const controller = CommonFindController.get(editor); if (!controller) { return null; } - let matches: Range[] = null; + let matches: editorCommon.FindMatch[] = null; const findState = controller.getState(); if (findState.isRevealed && findState.isRegex && findState.searchString.length > 0) { - matches = editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? editor.getConfiguration().wordSeparators : null, false).map(m => m.range); + matches = editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); } else { - let r = multiCursorFind(editor, { + const r = multiCursorFind(editor, { changeFindSearchString: true, allowMultiline: true, highlightFindOptions: true @@ -824,14 +825,14 @@ export abstract class AbstractSelectHighlightsAction extends EditorAction { return; } - matches = editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false).map(m => m.range); + matches = editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); } if (matches.length > 0) { - let editorSelection = editor.getSelection(); + const editorSelection = editor.getSelection(); for (let i = 0, len = matches.length; i < len; i++) { - let match = matches[i]; - let intersection = match.intersectRanges(editorSelection); + const match = matches[i]; + let intersection = match.range.intersectRanges(editorSelection); if (intersection) { // bingo! matches.splice(i, 1); @@ -839,7 +840,7 @@ export abstract class AbstractSelectHighlightsAction extends EditorAction { break; } } - editor.setSelections(matches.map(m => new Selection(m.startLineNumber, m.startColumn, m.endLineNumber, m.endColumn))); + editor.setSelections(matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn))); } } } From b2e886f1ebe4c0d3c5f20416ebd56f3a32c389e4 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 16:05:25 +0200 Subject: [PATCH 323/394] use play icon for debug --- .../workbench/parts/debug/browser/media/debug.contribution.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css index 2796a460a0d..ea62255fc43 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css @@ -109,7 +109,7 @@ } .monaco-workbench .part.statusbar .debug-statusbar-item .icon { - -webkit-mask: url('debug-dark.svg') no-repeat 50% 50%; + -webkit-mask: url('continue.svg') no-repeat 50% 50%; -webkit-mask-size: 18px; display: inline-block; padding-right: 2px; From 449f03a626aa05f4595bbb1840e97667dcbb9fcf Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 16:08:09 +0200 Subject: [PATCH 324/394] Saving file after it has been deleted from disk saves empty file. (fixes #36573) --- .../services/textfile/common/textFileEditorModel.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 6c3cd249763..35e832cb076 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -690,10 +690,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // mark the save participant as current pending save operation return this.saveSequentializer.setPending(versionId, saveParticipantPromise.then(newVersionId => { - // the model was not dirty and no save participant changed the contents, so we do not have - // to write the contents to disk, as they are already on disk. we still want to trigger - // a change on the file though so that external file watchers can be notified - if (options.force && !this.dirty && options.reason === SaveReason.EXPLICIT && versionId === newVersionId) { + // Under certain conditions a save to the model will not cause the contents to the flushed on + // disk because we can assume that the contents are already on disk. Instead, we just touch the + // file to still trigger external file watchers for example. + // The conditions are all of: + // - a forced, explicit save (Ctrl+S) + // - the model is not dirty (otherwise we know there are changed which needs to go to the file) + // - the model is not in orphan mode (because in that case we know the file does not exist on disk) + // - the model version did not change due to save participants running + if (options.force && !this.dirty && !this.inOrphanMode && options.reason === SaveReason.EXPLICIT && versionId === newVersionId) { return this.doTouch(); } From 65c08338e4bece35fb53f5a1cdf56d30b7706157 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 20 Oct 2017 16:31:50 +0200 Subject: [PATCH 325/394] disable smoketests --- build/tfs/darwin/build.sh | 16 ++++++++-------- build/tfs/linux/build.sh | 26 +++++++++++++------------- build/tfs/win32/1_build.ps1 | 10 +++++----- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh index b7efbf7b386..df7ee5e0b16 100755 --- a/build/tfs/darwin/build.sh +++ b/build/tfs/darwin/build.sh @@ -37,16 +37,16 @@ step "Run unit tests" \ step "Run integration tests" \ ./scripts/test-integration.sh -function smoketest { - ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" - rm -rf $ARTIFACTS +# function smoketest { +# ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" +# rm -rf $ARTIFACTS - [[ "$VSCODE_QUALITY" == "insider" ]] && VSCODE_APPNAME="Visual Studio Code - Insiders" || VSCODE_APPNAME="Visual Studio Code" - npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/$VSCODE_APPNAME.app" --log $ARTIFACTS -} +# [[ "$VSCODE_QUALITY" == "insider" ]] && VSCODE_APPNAME="Visual Studio Code - Insiders" || VSCODE_APPNAME="Visual Studio Code" +# npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/$VSCODE_APPNAME.app" --log $ARTIFACTS +# } -step "Run smoke test" \ - smoketest +# step "Run smoke test" \ +# smoketest step "Publish release" \ ./build/tfs/darwin/release.sh diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh index 933641afd21..f138b5d237e 100755 --- a/build/tfs/linux/build.sh +++ b/build/tfs/linux/build.sh @@ -39,22 +39,22 @@ step "Build minified" \ step "Run unit tests" \ ./scripts/test.sh --build --reporter dot -function smoketest { - id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) - sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' +# function smoketest { +# id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword) +# sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"' - ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" - rm -rf $ARTIFACTS - mkdir -p $ARTIFACTS - chown -R testuser $ARTIFACTS +# ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts" +# rm -rf $ARTIFACTS +# mkdir -p $ARTIFACTS +# chown -R testuser $ARTIFACTS - ps -o pid= -u testuser | xargs sudo kill -9 - DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --log $ARTIFACTS" - # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32" -} +# ps -o pid= -u testuser | xargs sudo kill -9 +# DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --log $ARTIFACTS" +# # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32" +# } -step "Run smoke test" \ - smoketest +# step "Run smoke test" \ +# smoketest step "Publish release" \ ./build/tfs/linux/release.sh diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1 index 0d87c5276c0..c7fb712e18f 100644 --- a/build/tfs/win32/1_build.ps1 +++ b/build/tfs/win32/1_build.ps1 @@ -52,11 +52,11 @@ step "Run unit tests" { # exec { & .\scripts\test-integration.bat } # } -step "Run smoke test" { - $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts" - Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts +# step "Run smoke test" { +# $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts" +# Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts - exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --log "$Artifacts" } -} +# exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --log "$Artifacts" } +# } done From ce7cbf00688edb208b670a1da2681f7ea9ca8cd6 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 16:41:41 +0200 Subject: [PATCH 326/394] compositeBar: smarter show of active composite --- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index df4ae59ddff..7682c32759b 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -248,9 +248,9 @@ export class CompositeBar implements ICompositeBar { this.compositeOverflowActionItem = null; } - // Pull out composites that overflow or got hidden - visibleComposites.forEach(compositeId => { - if (compositesToShow.indexOf(compositeId) === -1) { + // Pull out composites that overflow, got hidden or changed position + visibleComposites.forEach((compositeId, index) => { + if (compositesToShow.indexOf(compositeId) !== index) { this.pullComposite(compositeId); } }); From 245ee9742b94fd4141213fe125cf37d80e619f72 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 16:48:49 +0200 Subject: [PATCH 327/394] Fixes #36334 --- src/vs/editor/contrib/find/common/findModel.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index dda6ca2f533..573eba89a13 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -130,6 +130,10 @@ export class FindModelBoundToEditorModel { // The find model is disposed during a find state changed event return; } + if (!this._editor.getModel()) { + // The find model will be disposed momentarily + return; + } if (e.searchString || e.isReplaceRevealed || e.isRegex || e.wholeWord || e.matchCase || e.searchScope) { if (e.searchScope) { this.research(e.moveCursor, this._state.searchScope); From c349b491f9e2a17233c09646c76047c95876db2e Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Oct 2017 16:58:12 +0200 Subject: [PATCH 328/394] Fix #36285 --- .../electron-browser/extensionTipsService.ts | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index c6f10cffca4..91d5f4f6dc7 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; import { forEach } from 'vs/base/common/collections'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { match } from 'vs/base/common/glob'; import * as json from 'vs/base/common/json'; import { IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, LocalExtensionType, EXTENSION_IDENTIFIER_PATTERN } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -19,7 +19,7 @@ import { IChoiceService, IMessageService } from 'vs/platform/message/common/mess import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import Severity from 'vs/base/common/severity'; -import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; import { Schemas } from 'vs/base/common/network'; import { IFileService } from 'vs/platform/files/common/files'; import { IExtensionsConfiguration, ConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; @@ -36,7 +36,7 @@ interface IExtensionsContent { const empty: { [key: string]: any; } = Object.create(null); const milliSecondsInADay = 1000 * 60 * 60 * 24; -export class ExtensionTipsService implements IExtensionTipsService { +export class ExtensionTipsService extends Disposable implements IExtensionTipsService { _serviceBrand: any; @@ -48,6 +48,8 @@ export class ExtensionTipsService implements IExtensionTipsService { private _allRecommendations: string[]; private _disposables: IDisposable[] = []; + private _suggestedWorkspaceRecommendedExtensions: string[] = []; + constructor( @IExtensionGalleryService private _galleryService: IExtensionGalleryService, @IModelService private _modelService: IModelService, @@ -61,16 +63,20 @@ export class ExtensionTipsService implements IExtensionTipsService { @IMessageService private messageService: IMessageService, @ITelemetryService private telemetryService: ITelemetryService ) { + super(); + if (!this._galleryService.isEnabled()) { return; } + this._suggestTips(); this._suggestWorkspaceRecommendations(); // Executable based recommendations carry out a lot of file stats, so run them after 10 secs // So that the startup is not affected setTimeout(() => this._suggestBasedOnExecutables(this._exeBasedRecommendations), 10000); + this._register(this.contextService.onDidChangeWorkspaceFolders(e => this.onWorkspaceFoldersChanged(e))); } getWorkspaceRecommendations(): TPromise { @@ -102,6 +108,19 @@ export class ExtensionTipsService implements IExtensionTipsService { return []; } + private onWorkspaceFoldersChanged(event: IWorkspaceFoldersChangeEvent): void { + if (event.added.length) { + TPromise.join(event.added.map(workspaceFolder => this.resolveWorkspaceFolderRecommendations(workspaceFolder))) + .then(result => { + const newRecommendations = flatten(result); + // Suggest only if atleast one of the newly added recommendtations was not suggested before + if (newRecommendations.some(e => this._suggestedWorkspaceRecommendedExtensions.indexOf(e) === -1)) { + this._suggestWorkspaceRecommendations(); + } + }); + } + } + getRecommendations(installedExtensions: string[], searchText: string): string[] { const allRecomendations = this._getAllRecommendationsInProduct(); const fileBased = Object.keys(this._fileBasedRecommendations) @@ -360,6 +379,7 @@ export class ExtensionTipsService implements IExtensionTipsService { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ + this._suggestedWorkspaceRecommendedExtensions = allRecommendations; this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'show' }); return action.run(); case 1: From dce30c1b74ad5a5c8383b4660a81618082c46b25 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 20 Oct 2017 17:06:10 +0200 Subject: [PATCH 329/394] debug: show add config actions on debug quick open fixes #36486 --- .../parts/debug/browser/debugQuickOpen.ts | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts b/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts index e9c35de887b..27e900d3443 100644 --- a/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts +++ b/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts @@ -13,8 +13,38 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IDebugService, ILaunch } from 'vs/workbench/parts/debug/common/debug'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import * as errors from 'vs/base/common/errors'; +import { QuickOpenEntry, QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel'; +import { ICommandService } from 'vs/platform/commands/common/commands'; -class DebugEntry extends Model.QuickOpenEntry { +class AddConfigEntry extends Model.QuickOpenEntry { + + constructor(private label: string, private launch: ILaunch, private commandService: ICommandService, private contextService: IWorkspaceContextService, highlights: Model.IHighlight[] = []) { + super(highlights); + } + + public getLabel(): string { + return this.label; + } + + public getDescription(): string { + return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : ''; + } + + public getAriaLabel(): string { + return nls.localize('entryAriaLabel', "{0}, debug", this.getLabel()); + } + + public run(mode: QuickOpen.Mode, context: Model.IContext): boolean { + if (mode === QuickOpen.Mode.PREVIEW) { + return false; + } + this.commandService.executeCommand('debug.addConfiguration', this.launch.workspace.uri.toString()).done(undefined, errors.onUnexpectedError); + + return true; + } +} + +class StartDebugEntry extends Model.QuickOpenEntry { constructor(private debugService: IDebugService, private contextService: IWorkspaceContextService, private launch: ILaunch, private configurationName: string, highlights: Model.IHighlight[] = []) { super(highlights); @@ -51,7 +81,8 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler { constructor( @IQuickOpenService private quickOpenService: IQuickOpenService, @IDebugService private debugService: IDebugService, - @IWorkspaceContextService private contextService: IWorkspaceContextService + @IWorkspaceContextService private contextService: IWorkspaceContextService, + @ICommandService private commandService: ICommandService ) { super(); } @@ -61,13 +92,24 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler { } public getResults(input: string): TPromise { - const configurations: DebugEntry[] = []; + const configurations: QuickOpenEntry[] = []; - for (let launch of this.debugService.getConfigurationManager().getLaunches()) { + const launches = this.debugService.getConfigurationManager().getLaunches(); + for (let launch of launches) { launch.getConfigurationNames().map(config => ({ config: config, highlights: Filters.matchesContiguousSubString(input, config) })) .filter(({ highlights }) => !!highlights) - .forEach(({ config, highlights }) => configurations.push(new DebugEntry(this.debugService, this.contextService, launch, config, highlights))); + .forEach(({ config, highlights }) => configurations.push(new StartDebugEntry(this.debugService, this.contextService, launch, config, highlights))); } + launches.forEach((l, index) => { + const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.workspace.name) : nls.localize('addConfiguration', "Add Configuration..."); + const entry = new AddConfigEntry(label, l, this.commandService, this.contextService, Filters.matchesContiguousSubString(input, label)); + if (index === 0) { + configurations.push(new QuickOpenEntryGroup(entry, undefined, true)); + } else { + configurations.push(entry); + } + + }); return TPromise.as(new Model.QuickOpenModel(configurations)); } From 4c10294545fb70c9e2029d3c9e07f807fbcf5f57 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 20 Oct 2017 17:23:17 +0200 Subject: [PATCH 330/394] tests - more unique test folders --- .../backup/test/electron-main/backupMainService.test.ts | 3 ++- .../test/electron-main/workspacesMainService.test.ts | 9 ++++++--- .../services/backup/test/node/backupFileService.test.ts | 4 ++-- .../services/files/test/node/fileService.test.ts | 4 ++-- src/vs/workbench/test/workbenchTestServices.ts | 4 ++++ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 7d5a37d4edb..d200c14c5f7 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -23,9 +23,10 @@ import { LogMainService } from 'vs/platform/log/common/log'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { createHash } from 'crypto'; import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; +import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; suite('BackupMainService', () => { - const parentDir = path.join(os.tmpdir(), 'vsctests', 'service'); + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupservice'); const backupHome = path.join(parentDir, 'Backups'); const backupWorkspacesPath = path.join(backupHome, 'workspaces.json'); diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 3adce81a073..28c28f189d9 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -17,9 +17,10 @@ import { WorkspacesMainService, IStoredWorkspace } from 'vs/platform/workspaces/ import { WORKSPACE_EXTENSION, IWorkspaceSavedEvent, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { LogMainService } from 'vs/platform/log/common/log'; import URI from 'vs/base/common/uri'; +import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; suite('WorkspacesMainService', () => { - const parentDir = path.join(os.tmpdir(), 'vsctests', 'service'); + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'workspacesservice'); const workspacesHome = path.join(parentDir, 'Workspaces'); class TestEnvironmentService extends EnvironmentService { @@ -359,14 +360,16 @@ suite('WorkspacesMainService', () => { assert.equal(1, untitled.length); assert.equal(untitledOne.id, untitled[0].id); - return service.createWorkspace([process.cwd(), os.tmpdir()]).then(untitledTwo => { + return service.createWorkspace([os.tmpdir(), process.cwd()]).then(untitledTwo => { untitled = service.getUntitledWorkspacesSync(); assert.equal(2, untitled.length); service.deleteUntitledWorkspaceSync(untitledOne); - service.deleteUntitledWorkspaceSync(untitledTwo); + untitled = service.getUntitledWorkspacesSync(); + assert.equal(1, untitled.length); + service.deleteUntitledWorkspaceSync(untitledTwo); untitled = service.getUntitledWorkspacesSync(); assert.equal(0, untitled.length); diff --git a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts b/src/vs/workbench/services/backup/test/node/backupFileService.test.ts index 65a97a110a8..23420f77df0 100644 --- a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/node/backupFileService.test.ts @@ -19,7 +19,7 @@ import { FileService } from 'vs/workbench/services/files/node/fileService'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; import { RawTextSource } from 'vs/editor/common/model/textSource'; -import { TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices'; +import { TestContextService, TestTextResourceConfigurationService, getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; @@ -34,7 +34,7 @@ class TestEnvironmentService extends EnvironmentService { get backupWorkspacesPath(): string { return this._backupWorkspacesPath; } } -const parentDir = path.join(os.tmpdir(), 'vsctests', 'service'); +const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice'); const backupHome = path.join(parentDir, 'Backups'); const workspacesJsonPath = path.join(backupHome, 'workspaces.json'); diff --git a/src/vs/workbench/services/files/test/node/fileService.test.ts b/src/vs/workbench/services/files/test/node/fileService.test.ts index 6559d99dc1e..428474c05b7 100644 --- a/src/vs/workbench/services/files/test/node/fileService.test.ts +++ b/src/vs/workbench/services/files/test/node/fileService.test.ts @@ -19,13 +19,13 @@ import extfs = require('vs/base/node/extfs'); import encodingLib = require('vs/base/node/encoding'); import utils = require('vs/workbench/services/files/test/node/utils'); import { onError } from 'vs/base/test/common/utils'; -import { TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices'; +import { TestContextService, TestTextResourceConfigurationService, getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; suite('FileService', () => { let service: FileService; - const parentDir = path.join(os.tmpdir(), 'vsctests', 'service'); + const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'fileservice'); let testDir: string; setup(function (done) { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 6c20a16bf44..d4925ff23ff 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -1246,4 +1246,8 @@ export class TestHashService implements IHashService { createSHA1(content: string): string { return content; } +} + +export function getRandomTestPath(tmpdir: string, ...segments: string[]): string { + return paths.join(tmpdir, ...segments, generateUuid()); } \ No newline at end of file From 9bd9854bdd7e19994cb377c0663a800a85d1b563 Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 20 Oct 2017 18:59:06 +0300 Subject: [PATCH 331/394] Add sidebarVisible when clause (Fixes #36595) #36595 --- src/vs/workbench/electron-browser/workbench.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 5b34ea90179..0ca26a15f24 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -102,6 +102,7 @@ import URI from 'vs/base/common/uri'; export const MessagesVisibleContext = new RawContextKey('globalMessageVisible', false); export const EditorsVisibleContext = new RawContextKey('editorIsOpen', false); export const InZenModeContext = new RawContextKey('inZenMode', false); +export const SidebarVisibleContext = new RawContextKey('sidebarVisible', false); export const NoEditorsVisibleContext: ContextKeyExpr = EditorsVisibleContext.toNegated(); interface WorkbenchParams { @@ -200,6 +201,7 @@ export class Workbench implements IPartService { private messagesVisibleContext: IContextKey; private editorsVisibleContext: IContextKey; private inZenMode: IContextKey; + private sideBarVisibleContext: IContextKey; private hasFilesToCreateOpenOrDiff: boolean; private fontAliasing: string; private zenMode: { @@ -288,6 +290,7 @@ export class Workbench implements IPartService { this.messagesVisibleContext = MessagesVisibleContext.bindTo(this.contextKeyService); this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService); this.inZenMode = InZenModeContext.bindTo(this.contextKeyService); + this.sideBarVisibleContext = SidebarVisibleContext.bindTo(this.contextKeyService); // Register Listeners this.registerListeners(); @@ -308,6 +311,7 @@ export class Workbench implements IPartService { let viewletRestoreStopWatch: StopWatch; let viewletIdToRestore: string; if (!this.sideBarHidden) { + this.sideBarVisibleContext.set(true); if (this.shouldRestoreLastOpenedViewlet()) { viewletIdToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE); @@ -790,6 +794,7 @@ export class Workbench implements IPartService { public setSideBarHidden(hidden: boolean, skipLayout?: boolean): TPromise { this.sideBarHidden = hidden; + this.sideBarVisibleContext.set(!hidden); // Adjust CSS if (hidden) { From 5ba128e16721d6a2bff75b72a29f24dd1c02382f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 18:08:08 +0200 Subject: [PATCH 332/394] Fixes #36226: Validate language configuration before applying it. --- .../languageConfigurationExtensionPoint.ts | 199 ++++++++++++++++-- 1 file changed, 182 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts b/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts index 7da69d61142..4b7695b68b9 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts @@ -5,6 +5,7 @@ 'use strict'; import * as nls from 'vs/nls'; +import * as types from 'vs/base/common/types'; import { parse, ParseError } from 'vs/base/common/json'; import { readFile } from 'vs/base/node/pfs'; import { CharacterPair, LanguageConfiguration, IAutoClosingPair, IAutoClosingPairConditional, IndentationRule, CommentRule, FoldingRules } from 'vs/editor/common/modes/languageConfiguration'; @@ -38,6 +39,26 @@ interface ILanguageConfiguration { folding?: FoldingRules; } +function isStringArr(something: string[]): boolean { + if (!Array.isArray(something)) { + return false; + } + for (let i = 0, len = something.length; i < len; i++) { + if (typeof something[i] !== 'string') { + return false; + } + } + return true; + +} + +function isCharacterPair(something: CharacterPair): boolean { + return ( + isStringArr(something) + && something.length === 2 + ); +} + export class LanguageConfigurationFileHandler { private _modeService: IModeService; @@ -80,24 +101,177 @@ export class LanguageConfigurationFileHandler { }); } + private _extractValidCommentRule(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CommentRule { + const source = configuration.comments; + if (typeof source === 'undefined') { + return null; + } + if (!types.isObject(source)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`comments\` to be an object.`); + return null; + } + + let result: CommentRule = null; + if (typeof source.lineComment !== 'undefined') { + if (typeof source.lineComment !== 'string') { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`comments.lineComment\` to be a string.`); + } else { + result = result || {}; + result.lineComment = source.lineComment; + } + } + if (typeof source.blockComment !== 'undefined') { + if (!isCharacterPair(source.blockComment)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`comments.blockComment\` to be an array of two strings.`); + } else { + result = result || {}; + result.blockComment = source.blockComment; + } + } + return result; + } + + private _extractValidBrackets(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CharacterPair[] { + const source = configuration.brackets; + if (typeof source === 'undefined') { + return null; + } + if (!Array.isArray(source)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`brackets\` to be an array.`); + return null; + } + + let result: CharacterPair[] = null; + for (let i = 0, len = source.length; i < len; i++) { + const pair = source[i]; + if (!isCharacterPair(pair)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`brackets[${i}]\` to be an array of two strings.`); + continue; + } + + result = result || []; + result.push(pair); + } + return result; + } + + private _extractValidAutoClosingPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): IAutoClosingPairConditional[] { + const source = configuration.autoClosingPairs; + if (typeof source === 'undefined') { + return null; + } + if (!Array.isArray(source)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`autoClosingPairs\` to be an array.`); + return null; + } + + let result: IAutoClosingPairConditional[] = null; + for (let i = 0, len = source.length; i < len; i++) { + const pair = source[i]; + if (Array.isArray(pair)) { + if (!isCharacterPair(pair)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`autoClosingPairs[${i}]\` to be an array of two strings or an object.`); + continue; + } + result = result || []; + result.push({ open: pair[0], close: pair[1] }); + } else { + if (!types.isObject(pair)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`autoClosingPairs[${i}]\` to be an array of two strings or an object.`); + continue; + } + if (typeof pair.open !== 'string') { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`autoClosingPairs[${i}].open\` to be a string.`); + continue; + } + if (typeof pair.close !== 'string') { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`autoClosingPairs[${i}].close\` to be a string.`); + continue; + } + if (typeof pair.notIn !== 'undefined') { + if (!isStringArr(pair.notIn)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`autoClosingPairs[${i}].notIn\` to be a string array.`); + continue; + } + } + result = result || []; + result.push({ open: pair.open, close: pair.close, notIn: pair.notIn }); + } + } + return result; + } + + private _extractValidSurroundingPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): IAutoClosingPair[] { + const source = configuration.surroundingPairs; + if (typeof source === 'undefined') { + return null; + } + if (!Array.isArray(source)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`surroundingPairs\` to be an array.`); + return null; + } + + let result: IAutoClosingPair[] = null; + for (let i = 0, len = source.length; i < len; i++) { + const pair = source[i]; + if (Array.isArray(pair)) { + if (!isCharacterPair(pair)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`surroundingPairs[${i}]\` to be an array of two strings or an object.`); + continue; + } + result = result || []; + result.push({ open: pair[0], close: pair[1] }); + } else { + if (!types.isObject(pair)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`surroundingPairs[${i}]\` to be an array of two strings or an object.`); + continue; + } + if (typeof pair.open !== 'string') { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`surroundingPairs[${i}].open\` to be a string.`); + continue; + } + if (typeof pair.close !== 'string') { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`surroundingPairs[${i}].close\` to be a string.`); + continue; + } + result = result || []; + result.push({ open: pair.open, close: pair.close }); + } + } + return result; + } + + // private _mapCharacterPairs(pairs: (CharacterPair | IAutoClosingPairConditional)[]): IAutoClosingPairConditional[] { + // return pairs.map(pair => { + // if (Array.isArray(pair)) { + // return { open: pair[0], close: pair[1] }; + // } + // return pair; + // }); + // } + private _handleConfig(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): void { let richEditConfig: LanguageConfiguration = {}; - if (configuration.comments) { - richEditConfig.comments = configuration.comments; + const comments = this._extractValidCommentRule(languageIdentifier, configuration); + if (comments) { + richEditConfig.comments = comments; } - if (configuration.brackets) { - richEditConfig.brackets = configuration.brackets; + const brackets = this._extractValidBrackets(languageIdentifier, configuration); + if (brackets) { + richEditConfig.brackets = brackets; } - if (configuration.autoClosingPairs) { - richEditConfig.autoClosingPairs = this._mapCharacterPairs(configuration.autoClosingPairs); + const autoClosingPairs = this._extractValidAutoClosingPairs(languageIdentifier, configuration); + if (autoClosingPairs) { + richEditConfig.autoClosingPairs = autoClosingPairs; } - if (configuration.surroundingPairs) { - richEditConfig.surroundingPairs = this._mapCharacterPairs(configuration.surroundingPairs); + const surroundingPairs = this._extractValidSurroundingPairs(languageIdentifier, configuration); + if (surroundingPairs) { + richEditConfig.surroundingPairs = surroundingPairs; } if (configuration.wordPattern) { @@ -166,15 +340,6 @@ export class LanguageConfigurationFileHandler { return null; } - - private _mapCharacterPairs(pairs: (CharacterPair | IAutoClosingPairConditional)[]): IAutoClosingPairConditional[] { - return pairs.map(pair => { - if (Array.isArray(pair)) { - return { open: pair[0], close: pair[1] }; - } - return pair; - }); - } } const schemaId = 'vscode://schemas/language-configuration'; From 1ec704e19a73c8478bb8640c655924e6076dc947 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 20 Oct 2017 10:29:51 -0700 Subject: [PATCH 333/394] Fix #36548 - add search.followSymlinks --- src/vs/platform/search/common/search.ts | 2 ++ src/vs/workbench/parts/search/browser/search.contribution.ts | 5 +++++ src/vs/workbench/parts/search/common/queryBuilder.ts | 5 ++++- src/vs/workbench/parts/search/common/search.ts | 3 ++- src/vs/workbench/services/search/node/ripgrepFileSearch.ts | 4 +++- src/vs/workbench/services/search/node/ripgrepTextSearch.ts | 4 +++- src/vs/workbench/services/search/node/search.ts | 1 + src/vs/workbench/services/search/node/searchService.ts | 3 ++- 8 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/search/common/search.ts b/src/vs/platform/search/common/search.ts index bdd1918a876..1abcff42a87 100644 --- a/src/vs/platform/search/common/search.ts +++ b/src/vs/platform/search/common/search.ts @@ -55,6 +55,7 @@ export interface ICommonQueryOptions { useRipgrep?: boolean; disregardIgnoreFiles?: boolean; disregardExcludeSettings?: boolean; + ignoreSymlinks?: boolean; } export interface IQueryOptions extends ICommonQueryOptions { @@ -173,6 +174,7 @@ export interface ISearchConfiguration extends IFilesConfiguration { exclude: glob.IExpression; useRipgrep: boolean; useIgnoreFilesByDefault: boolean; + followSymlinks: boolean; }; editor: { wordSeparators: string; diff --git a/src/vs/workbench/parts/search/browser/search.contribution.ts b/src/vs/workbench/parts/search/browser/search.contribution.ts index 5c489ff6e63..07f79b0238b 100644 --- a/src/vs/workbench/parts/search/browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/browser/search.contribution.ts @@ -371,6 +371,11 @@ configurationRegistry.registerConfiguration({ 'type': 'boolean', 'description': nls.localize('search.quickOpen.includeSymbols', "Configure to include results from a global symbol search in the file results for Quick Open."), 'default': false + }, + 'search.followSymlinks': { + 'type': 'boolean', + 'description': nls.localize('search.followSymlinks', "Controls whether to follow symlinks while searching."), + 'default': true } } }); diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index cf614eeaeb0..65d70195724 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -60,6 +60,8 @@ export class QueryBuilder { return folderConfig.search.useRipgrep; }); + const ignoreSymlinks = !this.configurationService.getConfiguration().search.followSymlinks; + const query = { type, folderQueries, @@ -74,7 +76,8 @@ export class QueryBuilder { contentPattern: contentPattern, useRipgrep, disregardIgnoreFiles: options.disregardIgnoreFiles, - disregardExcludeSettings: options.disregardExcludeSettings + disregardExcludeSettings: options.disregardExcludeSettings, + ignoreSymlinks }; // Filter extraFileResources against global include/exclude patterns - they are already expected to not belong to a workspace diff --git a/src/vs/workbench/parts/search/common/search.ts b/src/vs/workbench/parts/search/common/search.ts index 6b074a33287..a0bbd0554b4 100644 --- a/src/vs/workbench/parts/search/common/search.ts +++ b/src/vs/workbench/parts/search/common/search.ts @@ -80,7 +80,8 @@ export interface IWorkbenchSearchConfiguration extends ISearchConfiguration { }, exclude: glob.IExpression, useRipgrep: boolean, - useIgnoreFilesByDefault: boolean + useIgnoreFilesByDefault: boolean, + followSymlinks: boolean; }; } diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index caba0ebd233..03ea2338f5c 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -42,7 +42,9 @@ function getRgArgs(config: IRawSearch, folderQuery: IFolderSearch, includePatter } // Follow symlinks - args.push('--follow'); + if (!config.ignoreSymlinks) { + args.push('--follow'); + } if (config.exists) { args.push('--quiet'); diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts index da61448ee47..df668d90e57 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts @@ -493,7 +493,9 @@ function getRgArgs(config: IRawSearch): IRgGlobResult { } // Follow symlinks - args.push('--follow'); + if (!config.ignoreSymlinks) { + args.push('--follow'); + } // Set default encoding if only one folder is opened if (config.folderQueries.length === 1 && config.folderQueries[0].fileEncoding && config.folderQueries[0].fileEncoding !== 'utf8') { diff --git a/src/vs/workbench/services/search/node/search.ts b/src/vs/workbench/services/search/node/search.ts index 38c3be3415c..3775f5d9a6e 100644 --- a/src/vs/workbench/services/search/node/search.ts +++ b/src/vs/workbench/services/search/node/search.ts @@ -19,6 +19,7 @@ export interface IFolderSearch { export interface IRawSearch { folderQueries: IFolderSearch[]; + ignoreSymlinks?: boolean; extraFiles?: string[]; filePattern?: string; excludePattern?: IExpression; diff --git a/src/vs/workbench/services/search/node/searchService.ts b/src/vs/workbench/services/search/node/searchService.ts index 85c20bd1f10..09f4f9de0e9 100644 --- a/src/vs/workbench/services/search/node/searchService.ts +++ b/src/vs/workbench/services/search/node/searchService.ts @@ -270,7 +270,8 @@ export class DiskSearch implements ISearchResultProvider { sortByScore: query.sortByScore, cacheKey: query.cacheKey, useRipgrep: query.useRipgrep, - disregardIgnoreFiles: query.disregardIgnoreFiles + disregardIgnoreFiles: query.disregardIgnoreFiles, + ignoreSymlinks: query.ignoreSymlinks }; if (query.folderQueries) { From 1c71515cfbfa22b77029268d91edc1d370b245cc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Oct 2017 10:46:58 -0700 Subject: [PATCH 334/394] Dont use hat for TS version --- extensions/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/package.json b/extensions/package.json index 1e3f4a31a5d..c2911d05072 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "^2.6.1-insiders.20171019" + "typescript": "2.6.1-insiders.20171019" }, "scripts": { "postinstall": "node ./postinstall" From dc44eab7031965fece35f24ce8867af789a836a3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Oct 2017 11:21:06 -0700 Subject: [PATCH 335/394] Prototype TS Codefix commands (#35002) * Prototype TS Codefix commands Initial prototype to support commands on JS/TS quick fixes Part of #34787 * use command for argument name * Update to use published api --- .../src/features/codeActionProvider.ts | 46 ++++++++++++------- .../src/features/refactorProvider.ts | 5 ++ .../typescript/src/typescriptService.ts | 1 + 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/extensions/typescript/src/features/codeActionProvider.ts b/extensions/typescript/src/features/codeActionProvider.ts index 32f50fef59f..99441cdb14a 100644 --- a/extensions/typescript/src/features/codeActionProvider.ts +++ b/extensions/typescript/src/features/codeActionProvider.ts @@ -55,7 +55,7 @@ export default class TypeScriptCodeActionProvider implements CodeActionProvider errorCodes: Array.from(supportedActions) }; const response = await this.client.execute('getCodeFixes', args, token); - return (response.body || []).map(action => this.getCommandForAction(action)); + return (response.body || []).map(action => this.getCommandForAction(action, file)); } private get supportedCodeActions(): Thenable { @@ -72,31 +72,45 @@ export default class TypeScriptCodeActionProvider implements CodeActionProvider return this._supportedCodeActions; } - private getSupportedActionsForContext(context: CodeActionContext): Thenable> { - return this.supportedCodeActions.then(supportedActions => - new Set(context.diagnostics - .map(diagnostic => +diagnostic.code) - .filter(code => supportedActions[code]))); + private async getSupportedActionsForContext(context: CodeActionContext): Promise> { + const supportedActions = await this.supportedCodeActions; + return new Set(context.diagnostics + .map(diagnostic => +diagnostic.code) + .filter(code => supportedActions[code])); } - private getCommandForAction(action: Proto.CodeAction): Command { + private getCommandForAction(action: Proto.CodeAction, file: string): Command { return { title: action.description, command: this.commandId, - arguments: [action] + arguments: [action, file] }; } - private async onCodeAction(action: Proto.CodeAction): Promise { - const workspaceEdit = new WorkspaceEdit(); - for (const change of action.changes) { - for (const textChange of change.textChanges) { - workspaceEdit.replace(this.client.asUrl(change.fileName), - tsTextSpanToVsRange(textChange), - textChange.newText); + private async onCodeAction(action: Proto.CodeAction, file: string): Promise { + if (action.changes && action.changes.length) { + const workspaceEdit = new WorkspaceEdit(); + for (const change of action.changes) { + for (const textChange of change.textChanges) { + workspaceEdit.replace(this.client.asUrl(change.fileName), + tsTextSpanToVsRange(textChange), + textChange.newText); + } + } + + if (!(await workspace.applyEdit(workspaceEdit))) { + return false; } } - return workspace.applyEdit(workspaceEdit); + if (action.commands && action.commands.length) { + for (const command of action.commands) { + const response = await this.client.execute('applyCodeActionCommand', { file, command }); + if (!response || !response.body) { + return false; + } + } + } + return true; } } \ No newline at end of file diff --git a/extensions/typescript/src/features/refactorProvider.ts b/extensions/typescript/src/features/refactorProvider.ts index a17533f4b4b..8b5094ce228 100644 --- a/extensions/typescript/src/features/refactorProvider.ts +++ b/extensions/typescript/src/features/refactorProvider.ts @@ -52,6 +52,11 @@ export default class TypeScriptRefactorProvider implements CodeActionProvider { const actions: Command[] = []; for (const info of response.body) { + // Workaround for https://github.com/Microsoft/TypeScript/issues/19378 + if (info.name.startsWith('Install missing ')) { + continue; + } + if (info.inlineable === false) { actions.push({ title: info.description, diff --git a/extensions/typescript/src/typescriptService.ts b/extensions/typescript/src/typescriptService.ts index bf4067894ef..bf367883cb5 100644 --- a/extensions/typescript/src/typescriptService.ts +++ b/extensions/typescript/src/typescriptService.ts @@ -66,6 +66,7 @@ export interface ITypescriptServiceClient { execute(command: 'docCommentTemplate', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise; execute(command: 'getApplicableRefactors', args: Proto.GetApplicableRefactorsRequestArgs, token?: CancellationToken): Promise; execute(command: 'getEditsForRefactor', args: Proto.GetEditsForRefactorRequestArgs, token?: CancellationToken): Promise; + execute(command: 'applyCodeActionCommand', args: Proto.ApplyCodeActionCommandRequestArgs, token?: CancellationToken): Promise; // execute(command: 'compileOnSaveAffectedFileList', args: Proto.CompileOnSaveEmitFileRequestArgs, token?: CancellationToken): Promise; // execute(command: 'compileOnSaveEmitFile', args: Proto.CompileOnSaveEmitFileRequestArgs, token?: CancellationToken): Promise; execute(command: string, args: any, expectedResult: boolean | CancellationToken, token?: CancellationToken): Promise; From 25a0274d5dc657dd9fdf56d8280dcc2b5e7511e4 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Fri, 20 Oct 2017 10:06:37 -0700 Subject: [PATCH 336/394] Reverting hashservice --- .../telemetry/common/telemetryUtils.ts | 31 +++++++++++++++++-- .../common/editor/resourceEditorInput.ts | 6 ++-- .../common/editor/untitledEditorInput.ts | 6 ++-- src/vs/workbench/electron-browser/shell.ts | 5 --- .../files/common/editors/fileEditorInput.ts | 6 ++-- .../workbench/parts/html/common/htmlInput.ts | 6 ++-- .../preferences/browser/preferencesEditor.ts | 6 ++-- .../walkThrough/node/walkThroughInput.ts | 6 ++-- .../test/node/keybindingEditing.test.ts | 4 +-- .../textfile/common/textFileEditorModel.ts | 5 ++- .../workbench/test/workbenchTestServices.ts | 10 ------ 11 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 904d9602127..4f177bbb2e2 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -39,6 +39,33 @@ export function combinedAppender(...appenders: ITelemetryAppender[]): ITelemetry export const NullAppender: ITelemetryAppender = { log: () => null }; +// --- util + +export function anonymize(input: string): string { + if (!input) { + return input; + } + + let r = ''; + for (let i = 0; i < input.length; i++) { + let ch = input[i]; + if (ch >= '0' && ch <= '9') { + r += '0'; + continue; + } + if (ch >= 'a' && ch <= 'z') { + r += 'a'; + continue; + } + if (ch >= 'A' && ch <= 'Z') { + r += 'A'; + continue; + } + r += ch; + } + return r; +} + /* __GDPR__FRAGMENT__ "URIDescriptor" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, @@ -52,9 +79,9 @@ export interface URIDescriptor { path?: string; } -export function telemetryURIDescriptor(uri: URI, hashPath: (path: string) => string): URIDescriptor { +export function telemetryURIDescriptor(uri: URI): URIDescriptor { const fsPath = uri && uri.fsPath; - return fsPath ? { mimeType: guessMimeTypes(fsPath).join(', '), ext: paths.extname(fsPath), path: hashPath(fsPath) } : {}; + return fsPath ? { mimeType: guessMimeTypes(fsPath).join(', '), ext: paths.extname(fsPath), path: anonymize(fsPath) } : {}; } /** diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index 4f9a57314ec..ea19725e484 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -11,7 +11,6 @@ import { IReference } from 'vs/base/common/lifecycle'; import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * A read-only text editor input whos contents are made of the provided resource that points to an existing @@ -30,8 +29,7 @@ export class ResourceEditorInput extends EditorInput { name: string, description: string, resource: URI, - @ITextModelService private textModelResolverService: ITextModelService, - @IHashService private hashService: IHashService + @ITextModelService private textModelResolverService: ITextModelService ) { super(); @@ -72,7 +70,7 @@ export class ResourceEditorInput extends EditorInput { public getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); - descriptor['resource'] = telemetryURIDescriptor(this.resource, path => this.hashService.createSHA1(path)); + descriptor['resource'] = telemetryURIDescriptor(this.resource); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 45092f33e98..8057bef0160 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -22,7 +22,6 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { Verbosity } from 'vs/platform/editor/common/editor'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * An editor input to be used for untitled text buffers. @@ -49,8 +48,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport @IInstantiationService private instantiationService: IInstantiationService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextFileService private textFileService: ITextFileService, - @IEnvironmentService private environmentService: IEnvironmentService, - @IHashService private hashService: IHashService + @IEnvironmentService private environmentService: IEnvironmentService ) { super(); @@ -254,7 +252,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport public getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); - descriptor['resource'] = telemetryURIDescriptor(this.getResource(), path => this.hashService.createSHA1(path)); + descriptor['resource'] = telemetryURIDescriptor(this.getResource()); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index b0a9dff094c..44543f77bd1 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -91,8 +91,6 @@ import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollba import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax'; import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService'; import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService'; -import { HashService } from 'vs/workbench/services/hash/node/hashService'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * Services that we require for the Shell @@ -295,9 +293,6 @@ export class WorkbenchShell { restoreFontInfo(this.storageService); readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel())); - // Hash - serviceCollection.set(IHashService, new SyncDescriptor(HashService)); - // Experiments this.experimentService = instantiationService.createInstance(ExperimentService); serviceCollection.set(IExperimentService, this.experimentService); diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts index c6ac6973969..f84e67a1176 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts @@ -24,7 +24,6 @@ import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUt import { Verbosity } from 'vs/platform/editor/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * A file editor input is the input type for the file editor of file system resources. @@ -48,8 +47,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextFileService private textFileService: ITextFileService, @IEnvironmentService private environmentService: IEnvironmentService, - @ITextModelService private textModelResolverService: ITextModelService, - @IHashService private hashService: IHashService + @ITextModelService private textModelResolverService: ITextModelService ) { super(); @@ -276,7 +274,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { public getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); - descriptor['resource'] = telemetryURIDescriptor(this.getResource(), path => this.hashService.createSHA1(path)); + descriptor['resource'] = telemetryURIDescriptor(this.getResource()); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { diff --git a/src/vs/workbench/parts/html/common/htmlInput.ts b/src/vs/workbench/parts/html/common/htmlInput.ts index 8338d4fd5b6..fe8955dc0c7 100644 --- a/src/vs/workbench/parts/html/common/htmlInput.ts +++ b/src/vs/workbench/parts/html/common/htmlInput.ts @@ -7,7 +7,6 @@ import URI from 'vs/base/common/uri'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export interface HtmlInputOptions { @@ -26,9 +25,8 @@ export class HtmlInput extends ResourceEditorInput { description: string, resource: URI, public readonly options: HtmlInputOptions, - @ITextModelService textModelResolverService: ITextModelService, - @IHashService hashService: IHashService + @ITextModelService textModelResolverService: ITextModelService ) { - super(name, description, resource, textModelResolverService, hashService); + super(name, description, resource, textModelResolverService); } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 910dcb09831..44875020629 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -59,7 +59,6 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { MessageController } from 'vs/editor/contrib/message/messageController'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export class PreferencesEditorInput extends SideBySideEditorInput { public static ID: string = 'workbench.editorinputs.preferencesEditorInput'; @@ -76,10 +75,9 @@ export class PreferencesEditorInput extends SideBySideEditorInput { export class DefaultPreferencesEditorInput extends ResourceEditorInput { public static ID = 'workbench.editorinputs.defaultpreferences'; constructor(defaultSettingsResource: URI, - @ITextModelService textModelResolverService: ITextModelService, - @IHashService hashService: IHashService + @ITextModelService textModelResolverService: ITextModelService ) { - super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService, hashService); + super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService); } getTypeId(): string { diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts index a534a77b13b..98a5ffc7c8d 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts @@ -15,7 +15,6 @@ import { marked } from 'vs/base/common/marked/marked'; import { Schemas } from 'vs/base/common/network'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export class WalkThroughModel extends EditorModel { @@ -64,8 +63,7 @@ export class WalkThroughInput extends EditorInput { private options: WalkThroughInputOptions, @ITelemetryService private telemetryService: ITelemetryService, @ILifecycleService lifecycleService: ILifecycleService, - @ITextModelService private textModelResolverService: ITextModelService, - @IHashService private hashService: IHashService + @ITextModelService private textModelResolverService: ITextModelService ) { super(); this.disposables.push(lifecycleService.onShutdown(e => this.disposeTelemetry(e))); @@ -94,7 +92,7 @@ export class WalkThroughInput extends EditorInput { getTelemetryDescriptor(): object { const descriptor = super.getTelemetryDescriptor(); descriptor['target'] = this.getTelemetryFrom(); - descriptor['resource'] = telemetryURIDescriptor(this.options.resource, path => this.hashService.createSHA1(path)); + descriptor['resource'] = telemetryURIDescriptor(this.options.resource); /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { "target" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, diff --git a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts index a3f9d2f1c0f..6f003bde491 100644 --- a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts @@ -16,7 +16,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { KeyCode, SimpleKeybinding, ChordKeybinding } from 'vs/base/common/keyCodes'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import extfs = require('vs/base/node/extfs'); -import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService, TestHashService } from 'vs/workbench/test/workbenchTestServices'; +import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService } from 'vs/workbench/test/workbenchTestServices'; import { IWorkspaceContextService, Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import uuid = require('vs/base/common/uuid'); import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; @@ -42,7 +42,6 @@ import { KeybindingsEditingService } from 'vs/workbench/services/keybinding/comm import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; interface Modifiers { metaKey?: boolean; @@ -71,7 +70,6 @@ suite('Keybindings Editing', () => { instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', () => { }); instantiationService.stub(IWorkspaceContextService, new TestContextService()); instantiationService.stub(ILifecycleService, new TestLifecycleService()); - instantiationService.stub(IHashService, new TestHashService()); instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(IModeService, ModeServiceImpl); diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 35e832cb076..1bf8c94ba2e 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -31,9 +31,9 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { anonymize } from 'vs/platform/telemetry/common/telemetryUtils'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IRawTextSource } from 'vs/editor/common/model/textSource'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; /** * The text file editor model listens to changes to its underlying code editor model and saves these changes through the file service back to the disk. @@ -87,7 +87,6 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil @IBackupFileService private backupFileService: IBackupFileService, @IEnvironmentService private environmentService: IEnvironmentService, @IWorkspaceContextService private contextService: IWorkspaceContextService, - @IHashService private hashService: IHashService ) { super(modelService, modeService); @@ -381,7 +380,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) }); + this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); } return model; diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index d4925ff23ff..f371d3afeca 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -59,7 +59,6 @@ import { IRecentlyOpened } from 'vs/platform/history/common/history'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IPosition } from 'vs/editor/common/core/position'; import { ICommandAction } from 'vs/platform/actions/common/actions'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, void 0); @@ -268,7 +267,6 @@ export function workbenchInstantiationService(): IInstantiationService { instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); instantiationService.stub(IEnvironmentService, TestEnvironmentService); instantiationService.stub(IThemeService, new TestThemeService()); - instantiationService.stub(IHashService, new TestHashService()); instantiationService.stub(IChoiceService, { choose: (severity, message, options, cancelId): TPromise => { return TPromise.as(cancelId); @@ -1240,14 +1238,6 @@ export class TestTextResourceConfigurationService implements ITextResourceConfig } } -export class TestHashService implements IHashService { - _serviceBrand: any; - - createSHA1(content: string): string { - return content; - } -} - export function getRandomTestPath(tmpdir: string, ...segments: string[]): string { return paths.join(tmpdir, ...segments, generateUuid()); } \ No newline at end of file From 5943b174aaa163163bb96f836e53abbcaf635bc5 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Fri, 20 Oct 2017 10:13:26 -0700 Subject: [PATCH 337/394] Stop sending path in telemetry data as it isnt used anywhere --- .../telemetry/common/telemetryUtils.ts | 31 ++----------------- .../textfile/common/textFileEditorModel.ts | 3 +- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 4f177bbb2e2..cb438e51f4f 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -41,47 +41,20 @@ export const NullAppender: ITelemetryAppender = { log: () => null }; // --- util -export function anonymize(input: string): string { - if (!input) { - return input; - } - - let r = ''; - for (let i = 0; i < input.length; i++) { - let ch = input[i]; - if (ch >= '0' && ch <= '9') { - r += '0'; - continue; - } - if (ch >= 'a' && ch <= 'z') { - r += 'a'; - continue; - } - if (ch >= 'A' && ch <= 'Z') { - r += 'A'; - continue; - } - r += ch; - } - return r; -} - /* __GDPR__FRAGMENT__ "URIDescriptor" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } + "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ export interface URIDescriptor { mimeType?: string; ext?: string; - path?: string; } export function telemetryURIDescriptor(uri: URI): URIDescriptor { const fsPath = uri && uri.fsPath; - return fsPath ? { mimeType: guessMimeTypes(fsPath).join(', '), ext: paths.extname(fsPath), path: anonymize(fsPath) } : {}; + return fsPath ? { mimeType: guessMimeTypes(fsPath).join(', '), ext: paths.extname(fsPath) } : {}; } /** diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 1bf8c94ba2e..a91a0e12f23 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -31,7 +31,6 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { anonymize } from 'vs/platform/telemetry/common/telemetryUtils'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IRawTextSource } from 'vs/editor/common/model/textSource'; @@ -380,7 +379,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: anonymize(this.resource.fsPath) }); + this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath) }); } return model; From a8fdcc4a6d4f71f75c6689cad4439eb106f60665 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Oct 2017 11:48:36 -0700 Subject: [PATCH 338/394] Auto import dependencies when accepting a global suggestion Fixes #2635 --- .../src/features/completionItemProvider.ts | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index f4e46e19cee..813ba074360 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -11,7 +11,7 @@ import TypingsStatus from '../utils/typingsStatus'; import * as PConst from '../protocol.const'; import { CompletionEntry, CompletionsRequestArgs, CompletionDetailsRequestArgs, CompletionEntryDetails } from '../protocol'; import * as Previewer from './previewer'; -import { tsTextSpanToVsRange, vsPositionToTsFileLocation } from '../utils/convert'; +import { tsTextSpanToVsRange, vsPositionToTsFileLocation, tsLocationToVsPosition } from '../utils/convert'; import * as nls from 'vscode-nls'; let localize = nls.loadMessageBundle(); @@ -46,6 +46,10 @@ class MyCompletionItem extends CompletionItem { } } } + + if (entry.hasAction) { + + } } private static convertKind(kind: string): CompletionItemKind { @@ -277,9 +281,25 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP } const detail = details[0]; item.detail = Previewer.plain(detail.displayParts); - item.documentation = Previewer.markdownDocumentation(detail.documentation, detail.tags); + if (detail.codeActions && detail.codeActions.length) { + const additionalEdits: TextEdit[] = []; + for (const action of detail.codeActions) { + for (const change of action.changes) { + if (change.fileName !== filepath) { + continue; + } + for (const edit of change.textChanges) { + additionalEdits.push(new TextEdit( + new Range(tsLocationToVsPosition(edit.start), tsLocationToVsPosition(edit.end)), + edit.newText)); + } + } + } + item.additionalTextEdits = additionalEdits; + } + if (detail && this.config.useCodeSnippetsOnMethodSuggest && (item.kind === CompletionItemKind.Function || item.kind === CompletionItemKind.Method)) { return this.isValidFunctionCompletionContext(filepath, item.position).then(shouldCompleteFunction => { if (shouldCompleteFunction) { From e164ca7cef0861d3145541a3832ba5b975581d6a Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 20 Oct 2017 11:51:13 -0700 Subject: [PATCH 339/394] Fix tests for ignoreSymlinks --- src/vs/workbench/parts/search/test/common/queryBuilder.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts b/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts index 059f34fb3e3..4cf542b63a9 100644 --- a/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts +++ b/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts @@ -594,6 +594,8 @@ function assertEqualQueries(actual: ISearchQuery, expected: ISearchQuery): void }; }; + delete actual.ignoreSymlinks; + // Avoid comparing URI objects, not a good idea if (expected.folderQueries) { assert.deepEqual(actual.folderQueries.map(folderQueryToCompareObject), expected.folderQueries.map(folderQueryToCompareObject)); From 8798aa5380e128f200658a0a018a22274f3d98b4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Oct 2017 11:52:31 -0700 Subject: [PATCH 340/394] Remove unused lines --- extensions/typescript/src/features/completionItemProvider.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index 813ba074360..7a8d579260d 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -46,10 +46,6 @@ class MyCompletionItem extends CompletionItem { } } } - - if (entry.hasAction) { - - } } private static convertKind(kind: string): CompletionItemKind { From 0a0033b855df211b2f54890c03be7c5c1c06e4e6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 Oct 2017 12:07:12 -0700 Subject: [PATCH 341/394] Remove duplicate code for applying a code action --- .../src/features/codeActionProvider.ts | 32 +++----------- .../src/features/completionItemProvider.ts | 42 +++++++++++-------- extensions/typescript/src/typescriptMain.ts | 2 +- extensions/typescript/src/utils/codeAction.ts | 41 ++++++++++++++++++ 4 files changed, 71 insertions(+), 46 deletions(-) create mode 100644 extensions/typescript/src/utils/codeAction.ts diff --git a/extensions/typescript/src/features/codeActionProvider.ts b/extensions/typescript/src/features/codeActionProvider.ts index 99441cdb14a..80773371264 100644 --- a/extensions/typescript/src/features/codeActionProvider.ts +++ b/extensions/typescript/src/features/codeActionProvider.ts @@ -3,12 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands, workspace, WorkspaceEdit } from 'vscode'; +import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands } from 'vscode'; import * as Proto from '../protocol'; import { ITypescriptServiceClient } from '../typescriptService'; -import { tsTextSpanToVsRange, vsRangeToTsFileRange } from '../utils/convert'; +import { vsRangeToTsFileRange } from '../utils/convert'; import FormattingConfigurationManager from './formattingConfigurationManager'; +import { applyCodeAction } from '../utils/codeAction'; interface NumberSet { [key: number]: boolean; @@ -87,30 +88,7 @@ export default class TypeScriptCodeActionProvider implements CodeActionProvider }; } - private async onCodeAction(action: Proto.CodeAction, file: string): Promise { - if (action.changes && action.changes.length) { - const workspaceEdit = new WorkspaceEdit(); - for (const change of action.changes) { - for (const textChange of change.textChanges) { - workspaceEdit.replace(this.client.asUrl(change.fileName), - tsTextSpanToVsRange(textChange), - textChange.newText); - } - } - - if (!(await workspace.applyEdit(workspaceEdit))) { - return false; - } - } - - if (action.commands && action.commands.length) { - for (const command of action.commands) { - const response = await this.client.execute('applyCodeActionCommand', { file, command }); - if (!response || !response.body) { - return false; - } - } - } - return true; + private onCodeAction(action: Proto.CodeAction, file: string): Promise { + return applyCodeAction(this.client, action, file); } } \ No newline at end of file diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index 7a8d579260d..2036add07d1 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -3,17 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CompletionItem, TextDocument, Position, CompletionItemKind, CompletionItemProvider, CancellationToken, TextEdit, Range, SnippetString, workspace, ProviderResult, CompletionContext } from 'vscode'; +import { CompletionItem, TextDocument, Position, CompletionItemKind, CompletionItemProvider, CancellationToken, TextEdit, Range, SnippetString, workspace, ProviderResult, CompletionContext, commands } from 'vscode'; import { ITypescriptServiceClient } from '../typescriptService'; import TypingsStatus from '../utils/typingsStatus'; import * as PConst from '../protocol.const'; -import { CompletionEntry, CompletionsRequestArgs, CompletionDetailsRequestArgs, CompletionEntryDetails } from '../protocol'; +import { CompletionEntry, CompletionsRequestArgs, CompletionDetailsRequestArgs, CompletionEntryDetails, CodeAction } from '../protocol'; import * as Previewer from './previewer'; -import { tsTextSpanToVsRange, vsPositionToTsFileLocation, tsLocationToVsPosition } from '../utils/convert'; +import { tsTextSpanToVsRange, vsPositionToTsFileLocation } from '../utils/convert'; import * as nls from 'vscode-nls'; +import { applyCodeAction } from '../utils/codeAction'; let localize = nls.loadMessageBundle(); class MyCompletionItem extends CompletionItem { @@ -132,6 +133,7 @@ namespace Configuration { } export default class TypeScriptCompletionItemProvider implements CompletionItemProvider { + private readonly commandId: string; private config: Configuration = { useCodeSnippetsOnMethodSuggest: false, @@ -141,8 +143,12 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP constructor( private client: ITypescriptServiceClient, + mode: string, private typingsStatus: TypingsStatus - ) { } + ) { + this.commandId = `_typescript.applyCompletionCodeAction.${mode}`; + commands.registerCommand(this.commandId, this.applyCompletionCodeAction, this); + } public updateConfiguration(): void { // Use shared setting for js and ts @@ -280,20 +286,11 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP item.documentation = Previewer.markdownDocumentation(detail.documentation, detail.tags); if (detail.codeActions && detail.codeActions.length) { - const additionalEdits: TextEdit[] = []; - for (const action of detail.codeActions) { - for (const change of action.changes) { - if (change.fileName !== filepath) { - continue; - } - for (const edit of change.textChanges) { - additionalEdits.push(new TextEdit( - new Range(tsLocationToVsPosition(edit.start), tsLocationToVsPosition(edit.end)), - edit.newText)); - } - } - } - item.additionalTextEdits = additionalEdits; + item.command = { + title: '', + command: this.commandId, + arguments: [filepath, detail.codeActions] + }; } if (detail && this.config.useCodeSnippetsOnMethodSuggest && (item.kind === CompletionItemKind.Function || item.kind === CompletionItemKind.Method)) { @@ -357,4 +354,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP return new SnippetString(codeSnippet); } + + private async applyCompletionCodeAction(file: string, codeActions: CodeAction[]): Promise { + for (const action of codeActions) { + if (!(await applyCodeAction(this.client, action, file))) { + return false; + } + } + return true; + } } diff --git a/extensions/typescript/src/typescriptMain.ts b/extensions/typescript/src/typescriptMain.ts index 99e6f08e734..b7f99cb8024 100644 --- a/extensions/typescript/src/typescriptMain.ts +++ b/extensions/typescript/src/typescriptMain.ts @@ -239,7 +239,7 @@ class LanguageProvider { const selector = this.description.modeIds; const config = workspace.getConfiguration(this.id); - const completionItemProvider = new (await import('./features/completionItemProvider')).default(client, this.typingsStatus); + const completionItemProvider = new (await import('./features/completionItemProvider')).default(client, this.description.id, this.typingsStatus); completionItemProvider.updateConfiguration(); this.toUpdateOnConfigurationChanged.push(completionItemProvider); this.disposables.push(languages.registerCompletionItemProvider(selector, completionItemProvider, '.', '"', '\'', '/', '@')); diff --git a/extensions/typescript/src/utils/codeAction.ts b/extensions/typescript/src/utils/codeAction.ts new file mode 100644 index 00000000000..c975a4ef9f2 --- /dev/null +++ b/extensions/typescript/src/utils/codeAction.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { WorkspaceEdit, workspace } from 'vscode'; +import * as Proto from '../protocol'; +import { tsTextSpanToVsRange } from './convert'; +import { ITypescriptServiceClient } from '../typescriptService'; + + +export async function applyCodeAction( + client: ITypescriptServiceClient, + action: Proto.CodeAction, + file: string +): Promise { + if (action.changes && action.changes.length) { + const workspaceEdit = new WorkspaceEdit(); + for (const change of action.changes) { + for (const textChange of change.textChanges) { + workspaceEdit.replace(client.asUrl(change.fileName), + tsTextSpanToVsRange(textChange), + textChange.newText); + } + } + + if (!(await workspace.applyEdit(workspaceEdit))) { + return false; + } + } + + if (action.commands && action.commands.length) { + for (const command of action.commands) { + const response = await client.execute('applyCodeActionCommand', { file, command }); + if (!response || !response.body) { + return false; + } + } + } + return true; +} \ No newline at end of file From 004d0da57a05783797ca2860821d613095b346a8 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 21:43:40 +0200 Subject: [PATCH 342/394] Fixes #36090: JS: editor.autoIndent seems to be broken --- .../common/controller/cursorTypeOperations.ts | 7 ++ .../test/common/controller/cursor.test.ts | 87 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 129d02b48a5..68640a9c663 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -324,6 +324,13 @@ export class TypeOperations { } // no enter rules applied, we should check indentation rules then. + if (!config.autoIndent) { + // Nothing special + let lineText = model.getLineContent(range.startLineNumber); + let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1); + return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition); + } + let ir = LanguageConfigurationRegistry.getIndentForEnter(model, range, { unshiftIndent: (indent) => { return TypeOperations.unshiftIndent(config, indent); diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index 8b8a9bd46c4..497327d1772 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -3106,6 +3106,93 @@ suite('Editor Controller - Indentation Rules', () => { assert.equal(model.getLineContent(3), '}'); }); }); + + test('issue #36090: JS: editor.autoIndent seems to be broken', () => { + class JSMode extends MockMode { + private static _id = new LanguageIdentifier('indentRulesMode', 4); + constructor() { + super(JSMode._id); + this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), { + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + indentationRules: { + // ^(.*\*/)?\s*\}.*$ + decreaseIndentPattern: /^((?!.*?\/\*).*\*\/)?\s*[\}\]\)].*$/, + // ^.*\{[^}"']*$ + increaseIndentPattern: /^((?!\/\/).)*(\{[^}"'`]*|\([^)"'`]*|\[[^\]"'`]*)$/ + }, + onEnterRules: [ + { + // e.g. /** | */ + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { indentAction: IndentAction.IndentOutdent, appendText: ' * ' } + }, { + // e.g. /** ...| + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + action: { indentAction: IndentAction.None, appendText: ' * ' } + }, { + // e.g. * ...| + beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { indentAction: IndentAction.None, appendText: '* ' } + }, { + // e.g. */| + beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, + action: { indentAction: IndentAction.None, removeText: 1 } + }, + { + // e.g. *-----*/| + beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/, + action: { indentAction: IndentAction.None, removeText: 1 } + } + ] + })); + } + } + + let mode = new JSMode(); + let model = Model.createFromString( + [ + 'class ItemCtrl {', + ' getPropertiesByItemId(id) {', + ' return this.fetchItem(id)', + ' .then(item => {', + ' return this.getPropertiesOfItem(item);', + ' });', + ' }', + '}', + ].join('\n'), + undefined, + mode.getLanguageIdentifier() + ); + + withMockCodeEditor(null, { model: model, autoIndent: false }, (editor, cursor) => { + moveTo(cursor, 7, 6, false); + assertCursor(cursor, new Selection(7, 6, 7, 6)); + + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); + assert.equal(model.getValue(), + [ + 'class ItemCtrl {', + ' getPropertiesByItemId(id) {', + ' return this.fetchItem(id)', + ' .then(item => {', + ' return this.getPropertiesOfItem(item);', + ' });', + ' }', + ' ', + '}', + ].join('\n') + ); + assertCursor(cursor, new Selection(8, 5, 8, 5)); + }); + + model.dispose(); + mode.dispose(); + }); }); interface ICursorOpts { From f80adf8a85e8eca690d3cd740c7e9f447fa35e89 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Oct 2017 22:08:44 +0200 Subject: [PATCH 343/394] Fix #35219 --- build/lib/i18n.resources.json | 4 ++ .../browser/actions/workspaceActions.ts | 8 +-- .../files/browser/views/explorerViewer.ts | 2 +- .../workspace/common/workspaceEditing.ts | 11 ++++ .../workspace/node/workspaceEditingService.ts | 52 ++++++++++++++++++- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 9325369a2a5..9aafba7dc49 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -186,6 +186,10 @@ "name": "vs/workbench/services/textMate", "project": "vscode-workbench" }, + { + "name": "vs/workbench/services/workspace", + "project": "vscode-workbench" + }, { "name": "setup_messages", "project": "vscode-workbench" diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 50a08486f98..ea253e70218 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -119,7 +119,7 @@ export class AddRootFolderAction extends BaseWorkspacesAction { return TPromise.as(null); } - addFoldersPromise = this.contextService.addFolders(folders.map(folder => URI.file(folder))); + addFoldersPromise = this.workspaceEditingService.addFolders(folders.map(folder => URI.file(folder))); } // Empty or Folder @@ -163,7 +163,7 @@ export class GlobalRemoveRootFolderAction extends BaseWorkspacesAction { } // Workspace: remove folder - return this.contextService.removeFolders([folder.uri]).then(() => true); + return this.workspaceEditingService.removeFolders([folder.uri]).then(() => true); } return true; @@ -216,13 +216,13 @@ export class RemoveRootFolderAction extends Action { private rootUri: URI, id: string, label: string, - @IWorkspaceContextService private contextService: IWorkspaceContextService + @IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService ) { super(id, label); } public run(): TPromise { - return this.contextService.removeFolders([this.rootUri]); + return this.workspaceEditingService.removeFolders([this.rootUri]); } } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 8c02ed1ac07..21617036d53 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -910,7 +910,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { const folders = result.filter(result => result.stat.isDirectory).map(result => result.stat.resource); if (folders.length > 0) { if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - return this.contextService.addFolders(folders); + return this.workspaceEditingService.addFolders(folders); } // If we are in single-folder context, ask for confirmation to create a workspace diff --git a/src/vs/workbench/services/workspace/common/workspaceEditing.ts b/src/vs/workbench/services/workspace/common/workspaceEditing.ts index 8f5e6cd634d..e7d86635073 100644 --- a/src/vs/workbench/services/workspace/common/workspaceEditing.ts +++ b/src/vs/workbench/services/workspace/common/workspaceEditing.ts @@ -7,6 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import URI from 'vs/base/common/uri'; export const IWorkspaceEditingService = createDecorator('workspaceEditingService'); @@ -14,6 +15,16 @@ export interface IWorkspaceEditingService { _serviceBrand: ServiceIdentifier; + /** + * Add folders to the existing workspace + */ + addFolders(folders: URI[]): TPromise; + + /** + * Remove folders from the existing workspace + */ + removeFolders(folders: URI[]): TPromise; + /** * creates a new workspace with the provided folders and opens it. if path is provided * the workspace will be saved into that location. diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index f5711bdfb21..5fa421760f4 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -7,10 +7,11 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import URI from 'vs/base/common/uri'; +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWindowService, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows'; -import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; +import { IJSONEditingService, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; @@ -22,6 +23,8 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; +import { IChoiceService, Severity, IMessageService } from 'vs/platform/message/common/message'; +import { ICommandService } from 'vs/platform/commands/common/commands'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -34,10 +37,23 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { @IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService, @IStorageService private storageService: IStorageService, @IExtensionService private extensionService: IExtensionService, - @IBackupFileService private backupFileService: IBackupFileService + @IBackupFileService private backupFileService: IBackupFileService, + @IChoiceService private choiceService: IChoiceService, + @IMessageService private messageService: IMessageService, + @ICommandService private commandService: ICommandService ) { } + public addFolders(folders: URI[]): TPromise { + return this.contextService.addFolders(folders) + .then(() => null, error => this.handleWorkspaceConfigurationEditingError(error)); + } + + public removeFolders(folders: URI[]): TPromise { + return this.contextService.removeFolders(folders) + .then(() => null, error => this.handleWorkspaceConfigurationEditingError(error)); + } + public createAndEnterWorkspace(folderPaths?: string[], path?: string): TPromise { return this.doEnterWorkspace(() => this.windowService.createAndEnterWorkspace(folderPaths, path)); } @@ -46,6 +62,38 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { return this.doEnterWorkspace(() => this.windowService.saveAndEnterWorkspace(path)); } + private handleWorkspaceConfigurationEditingError(error: JSONEditingError): TPromise { + switch (error.code) { + case JSONEditingErrorCode.ERROR_INVALID_FILE: + return this.onInvalidWorkspaceConfigurationFileError(); + case JSONEditingErrorCode.ERROR_FILE_DIRTY: + return this.onWorkspaceConfigurationFileDirtyError(); + } + this.messageService.show(Severity.Error, error.message); + return TPromise.as(void 0); + } + + private onInvalidWorkspaceConfigurationFileError(): TPromise { + const message = nls.localize('errorInvalidTaskConfiguration', "Unable to write into workspace configuration file. Please open the file to correct errors/warnings in it and try again."); + return this.askToOpenWorkspaceConfigurationFile(message); + } + + private onWorkspaceConfigurationFileDirtyError(): TPromise { + const message = nls.localize('errorWorkspaceConfigurationFileDirty', "Unable to write into workspace configuration file because the file is dirty. Please save it and try again."); + return this.askToOpenWorkspaceConfigurationFile(message); + } + + private askToOpenWorkspaceConfigurationFile(message: string): TPromise { + return this.choiceService.choose(Severity.Error, message, [nls.localize('openWorkspaceConfigurationFile', "Open Workspace Configuration File"), nls.localize('close', "Close")], 1) + .then(option => { + switch (option) { + case 0: + this.commandService.executeCommand('workbench.action.openWorkspaceConfigFile'); + break; + } + }); + } + private doEnterWorkspace(mainSidePromise: () => TPromise): TPromise { // Stop the extension host first to give extensions most time to shutdown From 5520af8168f837a6f79a5e3e89fa994d80383f07 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 20 Oct 2017 22:56:40 +0200 Subject: [PATCH 344/394] Fix #34254 --- .../standalone/browser/simpleServices.ts | 14 +++--- .../common/configurationModels.ts | 43 +++++++++---------- .../node/configurationService.ts | 14 +++--- .../api/node/extHostConfiguration.ts | 10 ++--- .../common/configurationModels.ts | 34 +++++++++++++-- 5 files changed, 71 insertions(+), 44 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 5bfb927109a..e1d06c1220c 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -464,30 +464,30 @@ export class SimpleConfigurationService implements IConfigurationService { getConfiguration(section: string, overrides: IConfigurationOverrides): T getConfiguration(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : void 0; - const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; - return this.configuration().getSection(section, overrides); + const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : {}; + return this.configuration().getSection(section, overrides, null); } - public getValue(key: string, options?: IConfigurationOverrides): C { - return this.configuration().getValue(key, options); + public getValue(key: string, options: IConfigurationOverrides = {}): C { + return this.configuration().getValue(key, options, null); } public updateValue(key: string, value: any, arg3?: any, arg4?: any): TPromise { return TPromise.as(null); } - public inspect(key: string, options?: IConfigurationOverrides): { + public inspect(key: string, options: IConfigurationOverrides = {}): { default: C, user: C, workspace: C, workspaceFolder: C value: C, } { - return this.configuration().lookup(key, options); + return this.configuration().lookup(key, options, null); } public keys() { - return this.configuration().keys(); + return this.configuration().keys(null); } public reloadConfiguration(): TPromise { diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 98a195affaa..dcd1c8eb569 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -283,8 +283,7 @@ export class Configuration { protected _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(), protected folders: StrictResourceMap = new StrictResourceMap(), protected _memoryConfiguration: ConfigurationModel = new ConfigurationModel(), - protected _memoryConfigurationByResource: StrictResourceMap = new StrictResourceMap(), - protected _workspace?: Workspace) { + protected _memoryConfigurationByResource: StrictResourceMap = new StrictResourceMap()) { this.merge(); } @@ -317,13 +316,13 @@ export class Configuration { this._foldersConsolidatedConfigurations.set(folder, this._workspaceConsolidatedConfiguration.merge(this.folders.get(folder))); } - getSection(section: string = '', overrides: IConfigurationOverrides = {}): C { - const configModel = this.getConsolidateConfigurationModel(overrides); + getSection(section: string = '', overrides: IConfigurationOverrides, workspace: Workspace): C { + const configModel = this.getConsolidateConfigurationModel(overrides, workspace); return objects.clone(section ? configModel.getSectionContents(section) : configModel.contents); } - getValue(key: string, overrides: IConfigurationOverrides = {}): any { - const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); + getValue(key: string, overrides: IConfigurationOverrides, workspace: Workspace): any { + const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides, workspace); return objects.clone(getConfigurationValue(consolidateConfigurationModel.contents, key)); } @@ -350,7 +349,7 @@ export class Configuration { } } - lookup(key: string, overrides: IConfigurationOverrides = {}): { + lookup(key: string, overrides: IConfigurationOverrides, workspace: Workspace): { default: C, user: C, workspace: C, @@ -358,26 +357,26 @@ export class Configuration { memory?: C value: C, } { - const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides); - const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource); + const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides, workspace); + const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace); const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration; return objects.clone({ default: getConfigurationValue(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key), user: getConfigurationValue(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key), - workspace: this._workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0, //Check on workspace exists or not because _workspaceConfiguration is never null + workspace: workspace ? getConfigurationValue(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0, //Check on workspace exists or not because _workspaceConfiguration is never null workspaceFolder: folderConfigurationModel ? getConfigurationValue(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0, memory: getConfigurationValue(overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).contents : memoryConfigurationModel.contents, key), value: getConfigurationValue(consolidateConfigurationModel.contents, key) }); } - keys(): { + keys(workspace: Workspace): { default: string[]; user: string[]; workspace: string[]; workspaceFolder: string[]; } { - const folderConfigurationModel = this.getFolderConfigurationModelForResource(); + const folderConfigurationModel = this.getFolderConfigurationModelForResource(null, workspace); return objects.clone({ default: this._defaults.keys, user: this._user.keys, @@ -386,13 +385,13 @@ export class Configuration { }); } - private getConsolidateConfigurationModel(overrides: IConfigurationOverrides): ConfigurationModel { - let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides); + private getConsolidateConfigurationModel(overrides: IConfigurationOverrides, workspace: Workspace): ConfigurationModel { + let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace); return overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel; } - private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides): ConfigurationModel { - if (!this._workspace) { + private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides, workspace: Workspace): ConfigurationModel { + if (!workspace) { return this._globalConfiguration; } @@ -401,7 +400,7 @@ export class Configuration { } let consolidateConfiguration = this._workspaceConsolidatedConfiguration; - const root = this._workspace.getFolder(resource); + const root = workspace.getFolder(resource); if (root) { consolidateConfiguration = this._foldersConsolidatedConfigurations.get(root.uri) || this._workspaceConsolidatedConfiguration; } @@ -414,12 +413,12 @@ export class Configuration { return consolidateConfiguration; } - private getFolderConfigurationModelForResource(resource?: URI): ConfigurationModel { - if (!this._workspace || !resource) { + private getFolderConfigurationModelForResource(resource: URI, workspace: Workspace): ConfigurationModel { + if (!workspace || !resource) { return null; } - const root = this._workspace.getFolder(resource); + const root = workspace.getFolder(resource); return root ? this.folders.get(root.uri) : null; } @@ -448,7 +447,7 @@ export class Configuration { }; } - public static parse(data: IConfigurationData, workspace: Workspace): Configuration { + public static parse(data: IConfigurationData): Configuration { const defaultConfiguration = Configuration.parseConfigurationModel(data.defaults); const userConfiguration = Configuration.parseConfigurationModel(data.user); const workspaceConfiguration = Configuration.parseConfigurationModel(data.workspace); @@ -456,7 +455,7 @@ export class Configuration { result.set(URI.parse(key), Configuration.parseConfigurationModel(data.folders[key])); return result; }, new StrictResourceMap()); - return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap(), workspace); + return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap()); } private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel { diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 9fb8cfc6fa6..43ad33bce80 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -62,12 +62,12 @@ export class ConfigurationService extends Disposable implements IConfigurationSe getConfiguration(section: string, overrides: IConfigurationOverrides): T getConfiguration(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : void 0; - const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : void 0; - return this.configuration.getSection(section, overrides); + const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : {}; + return this.configuration.getSection(section, overrides, null); } - getValue(key: string, overrides: IConfigurationOverrides): any { - return this.configuration.getValue(key, overrides); + getValue(key: string, overrides: IConfigurationOverrides = {}): any { + return this.configuration.getValue(key, overrides, null); } updateValue(key: string, value: any): TPromise @@ -85,7 +85,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe workspaceFolder: T value: T } { - return this.configuration.lookup(key); + return this.configuration.lookup(key, {}, null); } keys(): { @@ -94,7 +94,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe workspace: string[]; workspaceFolder: string[]; } { - return this.configuration.keys(); + return this.configuration.keys(null); } reloadConfiguration(folder?: IWorkspaceFolder): TPromise { @@ -109,7 +109,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe if (changedKeys.length) { const oldConfiguartion = this._configuration; this.reset(); - changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key), this._configuration.getValue(key))); + changedKeys = changedKeys.filter(key => !equals(oldConfiguartion.getValue(key, {}, null), this._configuration.getValue(key, {}, null))); if (changedKeys.length) { this.trigger(changedKeys, ConfigurationTarget.USER); } diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index fde9013ed78..f7b42446d55 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -45,7 +45,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationData) { this._proxy = proxy; this._extHostWorkspace = extHostWorkspace; - this._configuration = Configuration.parse(data, extHostWorkspace.workspace); + this._configuration = Configuration.parse(data); } get onDidChangeConfiguration(): Event { @@ -53,14 +53,14 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { } $acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) { - this._configuration = Configuration.parse(data, this._extHostWorkspace.workspace); + this._configuration = Configuration.parse(data); this._onDidChangeConfiguration.fire(undefined); } getConfiguration(section?: string, resource?: URI): vscode.WorkspaceConfiguration { const config = section - ? lookUp(this._configuration.getSection(null, { resource }), section) - : this._configuration.getSection(null, { resource }); + ? lookUp(this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace), section) + : this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace); function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget { if (arg === void 0 || arg === null) { @@ -99,7 +99,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { }, inspect: (key: string): ConfigurationInspect => { key = section ? `${section}.${key}` : key; - const config = this._configuration.lookup(key, { resource }); + const config = this._configuration.lookup(key, { resource }, this._extHostWorkspace.workspace); if (config) { return { key, diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 3e72fc9fe57..033e039225b 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import { clone, equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModel, Configuration as BaseConfiguration, CustomConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -193,8 +193,36 @@ export class Configuration extends BaseConfiguration { protected folders: StrictResourceMap, memoryConfiguration: ConfigurationModel, memoryConfigurationByResource: StrictResourceMap, - workspace: Workspace) { - super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource, workspace); + private readonly _workspace: Workspace) { + super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource); + } + + getSection(section: string = '', overrides: IConfigurationOverrides = {}): C { + return super.getSection(section, overrides, this._workspace); + } + + getValue(key: string, overrides: IConfigurationOverrides = {}): any { + return super.getValue(key, overrides, this._workspace); + } + + lookup(key: string, overrides: IConfigurationOverrides = {}): { + default: C, + user: C, + workspace: C, + workspaceFolder: C + memory?: C + value: C, + } { + return super.lookup(key, overrides, this._workspace); + } + + keys(): { + default: string[]; + user: string[]; + workspace: string[]; + workspaceFolder: string[]; + } { + return super.keys(this._workspace); } updateDefaultConfiguration(defaults: ConfigurationModel): void { From a608c4ae9b2c1fe0c208654b75c60cf01a1eecd1 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Fri, 20 Oct 2017 14:37:18 -0700 Subject: [PATCH 345/394] Refactoring extensionsTipsService --- .../electron-browser/extensionTipsService.ts | 59 ++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index 91d5f4f6dc7..cd39fd83d4c 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -122,11 +122,9 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe } getRecommendations(installedExtensions: string[], searchText: string): string[] { - const allRecomendations = this._getAllRecommendationsInProduct(); const fileBased = Object.keys(this._fileBasedRecommendations) .filter(recommendation => { - return allRecomendations.indexOf(recommendation) > -1 - && installedExtensions.indexOf(recommendation) === -1 + return installedExtensions.indexOf(recommendation) === -1 && recommendation.toLowerCase().indexOf(searchText) > -1; }).sort((a, b) => { return this._fileBasedRecommendations[a] > this._fileBasedRecommendations[b] ? -1 : 1; @@ -163,16 +161,6 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe return product.keymapExtensionTips || []; } - private _getAllRecommendationsInProduct(): string[] { - if (!this._allRecommendations) { - this._allRecommendations = [...Object.keys(this.importantRecommendations)]; - forEach(this._availableRecommendations, ({ value: ids }) => { - this._allRecommendations.push(...ids); - }); - } - return this._allRecommendations; - } - private _suggestTips() { const extensionTips = product.extensionTips; if (!extensionTips) { @@ -181,26 +169,6 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe this.importantRecommendations = product.extensionImportantTips || Object.create(null); this.importantRecommendationsIgnoreList = JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]')); - // retrieve ids of previous recommendations - const storedRecommendationsJson = JSON.parse(this.storageService.get('extensionsAssistant/recommendations', StorageScope.GLOBAL, '[]')); - if (Array.isArray(storedRecommendationsJson)) { - for (let id of storedRecommendationsJson) { - this._fileBasedRecommendations[id] = Date.now(); - } - } else { - const now = Date.now(); - forEach(storedRecommendationsJson, entry => { - if (typeof entry.value === 'number') { - const diff = (now - entry.value) / milliSecondsInADay; - if (diff > 7) { - delete this._fileBasedRecommendations[entry.value]; - } else { - this._fileBasedRecommendations[entry.key] = entry.value; - } - } - }); - } - // group ids by pattern, like {**/*.md} -> [ext.foo1, ext.bar2] this._availableRecommendations = Object.create(null); forEach(extensionTips, entry => { @@ -224,6 +192,31 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe } }); + forEach(this._availableRecommendations, ({ value: ids }) => { + this._allRecommendations.push(...ids); + }); + + // retrieve ids of previous recommendations + const storedRecommendationsJson = JSON.parse(this.storageService.get('extensionsAssistant/recommendations', StorageScope.GLOBAL, '[]')); + + if (Array.isArray(storedRecommendationsJson)) { + for (let id of storedRecommendationsJson) { + if (this._allRecommendations.indexOf(id) > -1) { + this._fileBasedRecommendations[id] = Date.now(); + } + } + } else { + const now = Date.now(); + forEach(storedRecommendationsJson, entry => { + if (typeof entry.value === 'number') { + const diff = (now - entry.value) / milliSecondsInADay; + if (diff <= 7 && this._allRecommendations.indexOf(entry.key) > -1) { + this._fileBasedRecommendations[entry.key] = entry.value; + } + } + }); + } + this._modelService.onModelAdded(this._suggest, this, this._disposables); this._modelService.getModels().forEach(model => this._suggest(model)); } From fa484b693f8fc61654b8a4321242b1fd9a189b4f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 20 Oct 2017 23:55:20 +0200 Subject: [PATCH 346/394] Fixes #29036: Create an undo stop when alternating between constructive edits and destructive edits --- .../editor/common/controller/coreCommands.ts | 10 +- src/vs/editor/common/controller/cursor.ts | 27 ++- .../editor/common/controller/cursorCommon.ts | 17 ++ .../controller/cursorDeleteOperations.ts | 12 +- .../common/controller/cursorTypeOperations.ts | 54 ++--- .../test/common/controller/cursor.test.ts | 214 +++++++++++++++++- 6 files changed, 289 insertions(+), 45 deletions(-) diff --git a/src/vs/editor/common/controller/coreCommands.ts b/src/vs/editor/common/controller/coreCommands.ts index cefe9d0d216..33661420850 100644 --- a/src/vs/editor/common/controller/coreCommands.ts +++ b/src/vs/editor/common/controller/coreCommands.ts @@ -8,7 +8,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext } from 'vs/editor/common/controller/cursorCommon'; +import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext, EditOperationType } from 'vs/editor/common/controller/cursorCommon'; import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { CursorMoveCommands, CursorMove as CursorMove_ } from 'vs/editor/common/controller/cursorMoveCommands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -1614,11 +1614,13 @@ export namespace CoreEditingCommands { } public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void { - const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()); + const cursors = editor._getCursors(); + const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(cursors.getPrevEditOperationType(), editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()); if (shouldPushStackElementBefore) { editor.pushUndoStop(); } editor.executeCommands(this.id, commands); + cursors.setPrevEditOperationType(EditOperationType.DeletingLeft); } }); @@ -1637,11 +1639,13 @@ export namespace CoreEditingCommands { } public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void { - const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteRight(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()); + const cursors = editor._getCursors(); + const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteRight(cursors.getPrevEditOperationType(), editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()); if (shouldPushStackElementBefore) { editor.pushUndoStop(); } editor.executeCommands(this.id, commands); + cursors.setPrevEditOperationType(EditOperationType.DeletingRight); } }); diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index bbe2d1aa6ee..9c247c0ac58 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -12,7 +12,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection, SelectionDirection, ISelection } from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { CursorColumns, CursorConfiguration, EditOperationResult, CursorContext, CursorState, RevealTarget, IColumnSelectData, ICursors } from 'vs/editor/common/controller/cursorCommon'; +import { CursorColumns, CursorConfiguration, EditOperationResult, CursorContext, CursorState, RevealTarget, IColumnSelectData, ICursors, EditOperationType } from 'vs/editor/common/controller/cursorCommon'; import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations'; import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; import { TextModelEventType, ModelRawContentChangedEvent, RawContentChangedType } from 'vs/editor/common/model/textModelEvents'; @@ -98,6 +98,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { private _isHandling: boolean; private _isDoingComposition: boolean; private _columnSelectData: IColumnSelectData; + private _prevEditOperationType: EditOperationType; constructor(configuration: editorCommon.IConfiguration, model: editorCommon.IModel, viewModel: IViewModel) { super(); @@ -110,6 +111,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { this._isHandling = false; this._isDoingComposition = false; this._columnSelectData = null; + this._prevEditOperationType = EditOperationType.Other; this._register(this._model.addBulkListener((events) => { if (this._isHandling) { @@ -278,6 +280,9 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { } private _onModelContentChanged(hadFlushEvent: boolean): void { + + this._prevEditOperationType = EditOperationType.Other; + if (hadFlushEvent) { // a model.setValue() was called this._cursors.dispose(); @@ -322,6 +327,14 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { this.setStates(source, CursorChangeReason.NotSet, CursorState.fromModelSelections(selections)); } + public getPrevEditOperationType(): EditOperationType { + return this._prevEditOperationType; + } + + public setPrevEditOperationType(type: EditOperationType): void { + this._prevEditOperationType = type; + } + // ------ auxiliary handling logic private _executeEditOperation(opResult: EditOperationResult): void { @@ -344,6 +357,8 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { if (result) { // The commands were applied correctly this._interpretCommandResult(result); + + this._prevEditOperationType = opResult.type; } if (opResult.shouldPushStackElementAfter) { @@ -515,16 +530,16 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { } // Here we must interpret each typed character individually, that's why we create a new context - this._executeEditOperation(TypeOperations.typeWithInterceptors(this.context.config, this.context.model, this.getSelections(), chr)); + this._executeEditOperation(TypeOperations.typeWithInterceptors(this._prevEditOperationType, this.context.config, this.context.model, this.getSelections(), chr)); } } else { - this._executeEditOperation(TypeOperations.typeWithoutInterceptors(this.context.config, this.context.model, this.getSelections(), text)); + this._executeEditOperation(TypeOperations.typeWithoutInterceptors(this._prevEditOperationType, this.context.config, this.context.model, this.getSelections(), text)); } } private _replacePreviousChar(text: string, replaceCharCnt: number): void { - this._executeEditOperation(TypeOperations.replacePreviousChar(this.context.config, this.context.model, this.getSelections(), text, replaceCharCnt)); + this._executeEditOperation(TypeOperations.replacePreviousChar(this._prevEditOperationType, this.context.config, this.context.model, this.getSelections(), text, replaceCharCnt)); } private _paste(text: string, pasteOnNewLine: boolean): void { @@ -538,14 +553,14 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { private _externalExecuteCommand(command: editorCommon.ICommand): void { this._cursors.killSecondaryCursors(); - this._executeEditOperation(new EditOperationResult([command], { + this._executeEditOperation(new EditOperationResult(EditOperationType.Other, [command], { shouldPushStackElementBefore: false, shouldPushStackElementAfter: false })); } private _externalExecuteCommands(commands: editorCommon.ICommand[]): void { - this._executeEditOperation(new EditOperationResult(commands, { + this._executeEditOperation(new EditOperationResult(EditOperationType.Other, commands, { shouldPushStackElementBefore: false, shouldPushStackElementAfter: false })); diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index 615643272da..b3b40cca6b3 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -31,6 +31,17 @@ export const enum RevealTarget { BottomMost = 2 } +/** + * This is an operation type that will be recorded for undo/redo purposes. + * The goal is to introduce an undo stop when the controller switches between different operation types. + */ +export const enum EditOperationType { + Other = 0, + Typing = 1, + DeletingLeft = 2, + DeletingRight = 3 +} + export interface ICursors { readonly context: CursorContext; getPrimaryCursor(): CursorState; @@ -45,6 +56,9 @@ export interface ICursors { revealRange(revealHorizontal: boolean, viewRange: Range, verticalType: VerticalRevealType, scrollType: ScrollType): void; scrollTo(desiredScrollTop: number): void; + + getPrevEditOperationType(): EditOperationType; + setPrevEditOperationType(type: EditOperationType): void; } export interface CharacterMap { @@ -422,17 +436,20 @@ export class CursorState { export class EditOperationResult { _editOperationResultBrand: void; + readonly type: EditOperationType; readonly commands: ICommand[]; readonly shouldPushStackElementBefore: boolean; readonly shouldPushStackElementAfter: boolean; constructor( + type: EditOperationType, commands: ICommand[], opts: { shouldPushStackElementBefore: boolean; shouldPushStackElementAfter: boolean; } ) { + this.type = type; this.commands = commands; this.shouldPushStackElementBefore = opts.shouldPushStackElementBefore; this.shouldPushStackElementAfter = opts.shouldPushStackElementAfter; diff --git a/src/vs/editor/common/controller/cursorDeleteOperations.ts b/src/vs/editor/common/controller/cursorDeleteOperations.ts index 7951ab91b83..e5b498b40e9 100644 --- a/src/vs/editor/common/controller/cursorDeleteOperations.ts +++ b/src/vs/editor/common/controller/cursorDeleteOperations.ts @@ -5,7 +5,7 @@ 'use strict'; import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand'; -import { CursorColumns, CursorConfiguration, ICursorSimpleModel, EditOperationResult } from 'vs/editor/common/controller/cursorCommon'; +import { CursorColumns, CursorConfiguration, ICursorSimpleModel, EditOperationResult, EditOperationType } from 'vs/editor/common/controller/cursorCommon'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations'; @@ -14,9 +14,9 @@ import { ICommand } from 'vs/editor/common/editorCommon'; export class DeleteOperations { - public static deleteRight(config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, ICommand[]] { + public static deleteRight(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, ICommand[]] { let commands: ICommand[] = []; - let shouldPushStackElementBefore = false; + let shouldPushStackElementBefore = (prevEditOperationType !== EditOperationType.DeletingRight); for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; @@ -94,14 +94,14 @@ export class DeleteOperations { return [true, commands]; } - public static deleteLeft(config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, ICommand[]] { + public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, ICommand[]] { if (this._isAutoClosingPairDelete(config, model, selections)) { return this._runAutoClosingPairDelete(config, model, selections); } let commands: ICommand[] = []; - let shouldPushStackElementBefore = false; + let shouldPushStackElementBefore = (prevEditOperationType !== EditOperationType.DeletingLeft); for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; @@ -210,7 +210,7 @@ export class DeleteOperations { commands[i] = new ReplaceCommand(selection, ''); } } - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Other, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: true }); diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 68640a9c663..cad7da5a71c 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -6,7 +6,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { ReplaceCommand, ReplaceCommandWithoutChangingPosition, ReplaceCommandWithOffsetCursorState } from 'vs/editor/common/commands/replaceCommand'; -import { CursorColumns, CursorConfiguration, ICursorSimpleModel, EditOperationResult } from 'vs/editor/common/controller/cursorCommon'; +import { CursorColumns, CursorConfiguration, ICursorSimpleModel, EditOperationResult, EditOperationType } from 'vs/editor/common/controller/cursorCommon'; import { Range } from 'vs/editor/common/core/range'; import { ICommand, ITokenizedModel } from 'vs/editor/common/editorCommon'; import * as strings from 'vs/base/common/strings'; @@ -73,7 +73,7 @@ export class TypeOperations { for (let i = 0, len = selections.length; i < len; i++) { commands[i] = new ReplaceCommand(selections[i], text[i]); } - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Other, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: true }); @@ -103,7 +103,7 @@ export class TypeOperations { commands[i] = new ReplaceCommand(selection, text); } } - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Other, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: true }); @@ -255,7 +255,7 @@ export class TypeOperations { return commands; } - public static replacePreviousChar(config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], txt: string, replaceCharCnt: number): EditOperationResult { + public static replacePreviousChar(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], txt: string, replaceCharCnt: number): EditOperationResult { let commands: ICommand[] = []; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; @@ -271,8 +271,8 @@ export class TypeOperations { let range = new Range(pos.lineNumber, startColumn, pos.lineNumber, pos.column); commands[i] = new ReplaceCommand(range, txt); } - return new EditOperationResult(commands, { - shouldPushStackElementBefore: false, + return new EditOperationResult(EditOperationType.Typing, commands, { + shouldPushStackElementBefore: (prevEditOperationType !== EditOperationType.Typing), shouldPushStackElementAfter: false }); } @@ -475,7 +475,7 @@ export class TypeOperations { return cnt; } - private static _runAutoClosingCloseCharType(config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { + private static _runAutoClosingCloseCharType(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { let commands: ICommand[] = []; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; @@ -483,8 +483,8 @@ export class TypeOperations { const typeSelection = new Range(position.lineNumber, position.column, position.lineNumber, position.column + 1); commands[i] = new ReplaceCommand(typeSelection, ch); } - return new EditOperationResult(commands, { - shouldPushStackElementBefore: false, + return new EditOperationResult(EditOperationType.Typing, commands, { + shouldPushStackElementBefore: (prevEditOperationType !== EditOperationType.Typing), shouldPushStackElementAfter: false }); } @@ -557,14 +557,14 @@ export class TypeOperations { return true; } - private static _runAutoClosingOpenCharType(config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { + private static _runAutoClosingOpenCharType(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { let commands: ICommand[] = []; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; const closeCharacter = config.autoClosingPairsOpen[ch]; commands[i] = new ReplaceCommandWithOffsetCursorState(selection, ch + closeCharacter, 0, -closeCharacter.length); } - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Typing, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: false }); @@ -604,14 +604,14 @@ export class TypeOperations { return true; } - private static _runSurroundSelectionType(config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { + private static _runSurroundSelectionType(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { let commands: ICommand[] = []; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; const closeCharacter = config.surroundingPairs[ch]; commands[i] = new SurroundSelectionCommand(selection, ch, closeCharacter); } - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Other, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: true }); @@ -624,7 +624,7 @@ export class TypeOperations { return false; } - private static _typeInterceptorElectricChar(config: CursorConfiguration, model: ITokenizedModel, selection: Selection, ch: string): EditOperationResult { + private static _typeInterceptorElectricChar(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selection: Selection, ch: string): EditOperationResult { if (!config.electricChars.hasOwnProperty(ch) || !selection.isEmpty()) { return null; } @@ -646,7 +646,7 @@ export class TypeOperations { if (electricAction.appendText) { const command = new ReplaceCommandWithOffsetCursorState(selection, ch + electricAction.appendText, 0, -electricAction.appendText.length); - return new EditOperationResult([command], { + return new EditOperationResult(EditOperationType.Typing, [command], { shouldPushStackElementBefore: false, shouldPushStackElementAfter: true }); @@ -677,7 +677,7 @@ export class TypeOperations { let typeSelection = new Range(position.lineNumber, 1, position.lineNumber, position.column); const command = new ReplaceCommand(typeSelection, typeText); - return new EditOperationResult([command], { + return new EditOperationResult(EditOperationType.Typing, [command], { shouldPushStackElementBefore: false, shouldPushStackElementAfter: true }); @@ -687,14 +687,14 @@ export class TypeOperations { return null; } - public static typeWithInterceptors(config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { + public static typeWithInterceptors(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], ch: string): EditOperationResult { if (ch === '\n') { let commands: ICommand[] = []; for (let i = 0, len = selections.length; i < len; i++) { commands[i] = TypeOperations._enter(config, model, false, selections[i]); } - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Typing, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: false, }); @@ -711,7 +711,7 @@ export class TypeOperations { } } if (!autoIndentFails) { - return new EditOperationResult(commands, { + return new EditOperationResult(EditOperationType.Typing, commands, { shouldPushStackElementBefore: true, shouldPushStackElementAfter: false, }); @@ -719,36 +719,36 @@ export class TypeOperations { } if (this._isAutoClosingCloseCharType(config, model, selections, ch)) { - return this._runAutoClosingCloseCharType(config, model, selections, ch); + return this._runAutoClosingCloseCharType(prevEditOperationType, config, model, selections, ch); } if (this._isAutoClosingOpenCharType(config, model, selections, ch)) { - return this._runAutoClosingOpenCharType(config, model, selections, ch); + return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch); } if (this._isSurroundSelectionType(config, model, selections, ch)) { - return this._runSurroundSelectionType(config, model, selections, ch); + return this._runSurroundSelectionType(prevEditOperationType, config, model, selections, ch); } // Electric characters make sense only when dealing with a single cursor, // as multiple cursors typing brackets for example would interfer with bracket matching if (this._isTypeInterceptorElectricChar(config, model, selections)) { - const r = this._typeInterceptorElectricChar(config, model, selections[0], ch); + const r = this._typeInterceptorElectricChar(prevEditOperationType, config, model, selections[0], ch); if (r) { return r; } } - return this.typeWithoutInterceptors(config, model, selections, ch); + return this.typeWithoutInterceptors(prevEditOperationType, config, model, selections, ch); } - public static typeWithoutInterceptors(config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], str: string): EditOperationResult { + public static typeWithoutInterceptors(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], str: string): EditOperationResult { let commands: ICommand[] = []; for (let i = 0, len = selections.length; i < len; i++) { commands[i] = new ReplaceCommand(selections[i], str); } - return new EditOperationResult(commands, { - shouldPushStackElementBefore: false, + return new EditOperationResult(EditOperationType.Typing, commands, { + shouldPushStackElementBefore: (prevEditOperationType !== EditOperationType.Typing), shouldPushStackElementAfter: false }); } diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index 497327d1772..f938ec29ad6 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -1453,9 +1453,9 @@ suite('Editor Controller - Regression tests', () => { cursorCommand(cursor, H.Undo); assert.equal(model.getValue(), [ - 'some lines', - 'and more lines', - 'just some text', + ' some lines', + ' and more lines', + ' just some text', ].join('\n'), '002'); cursorCommand(cursor, H.Undo); @@ -1464,6 +1464,13 @@ suite('Editor Controller - Regression tests', () => { 'and more lines', 'just some text', ].join('\n'), '003'); + + cursorCommand(cursor, H.Undo); + assert.equal(model.getValue(), [ + 'some lines', + 'and more lines', + 'just some text', + ].join('\n'), '004'); }); model.dispose(); @@ -3815,3 +3822,204 @@ suite('autoClosingPairs', () => { }); }); }); + +suite('Undo stops', () => { + + test('there is an undo stop between typing and deleting left', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(1, 3, 1, 3)]); + cursorCommand(cursor, H.Type, { text: 'first' }, 'keyboard'); + assert.equal(model.getLineContent(1), 'A first line'); + assertCursor(cursor, new Selection(1, 8, 1, 8)); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(1), 'A fir line'); + assertCursor(cursor, new Selection(1, 6, 1, 6)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A first line'); + assertCursor(cursor, new Selection(1, 8, 1, 8)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A line'); + assertCursor(cursor, new Selection(1, 3, 1, 3)); + }); + }); + + test('there is an undo stop between typing and deleting right', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(1, 3, 1, 3)]); + cursorCommand(cursor, H.Type, { text: 'first' }, 'keyboard'); + assert.equal(model.getLineContent(1), 'A first line'); + assertCursor(cursor, new Selection(1, 8, 1, 8)); + + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(1), 'A firstine'); + assertCursor(cursor, new Selection(1, 8, 1, 8)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A first line'); + assertCursor(cursor, new Selection(1, 8, 1, 8)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A line'); + assertCursor(cursor, new Selection(1, 3, 1, 3)); + }); + }); + + test('there is an undo stop between deleting left and typing', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(2, 8, 2, 8)]); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(2), ' line'); + assertCursor(cursor, new Selection(2, 1, 2, 1)); + + cursorCommand(cursor, H.Type, { text: 'Second' }, 'keyboard'); + assert.equal(model.getLineContent(2), 'Second line'); + assertCursor(cursor, new Selection(2, 7, 2, 7)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), ' line'); + assertCursor(cursor, new Selection(2, 1, 2, 1)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), 'Another line'); + assertCursor(cursor, new Selection(2, 8, 2, 8)); + }); + }); + + test('there is an undo stop between deleting left and deleting right', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(2, 8, 2, 8)]); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(2), ' line'); + assertCursor(cursor, new Selection(2, 1, 2, 1)); + + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(2), ''); + assertCursor(cursor, new Selection(2, 1, 2, 1)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), ' line'); + assertCursor(cursor, new Selection(2, 1, 2, 1)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), 'Another line'); + assertCursor(cursor, new Selection(2, 8, 2, 8)); + }); + }); + + test('there is an undo stop between deleting right and typing', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(2, 9, 2, 9)]); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(2), 'Another '); + assertCursor(cursor, new Selection(2, 9, 2, 9)); + + cursorCommand(cursor, H.Type, { text: 'text' }, 'keyboard'); + assert.equal(model.getLineContent(2), 'Another text'); + assertCursor(cursor, new Selection(2, 13, 2, 13)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), 'Another '); + assertCursor(cursor, new Selection(2, 9, 2, 9)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), 'Another line'); + assertCursor(cursor, new Selection(2, 9, 2, 9)); + }); + }); + + test('there is an undo stop between deleting right and deleting left', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(2, 9, 2, 9)]); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(2), 'Another '); + assertCursor(cursor, new Selection(2, 9, 2, 9)); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(2), 'An'); + assertCursor(cursor, new Selection(2, 3, 2, 3)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), 'Another '); + assertCursor(cursor, new Selection(2, 9, 2, 9)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(2), 'Another line'); + assertCursor(cursor, new Selection(2, 9, 2, 9)); + }); + }); + +}); From f45634df213d3a9713bd51b1e565cf6b9cb1b44e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Oct 2017 16:41:46 -0700 Subject: [PATCH 347/394] Don't prompt for workspace when creating terms with <=1 folder Fixes #36473 --- .../electron-browser/terminalActions.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 13ad6995359..d69f50bfbd0 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -8,7 +8,7 @@ import * as os from 'os'; import { Action, IAction } from 'vs/base/common/actions'; import { EndOfLinePreference } from 'vs/editor/common/editorCommon'; import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'; -import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalService, TERMINAL_PANEL_ID, ITerminalInstance } from 'vs/workbench/parts/terminal/common/terminal'; import { SelectActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { TPromise } from 'vs/base/common/winjs.base'; import { TogglePanelAction } from 'vs/workbench/browser/panel'; @@ -23,6 +23,7 @@ import { TerminalEntry } from 'vs/workbench/parts/terminal/browser/terminalQuick import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { PICK_WORKSPACE_FOLDER_COMMAND } from 'vs/workbench/browser/actions/workspaceActions'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; export const TERMINAL_PICKER_PREFIX = 'term '; @@ -225,15 +226,32 @@ export class CreateNewSelectWorkspaceTerminalAction extends Action { constructor( id: string, label: string, @ITerminalService private terminalService: ITerminalService, - @ICommandService private commandService: ICommandService + @ICommandService private commandService: ICommandService, + @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService ) { super(id, label); this.class = 'terminal-action new'; } public run(event?: any): TPromise { - return this.commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND).then(workspace => { - const instance = this.terminalService.createInstance(workspace ? { cwd: workspace.uri.fsPath } : undefined, true); + const folders = this.workspaceContextService.getWorkspace().folders; + + let instancePromise: TPromise; + if (folders.length <= 1) { + // Allow terminal service to handle the path when there is only a + // single root + instancePromise = TPromise.as(this.terminalService.createInstance(undefined, true)); + } else { + instancePromise = this.commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND).then(workspace => { + if (!workspace) { + // Don't create the instance if the workspace picker was canceled + return null; + } + return this.terminalService.createInstance({ cwd: workspace.uri.fsPath }, true); + }); + } + + return instancePromise.then(instance => { if (!instance) { return TPromise.as(void 0); } From 9d2e663374447b5bb6a26940fcbb39ba12af017d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Oct 2017 17:11:42 -0700 Subject: [PATCH 348/394] Pull in latest xterm.js Includes letterSpacing/rendering coord clean up and .xterm class change Fixes #36599 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index ac4d08222c9..0f5827cf0a1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -596,7 +596,7 @@ "xterm": { "version": "2.9.1", "from": "Tyriar/xterm.js#vscode-release/1.18", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#d57ac8df05ddf04b509505eadc0d408a0b3bfa38" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#e5b11bc3ffad1b66c49e705eac924b87717e313e" }, "yauzl": { "version": "2.8.0", From cda7364a5c7c9201085284dd5ea4a3155a790c69 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Oct 2017 17:14:16 -0700 Subject: [PATCH 349/394] Merge workspace create terminal into regular command With > 1 folder ctrl+shift+tilde will show the selector now Fixes #34163 --- .../electron-browser/terminal.contribution.ts | 4 +--- .../electron-browser/terminalActions.ts | 22 ------------------- .../electron-browser/terminalPanel.ts | 6 ++--- 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index d0771e15cb5..ff053b498b9 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -18,7 +18,7 @@ import { TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFA import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, CreateNewSelectWorkspaceTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; @@ -188,7 +188,6 @@ configurationRegistry.registerConfiguration({ QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, ShowAllCommandsAction.ID, CreateNewTerminalAction.ID, - CreateNewSelectWorkspaceTerminalAction.ID, CopyTerminalSelectionAction.ID, KillTerminalAction.ID, FocusActiveTerminalAction.ID, @@ -281,7 +280,6 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewTermina primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_BACKTICK } }), 'Terminal: Create New Integrated Terminal', category); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewSelectWorkspaceTerminalAction, CreateNewSelectWorkspaceTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (Select Workspace)', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousTerminalAction, FocusPreviousTerminalAction.ID, FocusPreviousTerminalAction.LABEL), 'Terminal: Focus Previous Terminal', category); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index d69f50bfbd0..ce3950c1dbb 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -199,28 +199,6 @@ export class CreateNewTerminalAction extends Action { public static ID = 'workbench.action.terminal.new'; public static LABEL = nls.localize('workbench.action.terminal.new', "Create New Integrated Terminal"); - - constructor( - id: string, label: string, - @ITerminalService private terminalService: ITerminalService - ) { - super(id, label); - } - - public run(event?: any): TPromise { - const instance = this.terminalService.createInstance(undefined, true); - if (!instance) { - return TPromise.as(void 0); - } - this.terminalService.setActiveInstance(instance); - return this.terminalService.showPanel(true); - } -} - -export class CreateNewSelectWorkspaceTerminalAction extends Action { - - public static ID = 'workbench.action.terminal.newSelectWorkspace'; - public static LABEL = nls.localize('workbench.action.terminal.newSelectWorkspace', "Create New Integrated Terminal (Select Workspace)"); public static PANEL_LABEL = nls.localize('workbench.action.terminal.new.short', "New Terminal"); constructor( diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index d382d1f2aa5..e862598502b 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -19,7 +19,7 @@ import { ITerminalService, ITerminalFont, TERMINAL_PANEL_ID } from 'vs/workbench import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { TerminalFindWidget } from './terminalFindWidget'; import { editorHoverBackground, editorHoverBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; -import { KillTerminalAction, CreateNewSelectWorkspaceTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Panel } from 'vs/workbench/browser/panel'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -115,7 +115,7 @@ export class TerminalPanel extends Panel { if (!this._actions) { this._actions = [ this._instantiationService.createInstance(SwitchTerminalInstanceAction, SwitchTerminalInstanceAction.ID, SwitchTerminalInstanceAction.LABEL), - this._instantiationService.createInstance(CreateNewSelectWorkspaceTerminalAction, CreateNewSelectWorkspaceTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.PANEL_LABEL), + this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.PANEL_LABEL), this._instantiationService.createInstance(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.PANEL_LABEL) ]; this._actions.forEach(a => { @@ -129,7 +129,7 @@ export class TerminalPanel extends Panel { if (!this._contextMenuActions) { this._copyContextMenuAction = this._instantiationService.createInstance(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, nls.localize('copy', "Copy")); this._contextMenuActions = [ - this._instantiationService.createInstance(CreateNewSelectWorkspaceTerminalAction, CreateNewSelectWorkspaceTerminalAction.ID, CreateNewSelectWorkspaceTerminalAction.PANEL_LABEL), + this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.PANEL_LABEL), new Separator(), this._copyContextMenuAction, this._instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, nls.localize('paste', "Paste")), From f2094fec06ec62e7fb2bbe3d6e6bba3caaa30b26 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Oct 2017 17:30:10 -0700 Subject: [PATCH 350/394] Move xterm interface typings into module Upstream PR: sourcelair/xterm.js#1072 Fixes #36560 --- src/typings/xterm.d.ts | 318 ++++++++++++++++++++--------------------- 1 file changed, 159 insertions(+), 159 deletions(-) diff --git a/src/typings/xterm.d.ts b/src/typings/xterm.d.ts index ceed656bf3f..40085d10893 100644 --- a/src/typings/xterm.d.ts +++ b/src/typings/xterm.d.ts @@ -7,166 +7,166 @@ * to be stable and consumed by external programs. */ -/** - * An object containing start up options for the terminal. - */ -interface ITerminalOptions { - /** - * A data uri of the sound to use for the bell (needs bellStyle = 'sound'). - */ - bellSound?: string; - - /** - * The type of the bell notification the terminal will use. - */ - bellStyle?: 'none' | 'visual' | 'sound' | 'both'; - - /** - * The number of columns in the terminal. - */ - cols?: number; - - /** - * Whether the cursor blinks. - */ - cursorBlink?: boolean; - - /** - * The style of the cursor. - */ - cursorStyle?: 'block' | 'underline' | 'bar'; - - /** - * Whether input should be disabled. - */ - disableStdin?: boolean; - - /** - * Whether to enable the rendering of bold text. - */ - enableBold?: boolean; - - /** - * The font size used to render text. - */ - fontSize?: number; - - /** - * The font family used to render text. - */ - fontFamily?: string; - - /** - * The line height used to render text. - */ - lineHeight?: number; - - /** - * The number of rows in the terminal. - */ - rows?: number; - - /** - * The amount of scrollback in the terminal. Scrollback is the amount of rows - * that are retained when lines are scrolled beyond the initial viewport. - */ - scrollback?: number; - - /** - * The size of tab stops in the terminal. - */ - tabStopWidth?: number; - - /** - * The color theme of the terminal. - */ - theme?: ITheme; -} - -/** - * Contains colors to theme the terminal with. - */ -interface ITheme { - /** The default foreground color */ - foreground?: string, - /** The default background color */ - background?: string, - /** The cursor color */ - cursor?: string, - /** The selection color (can be transparent) */ - selection?: string, - /** The accent color of the cursor (used as the foreground color for a block cursor) */ - cursorAccent?: string, - /** ANSI black (eg. `\x1b[30m`) */ - black?: string, - /** ANSI red (eg. `\x1b[31m`) */ - red?: string, - /** ANSI green (eg. `\x1b[32m`) */ - green?: string, - /** ANSI yellow (eg. `\x1b[33m`) */ - yellow?: string, - /** ANSI blue (eg. `\x1b[34m`) */ - blue?: string, - /** ANSI magenta (eg. `\x1b[35m`) */ - magenta?: string, - /** ANSI cyan (eg. `\x1b[36m`) */ - cyan?: string, - /** ANSI white (eg. `\x1b[37m`) */ - white?: string, - /** ANSI bright black (eg. `\x1b[1;30m`) */ - brightBlack?: string, - /** ANSI bright red (eg. `\x1b[1;31m`) */ - brightRed?: string, - /** ANSI bright green (eg. `\x1b[1;32m`) */ - brightGreen?: string, - /** ANSI bright yellow (eg. `\x1b[1;33m`) */ - brightYellow?: string, - /** ANSI bright blue (eg. `\x1b[1;34m`) */ - brightBlue?: string, - /** ANSI bright magenta (eg. `\x1b[1;35m`) */ - brightMagenta?: string, - /** ANSI bright cyan (eg. `\x1b[1;36m`) */ - brightCyan?: string, - /** ANSI bright white (eg. `\x1b[1;37m`) */ - brightWhite?: string -} - -/** - * An object containing options for a link matcher. - */ -interface ILinkMatcherOptions { - /** - * The index of the link from the regex.match(text) call. This defaults to 0 - * (for regular expressions without capture groups). - */ - matchIndex?: number; - - /** - * A callback that validates an individual link, returning true if valid and - * false if invalid. - */ - validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; - - /** - * A callback that fires when the mouse hovers over a link for a moment. - */ - tooltipCallback?: (event: MouseEvent, uri: string) => boolean | void; - - /** - * A callback that fires when the mouse leaves a link. Note that this can - * happen even when tooltipCallback hasn't fired for the link yet. - */ - leaveCallback?: (event: MouseEvent, uri: string) => boolean | void; - - /** - * The priority of the link matcher, this defines the order in which the link - * matcher is evaluated relative to others, from highest to lowest. The - * default value is 0. - */ - priority?: number; -} - declare module 'xterm' { + /** + * An object containing start up options for the terminal. + */ + interface ITerminalOptions { + /** + * A data uri of the sound to use for the bell (needs bellStyle = 'sound'). + */ + bellSound?: string; + + /** + * The type of the bell notification the terminal will use. + */ + bellStyle?: 'none' | 'visual' | 'sound' | 'both'; + + /** + * The number of columns in the terminal. + */ + cols?: number; + + /** + * Whether the cursor blinks. + */ + cursorBlink?: boolean; + + /** + * The style of the cursor. + */ + cursorStyle?: 'block' | 'underline' | 'bar'; + + /** + * Whether input should be disabled. + */ + disableStdin?: boolean; + + /** + * Whether to enable the rendering of bold text. + */ + enableBold?: boolean; + + /** + * The font size used to render text. + */ + fontSize?: number; + + /** + * The font family used to render text. + */ + fontFamily?: string; + + /** + * The line height used to render text. + */ + lineHeight?: number; + + /** + * The number of rows in the terminal. + */ + rows?: number; + + /** + * The amount of scrollback in the terminal. Scrollback is the amount of rows + * that are retained when lines are scrolled beyond the initial viewport. + */ + scrollback?: number; + + /** + * The size of tab stops in the terminal. + */ + tabStopWidth?: number; + + /** + * The color theme of the terminal. + */ + theme?: ITheme; + } + + /** + * Contains colors to theme the terminal with. + */ + interface ITheme { + /** The default foreground color */ + foreground?: string, + /** The default background color */ + background?: string, + /** The cursor color */ + cursor?: string, + /** The selection color (can be transparent) */ + selection?: string, + /** The accent color of the cursor (used as the foreground color for a block cursor) */ + cursorAccent?: string, + /** ANSI black (eg. `\x1b[30m`) */ + black?: string, + /** ANSI red (eg. `\x1b[31m`) */ + red?: string, + /** ANSI green (eg. `\x1b[32m`) */ + green?: string, + /** ANSI yellow (eg. `\x1b[33m`) */ + yellow?: string, + /** ANSI blue (eg. `\x1b[34m`) */ + blue?: string, + /** ANSI magenta (eg. `\x1b[35m`) */ + magenta?: string, + /** ANSI cyan (eg. `\x1b[36m`) */ + cyan?: string, + /** ANSI white (eg. `\x1b[37m`) */ + white?: string, + /** ANSI bright black (eg. `\x1b[1;30m`) */ + brightBlack?: string, + /** ANSI bright red (eg. `\x1b[1;31m`) */ + brightRed?: string, + /** ANSI bright green (eg. `\x1b[1;32m`) */ + brightGreen?: string, + /** ANSI bright yellow (eg. `\x1b[1;33m`) */ + brightYellow?: string, + /** ANSI bright blue (eg. `\x1b[1;34m`) */ + brightBlue?: string, + /** ANSI bright magenta (eg. `\x1b[1;35m`) */ + brightMagenta?: string, + /** ANSI bright cyan (eg. `\x1b[1;36m`) */ + brightCyan?: string, + /** ANSI bright white (eg. `\x1b[1;37m`) */ + brightWhite?: string + } + + /** + * An object containing options for a link matcher. + */ + interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + + /** + * A callback that validates an individual link, returning true if valid and + * false if invalid. + */ + validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; + + /** + * A callback that fires when the mouse hovers over a link for a moment. + */ + tooltipCallback?: (event: MouseEvent, uri: string) => boolean | void; + + /** + * A callback that fires when the mouse leaves a link. Note that this can + * happen even when tooltipCallback hasn't fired for the link yet. + */ + leaveCallback?: (event: MouseEvent, uri: string) => boolean | void; + + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; + } + /** * The class that represents an xterm.js terminal. */ From 12277f88d185e233b885f00046dce0d79df50140 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Fri, 20 Oct 2017 17:46:57 -0700 Subject: [PATCH 351/394] Refactoring extensionsTipsService --- .../electron-browser/extensionTipsService.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index cd39fd83d4c..ee2fdca900c 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -45,10 +45,10 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe private _availableRecommendations: { [pattern: string]: string[] } = Object.create(null); private importantRecommendations: { [id: string]: { name: string; pattern: string; } } = Object.create(null); private importantRecommendationsIgnoreList: string[]; - private _allRecommendations: string[]; + private _allRecommendations: string[] = []; private _disposables: IDisposable[] = []; - private _suggestedWorkspaceRecommendedExtensions: string[] = []; + private _allWorkspaceRecommendedExtensions: string[] = []; constructor( @IExtensionGalleryService private _galleryService: IExtensionGalleryService, @@ -82,7 +82,10 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe getWorkspaceRecommendations(): TPromise { const workspace = this.contextService.getWorkspace(); return TPromise.join([this.resolveWorkspaceRecommendations(workspace), ...workspace.folders.map(workspaceFolder => this.resolveWorkspaceFolderRecommendations(workspaceFolder))]) - .then(recommendations => distinct(flatten(recommendations))); + .then(recommendations => { + this._allWorkspaceRecommendedExtensions = distinct(flatten(recommendations)); + return this._allWorkspaceRecommendedExtensions; + }); } private resolveWorkspaceRecommendations(workspace: IWorkspace): TPromise { @@ -114,7 +117,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe .then(result => { const newRecommendations = flatten(result); // Suggest only if atleast one of the newly added recommendtations was not suggested before - if (newRecommendations.some(e => this._suggestedWorkspaceRecommendedExtensions.indexOf(e) === -1)) { + if (newRecommendations.some(e => this._allWorkspaceRecommendedExtensions.indexOf(e) === -1)) { this._suggestWorkspaceRecommendations(); } }); @@ -372,7 +375,6 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ - this._suggestedWorkspaceRecommendedExtensions = allRecommendations; this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'show' }); return action.run(); case 1: From 6fbb99193149eccf24dce8d5652007452226dee4 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Fri, 20 Oct 2017 21:30:43 -0700 Subject: [PATCH 352/394] Do not capture task shortcuts in terminal --- .../terminal/electron-browser/terminal.contribution.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index ff053b498b9..a59abbfbaa3 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -193,6 +193,13 @@ configurationRegistry.registerConfiguration({ FocusActiveTerminalAction.ID, FocusPreviousTerminalAction.ID, FocusNextTerminalAction.ID, + 'workbench.action.tasks.build', + 'workbench.action.tasks.restartTask', + 'workbench.action.tasks.runTask', + 'workbench.action.tasks.showLog', + 'workbench.action.tasks.showTasks', + 'workbench.action.tasks.terminate', + 'workbench.action.tasks.test', 'workbench.action.terminal.focusAtIndex1', 'workbench.action.terminal.focusAtIndex2', 'workbench.action.terminal.focusAtIndex3', From 9418ba5feec1208a6b0991210a06ca23a328100e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Oct 2017 09:52:35 +0200 Subject: [PATCH 353/394] Don't forget to push undo stops when executing edits (#36234) --- .../contrib/indentation/common/indentation.ts | 2 + .../linesOperations/common/linesOperations.ts | 5 +- .../test/common/linesOperations.test.ts | 51 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/indentation/common/indentation.ts b/src/vs/editor/contrib/indentation/common/indentation.ts index cd9add8748f..41fb47db826 100644 --- a/src/vs/editor/contrib/indentation/common/indentation.ts +++ b/src/vs/editor/contrib/indentation/common/indentation.ts @@ -323,7 +323,9 @@ export class ReindentLinesAction extends EditorAction { } let edits = getReindentEditOperations(model, 1, model.getLineCount()); if (edits) { + editor.pushUndoStop(); editor.executeEdits(this.id, edits); + editor.pushUndoStop(); } } } diff --git a/src/vs/editor/contrib/linesOperations/common/linesOperations.ts b/src/vs/editor/contrib/linesOperations/common/linesOperations.ts index 3c5229de450..1b0ef8b7e2f 100644 --- a/src/vs/editor/contrib/linesOperations/common/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/common/linesOperations.ts @@ -407,7 +407,9 @@ export abstract class AbstractDeleteAllToBoundaryAction extends EditorAction { return EditOperation.replace(range, ''); }); + editor.pushUndoStop(); editor.executeEdits(this.id, edits, endCursorState); + editor.pushUndoStop(); } /** @@ -673,8 +675,9 @@ export class JoinLinesAction extends EditorAction { } endCursorState.unshift(endPrimaryCursor); + editor.pushUndoStop(); editor.executeEdits(this.id, edits, endCursorState); - + editor.pushUndoStop(); } } diff --git a/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts index 64c67e2cb9a..3e7578ef9e8 100644 --- a/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts @@ -73,6 +73,32 @@ suite('Editor Contrib - Line Operations', () => { assert.equal(model.getLineContent(5), 'horlworld', '005'); }); }); + + test('issue #36234: should push undo stop', () => { + withMockCodeEditor( + [ + 'one', + 'two', + 'three' + ], {}, (editor, cursor) => { + let model = editor.getModel(); + let deleteAllLeftAction = new DeleteAllLeftAction(); + + editor.setSelection(new Selection(1, 1, 1, 1)); + + editor.trigger('keyboard', Handler.Type, { text: 'Typing some text here on line ' }); + assert.equal(model.getLineContent(1), 'Typing some text here on line one'); + assert.deepEqual(editor.getSelection(), new Selection(1, 31, 1, 31)); + + deleteAllLeftAction.run(null, editor); + assert.equal(model.getLineContent(1), 'one'); + assert.deepEqual(editor.getSelection(), new Selection(1, 1, 1, 1)); + + editor.trigger('keyboard', Handler.Undo, {}); + assert.equal(model.getLineContent(1), 'Typing some text here on line one'); + assert.deepEqual(editor.getSelection(), new Selection(1, 31, 1, 31)); + }); + }); }); suite('JoinLinesAction', () => { @@ -164,6 +190,31 @@ suite('Editor Contrib - Line Operations', () => { assert.deepEqual(editor.getSelection().toString(), new Selection(3, 4, 3, 8).toString(), '003'); }); }); + + test('should push undo stop', function () { + withMockCodeEditor( + [ + 'hello', + 'world' + ], {}, (editor, cursor) => { + let model = editor.getModel(); + let joinLinesAction = new JoinLinesAction(); + + editor.setSelection(new Selection(1, 6, 1, 6)); + + editor.trigger('keyboard', Handler.Type, { text: ' my dear' }); + assert.equal(model.getLineContent(1), 'hello my dear'); + assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); + + joinLinesAction.run(null, editor); + assert.equal(model.getLineContent(1), 'hello my dear world'); + assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); + + editor.trigger('keyboard', Handler.Undo, {}); + assert.equal(model.getLineContent(1), 'hello my dear'); + assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 14)); + }); + }); }); test('transpose', function () { From 8e1402b8aced67f8208c770fa68cbcb2146430eb Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Oct 2017 10:50:58 +0200 Subject: [PATCH 354/394] Fixes #33788: Wrong cursor position when double click to select a word --- .../common/controller/cursorWordOperations.ts | 4 +++- .../test/common/controller/cursor.test.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index 7d8b52b17a3..8f83c1f8621 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -425,7 +425,9 @@ export class WordOperations { let lineNumber = position.lineNumber; let column: number; - if (position.isBeforeOrEqual(cursor.selectionStart.getStartPosition())) { + if (cursor.selectionStart.containsPosition(position)) { + column = cursor.selectionStart.endColumn; + } else if (position.isBeforeOrEqual(cursor.selectionStart.getStartPosition())) { column = startColumn; let possiblePosition = new Position(lineNumber, column); if (cursor.selectionStart.containsPosition(possiblePosition)) { diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index f938ec29ad6..c891a78db07 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -1629,6 +1629,24 @@ suite('Editor Controller - Regression tests', () => { }); }); + test('issue #33788: Wrong cursor position when double click to select a word', () => { + let model = Model.createFromString( + [ + 'Just some text' + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + CoreNavigationCommands.WordSelect.runCoreEditorCommand(cursor, { position: new Position(1, 8) }); + assert.deepEqual(cursor.getSelection(), new Selection(1, 6, 1, 10)); + + CoreNavigationCommands.WordSelectDrag.runCoreEditorCommand(cursor, { position: new Position(1, 8) }); + assert.deepEqual(cursor.getSelection(), new Selection(1, 6, 1, 10)); + }); + + model.dispose(); + }); + test('issue #9675: Undo/Redo adds a stop in between CHN Characters', () => { usingCursor({ text: [ From 47c8925894fedd4bae7962448f7af7ab5ca2e00b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Oct 2017 10:58:34 +0200 Subject: [PATCH 355/394] Insert an undo stop when typing space (#34073) --- .../common/controller/cursorTypeOperations.ts | 14 +++++++++- .../test/common/controller/cursor.test.ts | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index cad7da5a71c..0ffb52bd5af 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -739,7 +739,19 @@ export class TypeOperations { } } - return this.typeWithoutInterceptors(prevEditOperationType, config, model, selections, ch); + // A simple character type + let commands: ICommand[] = []; + for (let i = 0, len = selections.length; i < len; i++) { + commands[i] = new ReplaceCommand(selections[i], ch); + } + let shouldPushStackElementBefore = (prevEditOperationType !== EditOperationType.Typing); + if (ch === ' ') { + shouldPushStackElementBefore = true; + } + return new EditOperationResult(EditOperationType.Typing, commands, { + shouldPushStackElementBefore: shouldPushStackElementBefore, + shouldPushStackElementAfter: false + }); } public static typeWithoutInterceptors(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITokenizedModel, selections: Selection[], str: string): EditOperationResult { diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index c891a78db07..98b3810dec4 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -4040,4 +4040,32 @@ suite('Undo stops', () => { }); }); + test('inserts undo stop when typing space', () => { + let model = Model.createFromString( + [ + 'A line', + 'Another line', + ].join('\n') + ); + + withMockCodeEditor(null, { model: model }, (editor, cursor) => { + cursor.setSelections('test', [new Selection(1, 3, 1, 3)]); + cursorCommand(cursor, H.Type, { text: 'first and interesting' }, 'keyboard'); + assert.equal(model.getLineContent(1), 'A first and interesting line'); + assertCursor(cursor, new Selection(1, 24, 1, 24)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A first and line'); + assertCursor(cursor, new Selection(1, 12, 1, 12)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A first line'); + assertCursor(cursor, new Selection(1, 8, 1, 8)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'A line'); + assertCursor(cursor, new Selection(1, 3, 1, 3)); + }); + }); + }); From 3d42ac09eee93b6ab516f17f5ba2933184056b5c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Oct 2017 15:27:08 +0200 Subject: [PATCH 356/394] Introduce MultiCursorSelectionController --- .../contrib/find/common/findController.ts | 135 +++++++++++------- .../find/test/common/findController.test.ts | 13 +- 2 files changed, 96 insertions(+), 52 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 2c185f6f42d..304f4cf3e76 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -529,61 +529,94 @@ export interface IMultiCursorFindResult { currentMatch: Selection; } +@commonEditorContribution +export class MultiCursorSelectionController extends Disposable implements editorCommon.IEditorContribution { + + private static ID = 'editor.contrib.multiCursorController'; + + private readonly _editor: editorCommon.ICommonCodeEditor; + + public static get(editor: editorCommon.ICommonCodeEditor): MultiCursorSelectionController { + return editor.getContribution(MultiCursorSelectionController.ID); + } + + constructor(editor: editorCommon.ICommonCodeEditor) { + super(); + this._editor = editor; + } + + public dispose(): void { + super.dispose(); + } + + public getId(): string { + return MultiCursorSelectionController.ID; + } + + public multiCursorFind(input: IMultiCursorFindInput): IMultiCursorFindResult { + let controller = CommonFindController.get(this._editor); + if (!controller) { + return null; + } + let state = controller.getState(); + let searchText: string; + let currentMatch: Selection; + + // In any case, if the find widget was ever opened, the options are taken from it + let wholeWord = state.wholeWord; + let matchCase = state.matchCase; + + // Find widget owns what we search for if: + // - focus is not in the editor (i.e. it is in the find widget) + // - and the search widget is visible + // - and the search string is non-empty + if (!this._editor.isFocused() && state.isRevealed && state.searchString.length > 0) { + // Find widget owns what is searched for + searchText = state.searchString; + } else { + // Selection owns what is searched for + let s = this._editor.getSelection(); + + if (s.startLineNumber !== s.endLineNumber && !input.allowMultiline) { + // multiline forbidden + return null; + } + + if (s.isEmpty()) { + // selection is empty => expand to current word + let word = this._editor.getModel().getWordAtPosition(s.getStartPosition()); + if (!word) { + return null; + } + searchText = word.word; + currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn); + } else { + searchText = this._editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); + } + if (input.changeFindSearchString) { + controller.setSearchString(searchText); + } + } + + if (input.highlightFindOptions) { + controller.highlightFindOptions(); + } + + return { + searchText: searchText, + matchCase: matchCase, + wholeWord: wholeWord, + currentMatch: currentMatch + }; + } +} + function multiCursorFind(editor: editorCommon.ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { - let controller = CommonFindController.get(editor); + let controller = MultiCursorSelectionController.get(editor); if (!controller) { return null; } - let state = controller.getState(); - let searchText: string; - let currentMatch: Selection; - - // In any case, if the find widget was ever opened, the options are taken from it - let wholeWord = state.wholeWord; - let matchCase = state.matchCase; - - // Find widget owns what we search for if: - // - focus is not in the editor (i.e. it is in the find widget) - // - and the search widget is visible - // - and the search string is non-empty - if (!editor.isFocused() && state.isRevealed && state.searchString.length > 0) { - // Find widget owns what is searched for - searchText = state.searchString; - } else { - // Selection owns what is searched for - let s = editor.getSelection(); - - if (s.startLineNumber !== s.endLineNumber && !input.allowMultiline) { - // multiline forbidden - return null; - } - - if (s.isEmpty()) { - // selection is empty => expand to current word - let word = editor.getModel().getWordAtPosition(s.getStartPosition()); - if (!word) { - return null; - } - searchText = word.word; - currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn); - } else { - searchText = editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); - } - if (input.changeFindSearchString) { - controller.setSearchString(searchText); - } - } - - if (input.highlightFindOptions) { - controller.highlightFindOptions(); - } - - return { - searchText: searchText, - matchCase: matchCase, - wholeWord: wholeWord, - currentMatch: currentMatch - }; + return controller.multiCursorFind(input); } export abstract class SelectNextFindMatchAction extends EditorAction { diff --git a/src/vs/editor/contrib/find/test/common/findController.test.ts b/src/vs/editor/contrib/find/test/common/findController.test.ts index 20559f5713b..af37560e3cb 100644 --- a/src/vs/editor/contrib/find/test/common/findController.test.ts +++ b/src/vs/editor/contrib/find/test/common/findController.test.ts @@ -15,7 +15,8 @@ import { EndOfLineSequence, ICommonCodeEditor, Handler } from 'vs/editor/common/ import { CommonFindController, FindStartFocusAction, IFindStartOptions, NextMatchFindAction, StartFindAction, SelectHighlightsAction, - AddSelectionToNextFindMatchAction + AddSelectionToNextFindMatchAction, + MultiCursorSelectionController } from 'vs/editor/contrib/find/common/findController'; import { MockCodeEditor, withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { HistoryNavigator } from 'vs/base/common/history'; @@ -196,6 +197,7 @@ suite('FindController', () => { ], { serviceCollection: serviceCollection }, (editor, cursor) => { let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let selectHighlightsAction = new SelectHighlightsAction(); editor.setSelection(new Selection(2, 9, 2, 16)); @@ -211,6 +213,7 @@ suite('FindController', () => { assert.deepEqual(fromRange(editor.getSelection()), [2, 9, 2, 16]); + multiCursorSelectController.dispose(); findController.dispose(); }); }); @@ -394,6 +397,7 @@ suite('FindController', () => { ], { serviceCollection: serviceCollection }, (editor, cursor) => { let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); editor.setSelection(new Selection(2, 1, 3, 4)); @@ -408,6 +412,7 @@ suite('FindController', () => { assert.deepEqual(fromRange(editor.getSelection()), [2, 1, 3, 4]); + multiCursorSelectController.dispose(); findController.dispose(); }); }); @@ -420,6 +425,7 @@ suite('FindController', () => { ], { serviceCollection: serviceCollection }, (editor, cursor) => { let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); editor.setSelection(new Selection(1, 1, 1, 4)); @@ -455,6 +461,7 @@ suite('FindController', () => { 'zz', ].join('\n')); + multiCursorSelectController.dispose(); findController.dispose(); }); }); @@ -475,6 +482,7 @@ suite('FindController', () => { editor.getModel().setEOL(EndOfLineSequence.CRLF); let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); editor.setSelection(new Selection(2, 1, 3, 4)); @@ -489,6 +497,7 @@ suite('FindController', () => { assert.deepEqual(fromRange(editor.getSelection()), [2, 1, 3, 4]); + multiCursorSelectController.dispose(); findController.dispose(); }); }); @@ -560,11 +569,13 @@ suite('FindController', () => { withMockCodeEditor(text, { serviceCollection: serviceCollection }, (editor, cursor) => { let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let action = new AddSelectionToNextFindMatchAction(); callback(editor, action, findController); + multiCursorSelectController.dispose(); findController.dispose(); }); } From 7f356075c3c41b074e32e12535b2249d8723f466 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Oct 2017 15:55:54 +0200 Subject: [PATCH 357/394] Move Ctrl-D related code from contrib/find to contrib/multicursor --- .../contrib/find/common/findController.ts | 672 +---------------- .../editor/contrib/find/common/findModel.ts | 4 - .../find/test/common/findController.test.ts | 421 +---------- .../contrib/multicursor/common/multicursor.ts | 676 +++++++++++++++++- .../test/common/multicursor.test.ts | 432 ++++++++++- .../preferences/browser/preferencesEditor.ts | 2 +- 6 files changed, 1109 insertions(+), 1098 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 304f4cf3e76..4ead5ef999c 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -6,26 +6,18 @@ import * as nls from 'vs/nls'; import { HistoryNavigator } from 'vs/base/common/history'; -import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Disposable } from 'vs/base/common/lifecycle'; import { ContextKeyExpr, RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { Range } from 'vs/editor/common/core/range'; -import { Selection } from 'vs/editor/common/core/selection'; import * as strings from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { editorAction, commonEditorContribution, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; +import { editorAction, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ToggleSearchScopeKeybinding, ShowPreviousFindTermKeybinding, ShowNextFindTermKeybinding } from 'vs/editor/contrib/find/common/findModel'; import { FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState } from 'vs/editor/contrib/find/common/findState'; import { getSelectionSearchString } from 'vs/editor/contrib/find/common/find'; -import { DocumentHighlightProviderRegistry } from 'vs/editor/common/modes'; -import { RunOnceScheduler, Delayer } from 'vs/base/common/async'; -import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; +import { Delayer } from 'vs/base/common/async'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; -import { overviewRulerSelectionHighlightForeground } from 'vs/platform/theme/common/colorRegistry'; -import { themeColorFromId } from 'vs/platform/theme/common/themeService'; -import { Constants } from 'vs/editor/common/core/uint'; export const enum FindStartFocusAction { NoFocusChange, @@ -515,664 +507,6 @@ export class StartFindReplaceAction extends EditorAction { } } -export interface IMultiCursorFindInput { - changeFindSearchString: boolean; - allowMultiline: boolean; - highlightFindOptions: boolean; -} - -export interface IMultiCursorFindResult { - searchText: string; - matchCase: boolean; - wholeWord: boolean; - - currentMatch: Selection; -} - -@commonEditorContribution -export class MultiCursorSelectionController extends Disposable implements editorCommon.IEditorContribution { - - private static ID = 'editor.contrib.multiCursorController'; - - private readonly _editor: editorCommon.ICommonCodeEditor; - - public static get(editor: editorCommon.ICommonCodeEditor): MultiCursorSelectionController { - return editor.getContribution(MultiCursorSelectionController.ID); - } - - constructor(editor: editorCommon.ICommonCodeEditor) { - super(); - this._editor = editor; - } - - public dispose(): void { - super.dispose(); - } - - public getId(): string { - return MultiCursorSelectionController.ID; - } - - public multiCursorFind(input: IMultiCursorFindInput): IMultiCursorFindResult { - let controller = CommonFindController.get(this._editor); - if (!controller) { - return null; - } - let state = controller.getState(); - let searchText: string; - let currentMatch: Selection; - - // In any case, if the find widget was ever opened, the options are taken from it - let wholeWord = state.wholeWord; - let matchCase = state.matchCase; - - // Find widget owns what we search for if: - // - focus is not in the editor (i.e. it is in the find widget) - // - and the search widget is visible - // - and the search string is non-empty - if (!this._editor.isFocused() && state.isRevealed && state.searchString.length > 0) { - // Find widget owns what is searched for - searchText = state.searchString; - } else { - // Selection owns what is searched for - let s = this._editor.getSelection(); - - if (s.startLineNumber !== s.endLineNumber && !input.allowMultiline) { - // multiline forbidden - return null; - } - - if (s.isEmpty()) { - // selection is empty => expand to current word - let word = this._editor.getModel().getWordAtPosition(s.getStartPosition()); - if (!word) { - return null; - } - searchText = word.word; - currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn); - } else { - searchText = this._editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); - } - if (input.changeFindSearchString) { - controller.setSearchString(searchText); - } - } - - if (input.highlightFindOptions) { - controller.highlightFindOptions(); - } - - return { - searchText: searchText, - matchCase: matchCase, - wholeWord: wholeWord, - currentMatch: currentMatch - }; - } -} - -function multiCursorFind(editor: editorCommon.ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { - let controller = MultiCursorSelectionController.get(editor); - if (!controller) { - return null; - } - return controller.multiCursorFind(input); -} - -export abstract class SelectNextFindMatchAction extends EditorAction { - protected _getNextMatch(editor: editorCommon.ICommonCodeEditor): Selection { - let r = multiCursorFind(editor, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { - return null; - } - if (r.currentMatch) { - return r.currentMatch; - } - - let allSelections = editor.getSelections(); - let lastAddedSelection = allSelections[allSelections.length - 1]; - - let nextMatch = editor.getModel().findNextMatch(r.searchText, lastAddedSelection.getEndPosition(), false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false); - - if (!nextMatch) { - return null; - } - - return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn); - } -} - -export abstract class SelectPreviousFindMatchAction extends EditorAction { - protected _getPreviousMatch(editor: editorCommon.ICommonCodeEditor): Selection { - let r = multiCursorFind(editor, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { - return null; - } - if (r.currentMatch) { - return r.currentMatch; - } - - let allSelections = editor.getSelections(); - let lastAddedSelection = allSelections[allSelections.length - 1]; - - let previousMatch = editor.getModel().findPreviousMatch(r.searchText, lastAddedSelection.getStartPosition(), false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false); - - if (!previousMatch) { - return null; - } - - return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn); - } -} - -@editorAction -export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction { - - constructor() { - super({ - id: FIND_IDS.AddSelectionToNextFindMatchAction, - label: nls.localize('addSelectionToNextFindMatch', "Add Selection To Next Find Match"), - alias: 'Add Selection To Next Find Match', - precondition: null, - kbOpts: { - kbExpr: EditorContextKeys.focus, - primary: KeyMod.CtrlCmd | KeyCode.KEY_D - } - }); - } - - public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { - const allSelections = editor.getSelections(); - - // If there are mulitple cursors, handle the case where they do not all select the same text. - if (allSelections.length > 1) { - const model = editor.getModel(); - const controller = CommonFindController.get(editor); - if (!controller) { - return; - } - const findState = controller.getState(); - const caseSensitive = findState.matchCase; - - let selectionsContainSameText = true; - - let selectedText = model.getValueInRange(allSelections[0]); - if (!caseSensitive) { - selectedText = selectedText.toLowerCase(); - } - for (let i = 1, len = allSelections.length; i < len; i++) { - let selection = allSelections[i]; - if (selection.isEmpty()) { - selectionsContainSameText = false; - break; - } - - let thisSelectedText = model.getValueInRange(selection); - if (!caseSensitive) { - thisSelectedText = thisSelectedText.toLowerCase(); - } - if (selectedText !== thisSelectedText) { - selectionsContainSameText = false; - break; - } - } - - if (!selectionsContainSameText) { - let resultingSelections: Selection[] = []; - for (let i = 0, len = allSelections.length; i < len; i++) { - let selection = allSelections[i]; - if (selection.isEmpty()) { - let word = editor.getModel().getWordAtPosition(selection.getStartPosition()); - if (word) { - resultingSelections[i] = new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); - continue; - } - } - resultingSelections[i] = selection; - } - editor.setSelections(resultingSelections); - return; - } - } - - let nextMatch = this._getNextMatch(editor); - - if (!nextMatch) { - return; - } - - editor.setSelections(allSelections.concat(nextMatch)); - editor.revealRangeInCenterIfOutsideViewport(nextMatch, editorCommon.ScrollType.Smooth); - } -} - -@editorAction -export class AddSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction { - - constructor() { - super({ - id: FIND_IDS.AddSelectionToPreviousFindMatchAction, - label: nls.localize('addSelectionToPreviousFindMatch', "Add Selection To Previous Find Match"), - alias: 'Add Selection To Previous Find Match', - precondition: null - }); - } - - public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { - let previousMatch = this._getPreviousMatch(editor); - - if (!previousMatch) { - return; - } - - let allSelections = editor.getSelections(); - editor.setSelections(allSelections.concat(previousMatch)); - editor.revealRangeInCenterIfOutsideViewport(previousMatch, editorCommon.ScrollType.Smooth); - } -} - -@editorAction -export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchAction { - - constructor() { - super({ - id: FIND_IDS.MoveSelectionToNextFindMatchAction, - label: nls.localize('moveSelectionToNextFindMatch', "Move Last Selection To Next Find Match"), - alias: 'Move Last Selection To Next Find Match', - precondition: null, - kbOpts: { - kbExpr: EditorContextKeys.focus, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D) - } - }); - } - - public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { - let nextMatch = this._getNextMatch(editor); - - if (!nextMatch) { - return; - } - - let allSelections = editor.getSelections(); - editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); - editor.revealRangeInCenterIfOutsideViewport(nextMatch, editorCommon.ScrollType.Smooth); - } -} - -@editorAction -export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction { - - constructor() { - super({ - id: FIND_IDS.MoveSelectionToPreviousFindMatchAction, - label: nls.localize('moveSelectionToPreviousFindMatch', "Move Last Selection To Previous Find Match"), - alias: 'Move Last Selection To Previous Find Match', - precondition: null - }); - } - - public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { - let previousMatch = this._getPreviousMatch(editor); - - if (!previousMatch) { - return; - } - - let allSelections = editor.getSelections(); - editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); - editor.revealRangeInCenterIfOutsideViewport(previousMatch, editorCommon.ScrollType.Smooth); - } -} - -export abstract class AbstractSelectHighlightsAction extends EditorAction { - public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void { - const controller = CommonFindController.get(editor); - if (!controller) { - return null; - } - - let matches: editorCommon.FindMatch[] = null; - - const findState = controller.getState(); - if (findState.isRevealed && findState.isRegex && findState.searchString.length > 0) { - - matches = editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); - - } else { - - const r = multiCursorFind(editor, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { - return; - } - - matches = editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); - } - - if (matches.length > 0) { - const editorSelection = editor.getSelection(); - for (let i = 0, len = matches.length; i < len; i++) { - const match = matches[i]; - let intersection = match.range.intersectRanges(editorSelection); - if (intersection) { - // bingo! - matches.splice(i, 1); - matches.unshift(match); - break; - } - } - editor.setSelections(matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn))); - } - } -} - -@editorAction -export class SelectHighlightsAction extends AbstractSelectHighlightsAction { - constructor() { - super({ - id: 'editor.action.selectHighlights', - label: nls.localize('selectAllOccurrencesOfFindMatch', "Select All Occurrences of Find Match"), - alias: 'Select All Occurrences of Find Match', - precondition: null, - kbOpts: { - kbExpr: EditorContextKeys.focus, - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_L - } - }); - } -} - -@editorAction -export class CompatChangeAll extends AbstractSelectHighlightsAction { - constructor() { - super({ - id: 'editor.action.changeAll', - label: nls.localize('changeAll.label', "Change All Occurrences"), - alias: 'Change All Occurrences', - precondition: EditorContextKeys.writable, - kbOpts: { - kbExpr: EditorContextKeys.textFocus, - primary: KeyMod.CtrlCmd | KeyCode.F2 - }, - menuOpts: { - group: '1_modification', - order: 1.2 - } - }); - } -} - -class SelectionHighlighterState { - public readonly lastWordUnderCursor: Selection; - public readonly searchText: string; - public readonly matchCase: boolean; - public readonly wordSeparators: string; - - constructor(lastWordUnderCursor: Selection, searchText: string, matchCase: boolean, wordSeparators: string) { - this.searchText = searchText; - this.matchCase = matchCase; - this.wordSeparators = wordSeparators; - } - - /** - * Everything equals except for `lastWordUnderCursor` - */ - public static softEquals(a: SelectionHighlighterState, b: SelectionHighlighterState): boolean { - if (!a && !b) { - return true; - } - if (!a || !b) { - return false; - } - return ( - a.searchText === b.searchText - && a.matchCase === b.matchCase - && a.wordSeparators === b.wordSeparators - ); - } -} - -@commonEditorContribution -export class SelectionHighlighter extends Disposable implements editorCommon.IEditorContribution { - private static ID = 'editor.contrib.selectionHighlighter'; - - private editor: editorCommon.ICommonCodeEditor; - private _isEnabled: boolean; - private decorations: string[]; - private updateSoon: RunOnceScheduler; - private state: SelectionHighlighterState; - - constructor(editor: editorCommon.ICommonCodeEditor) { - super(); - this.editor = editor; - this._isEnabled = editor.getConfiguration().contribInfo.selectionHighlight; - this.decorations = []; - this.updateSoon = this._register(new RunOnceScheduler(() => this._update(), 300)); - this.state = null; - - this._register(editor.onDidChangeConfiguration((e) => { - this._isEnabled = editor.getConfiguration().contribInfo.selectionHighlight; - })); - this._register(editor.onDidChangeCursorSelection((e: ICursorSelectionChangedEvent) => { - - if (!this._isEnabled) { - // Early exit if nothing needs to be done! - // Leave some form of early exit check here if you wish to continue being a cursor position change listener ;) - return; - } - - if (e.selection.isEmpty()) { - if (e.reason === CursorChangeReason.Explicit) { - if (this.state && (!this.state.lastWordUnderCursor || !this.state.lastWordUnderCursor.containsPosition(e.selection.getStartPosition()))) { - // no longer valid - this._setState(null); - } - this.updateSoon.schedule(); - } else { - this._setState(null); - - } - } else { - this._update(); - } - })); - this._register(editor.onDidChangeModel((e) => { - this._setState(null); - })); - this._register(CommonFindController.get(editor).getState().addChangeListener((e) => { - this._update(); - })); - } - - public getId(): string { - return SelectionHighlighter.ID; - } - - private _update(): void { - this._setState(SelectionHighlighter._createState(this._isEnabled, this.editor)); - } - - private static _createState(isEnabled: boolean, editor: editorCommon.ICommonCodeEditor): SelectionHighlighterState { - const model = editor.getModel(); - if (!model) { - return null; - } - - const config = editor.getConfiguration(); - - let lastWordUnderCursor: Selection = null; - if (!isEnabled) { - return null; - } - - const r = multiCursorFind(editor, { - changeFindSearchString: false, - allowMultiline: false, - highlightFindOptions: false - }); - if (!r) { - return null; - } - - const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model); - if (r.currentMatch) { - // This is an empty selection - if (hasFindOccurrences) { - // Do not interfere with semantic word highlighting in the no selection case - return null; - } - - if (!config.contribInfo.occurrencesHighlight) { - return null; - } - - lastWordUnderCursor = r.currentMatch; - } - if (/^[ \t]+$/.test(r.searchText)) { - // whitespace only selection - return null; - } - if (r.searchText.length > 200) { - // very long selection - return null; - } - - const controller = CommonFindController.get(editor); - if (!controller) { - return null; - } - const findState = controller.getState(); - const caseSensitive = findState.matchCase; - - const selections = editor.getSelections(); - let firstSelectedText = model.getValueInRange(selections[0]); - if (!caseSensitive) { - firstSelectedText = firstSelectedText.toLowerCase(); - } - for (let i = 1; i < selections.length; i++) { - let selectedText = model.getValueInRange(selections[i]); - if (!caseSensitive) { - selectedText = selectedText.toLowerCase(); - } - if (firstSelectedText !== selectedText) { - // not all selections have the same text - return null; - } - } - - // Return early if the find widget shows the exact same matches - if (findState.isRevealed) { - let findStateSearchString = findState.searchString; - if (!caseSensitive) { - findStateSearchString = findStateSearchString.toLowerCase(); - } - - let mySearchString = r.searchText; - if (!caseSensitive) { - mySearchString = mySearchString.toLowerCase(); - } - - if (findStateSearchString === mySearchString && r.matchCase === findState.matchCase && r.wholeWord === findState.wholeWord && !findState.isRegex) { - return null; - } - } - - return new SelectionHighlighterState(lastWordUnderCursor, r.searchText, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null); - } - - - private _setState(state: SelectionHighlighterState): void { - if (SelectionHighlighterState.softEquals(this.state, state)) { - this.state = state; - return; - } - this.state = state; - - if (!this.state) { - if (this.decorations.length > 0) { - this.decorations = this.editor.deltaDecorations(this.decorations, []); - } - return; - } - - const model = this.editor.getModel(); - const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model); - - let allMatches = model.findMatches(this.state.searchText, true, false, this.state.matchCase, this.state.wordSeparators, false).map(m => m.range); - allMatches.sort(Range.compareRangesUsingStarts); - - let selections = this.editor.getSelections(); - selections.sort(Range.compareRangesUsingStarts); - - // do not overlap with selection (issue #64 and #512) - let matches: Range[] = []; - for (let i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len;) { - const match = allMatches[i]; - - if (j >= lenJ) { - // finished all editor selections - matches.push(match); - i++; - } else { - const cmp = Range.compareRangesUsingStarts(match, selections[j]); - if (cmp < 0) { - // match is before sel - matches.push(match); - i++; - } else if (cmp > 0) { - // sel is before match - j++; - } else { - // sel is equal to match - i++; - j++; - } - } - } - - const decorations = matches.map(r => { - return { - range: r, - // Show in overviewRuler only if model has no semantic highlighting - options: (hasFindOccurrences ? SelectionHighlighter._SELECTION_HIGHLIGHT : SelectionHighlighter._SELECTION_HIGHLIGHT_OVERVIEW) - }; - }); - - this.decorations = this.editor.deltaDecorations(this.decorations, decorations); - } - - private static _SELECTION_HIGHLIGHT_OVERVIEW = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - className: 'selectionHighlight', - overviewRuler: { - color: themeColorFromId(overviewRulerSelectionHighlightForeground), - darkColor: themeColorFromId(overviewRulerSelectionHighlightForeground), - position: editorCommon.OverviewRulerLane.Center - } - }); - - private static _SELECTION_HIGHLIGHT = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - className: 'selectionHighlight', - }); - - public dispose(): void { - this._setState(null); - super.dispose(); - } -} @editorAction export class ShowNextFindTermAction extends MatchFindAction { diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 573eba89a13..1536e8c9541 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -50,10 +50,6 @@ export const FIND_IDS = { PreviousMatchFindAction: 'editor.action.previousMatchFindAction', NextSelectionMatchFindAction: 'editor.action.nextSelectionMatchFindAction', PreviousSelectionMatchFindAction: 'editor.action.previousSelectionMatchFindAction', - AddSelectionToNextFindMatchAction: 'editor.action.addSelectionToNextFindMatch', - AddSelectionToPreviousFindMatchAction: 'editor.action.addSelectionToPreviousFindMatch', - MoveSelectionToNextFindMatchAction: 'editor.action.moveSelectionToNextFindMatch', - MoveSelectionToPreviousFindMatchAction: 'editor.action.moveSelectionToPreviousFindMatch', StartFindReplaceAction: 'editor.action.startFindReplaceAction', CloseFindWidgetCommand: 'closeFindWidget', ToggleCaseSensitiveCommand: 'toggleFindCaseSensitive', diff --git a/src/vs/editor/contrib/find/test/common/findController.test.ts b/src/vs/editor/contrib/find/test/common/findController.test.ts index af37560e3cb..323f3f0ce42 100644 --- a/src/vs/editor/contrib/find/test/common/findController.test.ts +++ b/src/vs/editor/contrib/find/test/common/findController.test.ts @@ -11,21 +11,16 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import { Range } from 'vs/editor/common/core/range'; -import { EndOfLineSequence, ICommonCodeEditor, Handler } from 'vs/editor/common/editorCommon'; -import { - CommonFindController, FindStartFocusAction, IFindStartOptions, - NextMatchFindAction, StartFindAction, SelectHighlightsAction, - AddSelectionToNextFindMatchAction, - MultiCursorSelectionController -} from 'vs/editor/contrib/find/common/findController'; -import { MockCodeEditor, withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; +import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; +import { CommonFindController, FindStartFocusAction, IFindStartOptions, NextMatchFindAction, StartFindAction } from 'vs/editor/contrib/find/common/findController'; +import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { HistoryNavigator } from 'vs/base/common/history'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { Delayer } from 'vs/base/common/async'; -class TestFindController extends CommonFindController { +export class TestFindController extends CommonFindController { public hasFocus: boolean; public delayUpdateHistory: boolean = false; @@ -189,62 +184,6 @@ suite('FindController', () => { }); }); - test('issue #8817: Cursor position changes when you cancel multicursor', () => { - withMockCodeEditor([ - 'var x = (3 * 5)', - 'var y = (3 * 5)', - 'var z = (3 * 5)', - ], { serviceCollection: serviceCollection }, (editor, cursor) => { - - let findController = editor.registerAndInstantiateContribution(TestFindController); - let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); - let selectHighlightsAction = new SelectHighlightsAction(); - - editor.setSelection(new Selection(2, 9, 2, 16)); - - selectHighlightsAction.run(null, editor); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [2, 9, 2, 16], - [1, 9, 1, 16], - [3, 9, 3, 16], - ]); - - editor.trigger('test', 'removeSecondaryCursors', null); - - assert.deepEqual(fromRange(editor.getSelection()), [2, 9, 2, 16]); - - multiCursorSelectController.dispose(); - findController.dispose(); - }); - }); - - test('issue #5400: "Select All Occurrences of Find Match" does not select all if find uses regex', () => { - withMockCodeEditor([ - 'something', - 'someething', - 'someeething', - 'nothing' - ], { serviceCollection: serviceCollection }, (editor, cursor) => { - - let findController = editor.registerAndInstantiateContribution(TestFindController); - let selectHighlightsAction = new SelectHighlightsAction(); - - editor.setSelection(new Selection(1, 1, 1, 1)); - findController.getState().change({ searchString: 'some+thing', isRegex: true, isRevealed: true }, false); - - selectHighlightsAction.run(null, editor); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [1, 1, 1, 10], - [2, 1, 2, 11], - [3, 1, 3, 12], - ]); - - assert.equal(findController.getState().searchString, 'some+thing'); - - findController.dispose(); - }); - }); - test('issue #9043: Clear search scope when find widget is hidden', () => { withMockCodeEditor([ 'var x = (3 * 5)', @@ -383,125 +322,6 @@ suite('FindController', () => { }); }); - test('AddSelectionToNextFindMatchAction can work with multiline', () => { - withMockCodeEditor([ - '', - 'qwe', - 'rty', - '', - 'qwe', - '', - 'rty', - 'qwe', - 'rty' - ], { serviceCollection: serviceCollection }, (editor, cursor) => { - - let findController = editor.registerAndInstantiateContribution(TestFindController); - let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); - let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); - - editor.setSelection(new Selection(2, 1, 3, 4)); - - addSelectionToNextFindMatch.run(null, editor); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [2, 1, 3, 4], - [8, 1, 9, 4] - ]); - - editor.trigger('test', 'removeSecondaryCursors', null); - - assert.deepEqual(fromRange(editor.getSelection()), [2, 1, 3, 4]); - - multiCursorSelectController.dispose(); - findController.dispose(); - }); - }); - - test('issue #6661: AddSelectionToNextFindMatchAction can work with touching ranges', () => { - withMockCodeEditor([ - 'abcabc', - 'abc', - 'abcabc', - ], { serviceCollection: serviceCollection }, (editor, cursor) => { - - let findController = editor.registerAndInstantiateContribution(TestFindController); - let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); - let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); - - editor.setSelection(new Selection(1, 1, 1, 4)); - - addSelectionToNextFindMatch.run(null, editor); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [1, 1, 1, 4], - [1, 4, 1, 7] - ]); - - addSelectionToNextFindMatch.run(null, editor); - addSelectionToNextFindMatch.run(null, editor); - addSelectionToNextFindMatch.run(null, editor); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [1, 1, 1, 4], - [1, 4, 1, 7], - [2, 1, 2, 4], - [3, 1, 3, 4], - [3, 4, 3, 7] - ]); - - editor.trigger('test', Handler.Type, { text: 'z' }); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [1, 2, 1, 2], - [1, 3, 1, 3], - [2, 2, 2, 2], - [3, 2, 3, 2], - [3, 3, 3, 3] - ]); - assert.equal(editor.getValue(), [ - 'zz', - 'z', - 'zz', - ].join('\n')); - - multiCursorSelectController.dispose(); - findController.dispose(); - }); - }); - - test('issue #23541: Multiline Ctrl+D does not work in CRLF files', () => { - withMockCodeEditor([ - '', - 'qwe', - 'rty', - '', - 'qwe', - '', - 'rty', - 'qwe', - 'rty' - ], { serviceCollection: serviceCollection }, (editor, cursor) => { - - editor.getModel().setEOL(EndOfLineSequence.CRLF); - - let findController = editor.registerAndInstantiateContribution(TestFindController); - let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); - let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); - - editor.setSelection(new Selection(2, 1, 3, 4)); - - addSelectionToNextFindMatch.run(null, editor); - assert.deepEqual(editor.getSelections().map(fromRange), [ - [2, 1, 3, 4], - [8, 1, 9, 4] - ]); - - editor.trigger('test', 'removeSecondaryCursors', null); - - assert.deepEqual(fromRange(editor.getSelection()), [2, 1, 3, 4]); - - multiCursorSelectController.dispose(); - findController.dispose(); - }); - }); - test('issue #18111: Regex replace with single space replaces with no space', () => { withMockCodeEditor([ 'HRESULT OnAmbientPropertyChange(DISPID dispid);' @@ -564,239 +384,6 @@ suite('FindController', () => { } return result; } - - function testAddSelectionToNextFindMatchAction(text: string[], callback: (editor: MockCodeEditor, action: AddSelectionToNextFindMatchAction, findController: TestFindController) => void): void { - withMockCodeEditor(text, { serviceCollection: serviceCollection }, (editor, cursor) => { - - let findController = editor.registerAndInstantiateContribution(TestFindController); - let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); - - let action = new AddSelectionToNextFindMatchAction(); - - callback(editor, action, findController); - - multiCursorSelectController.dispose(); - findController.dispose(); - }); - } - - test('AddSelectionToNextFindMatchAction starting with single collapsed selection', () => { - const text = [ - 'abc pizza', - 'abc house', - 'abc bar' - ]; - testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { - editor.setSelections([ - new Selection(1, 2, 1, 2), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - }); - }); - - test('AddSelectionToNextFindMatchAction starting with two selections, one being collapsed 1)', () => { - const text = [ - 'abc pizza', - 'abc house', - 'abc bar' - ]; - testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { - editor.setSelections([ - new Selection(1, 1, 1, 4), - new Selection(2, 2, 2, 2), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - }); - }); - - test('AddSelectionToNextFindMatchAction starting with two selections, one being collapsed 2)', () => { - const text = [ - 'abc pizza', - 'abc house', - 'abc bar' - ]; - testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { - editor.setSelections([ - new Selection(1, 2, 1, 2), - new Selection(2, 1, 2, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - }); - }); - - test('AddSelectionToNextFindMatchAction starting with all collapsed selections', () => { - const text = [ - 'abc pizza', - 'abc house', - 'abc bar' - ]; - testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { - editor.setSelections([ - new Selection(1, 2, 1, 2), - new Selection(2, 2, 2, 2), - new Selection(3, 1, 3, 1), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 4), - new Selection(2, 1, 2, 4), - new Selection(3, 1, 3, 4), - ]); - }); - }); - - test('AddSelectionToNextFindMatchAction starting with all collapsed selections on different words', () => { - const text = [ - 'abc pizza', - 'abc house', - 'abc bar' - ]; - testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { - editor.setSelections([ - new Selection(1, 6, 1, 6), - new Selection(2, 6, 2, 6), - new Selection(3, 6, 3, 6), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 5, 1, 10), - new Selection(2, 5, 2, 10), - new Selection(3, 5, 3, 8), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 5, 1, 10), - new Selection(2, 5, 2, 10), - new Selection(3, 5, 3, 8), - ]); - }); - }); - - test('issue #20651: AddSelectionToNextFindMatchAction case insensitive', () => { - const text = [ - 'test', - 'testte', - 'Test', - 'testte', - 'test' - ]; - testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { - editor.setSelections([ - new Selection(1, 1, 1, 5), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 5), - new Selection(2, 1, 2, 5), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 5), - new Selection(2, 1, 2, 5), - new Selection(3, 1, 3, 5), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 5), - new Selection(2, 1, 2, 5), - new Selection(3, 1, 3, 5), - new Selection(4, 1, 4, 5), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 5), - new Selection(2, 1, 2, 5), - new Selection(3, 1, 3, 5), - new Selection(4, 1, 4, 5), - new Selection(5, 1, 5, 5), - ]); - - action.run(null, editor); - assert.deepEqual(editor.getSelections(), [ - new Selection(1, 1, 1, 5), - new Selection(2, 1, 2, 5), - new Selection(3, 1, 3, 5), - new Selection(4, 1, 4, 5), - new Selection(5, 1, 5, 5), - ]); - }); - }); }); suite('FindController query options persistence', () => { diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index 0f6b2fdec41..ca4404ee09a 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -5,14 +5,23 @@ 'use strict'; import * as nls from 'vs/nls'; -import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { ICommonCodeEditor, ScrollType } from 'vs/editor/common/editorCommon'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { ICommonCodeEditor, ScrollType, IEditorContribution, FindMatch, TrackedRangeStickiness, OverviewRulerLane } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions'; +import { editorAction, commonEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions'; +import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; +import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { CursorMoveCommands } from 'vs/editor/common/controller/cursorMoveCommands'; import { CursorState, RevealTarget } from 'vs/editor/common/controller/cursorCommon'; +import { Constants } from 'vs/editor/common/core/uint'; +import { DocumentHighlightProviderRegistry } from 'vs/editor/common/modes'; +import { CommonFindController } from 'vs/editor/contrib/find/common/findController'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; +import { overviewRulerSelectionHighlightForeground } from 'vs/platform/theme/common/colorRegistry'; +import { themeColorFromId } from 'vs/platform/theme/common/themeService'; @editorAction export class InsertCursorAbove extends EditorAction { @@ -139,3 +148,662 @@ class InsertCursorAtEndOfEachLineSelected extends EditorAction { } } } + +export interface IMultiCursorFindInput { + changeFindSearchString: boolean; + allowMultiline: boolean; + highlightFindOptions: boolean; +} + +export interface IMultiCursorFindResult { + searchText: string; + matchCase: boolean; + wholeWord: boolean; + + currentMatch: Selection; +} + +@commonEditorContribution +export class MultiCursorSelectionController extends Disposable implements IEditorContribution { + + private static ID = 'editor.contrib.multiCursorController'; + + private readonly _editor: ICommonCodeEditor; + + public static get(editor: ICommonCodeEditor): MultiCursorSelectionController { + return editor.getContribution(MultiCursorSelectionController.ID); + } + + constructor(editor: ICommonCodeEditor) { + super(); + this._editor = editor; + } + + public dispose(): void { + super.dispose(); + } + + public getId(): string { + return MultiCursorSelectionController.ID; + } + + public multiCursorFind(input: IMultiCursorFindInput): IMultiCursorFindResult { + let controller = CommonFindController.get(this._editor); + if (!controller) { + return null; + } + let state = controller.getState(); + let searchText: string; + let currentMatch: Selection; + + // In any case, if the find widget was ever opened, the options are taken from it + let wholeWord = state.wholeWord; + let matchCase = state.matchCase; + + // Find widget owns what we search for if: + // - focus is not in the editor (i.e. it is in the find widget) + // - and the search widget is visible + // - and the search string is non-empty + if (!this._editor.isFocused() && state.isRevealed && state.searchString.length > 0) { + // Find widget owns what is searched for + searchText = state.searchString; + } else { + // Selection owns what is searched for + let s = this._editor.getSelection(); + + if (s.startLineNumber !== s.endLineNumber && !input.allowMultiline) { + // multiline forbidden + return null; + } + + if (s.isEmpty()) { + // selection is empty => expand to current word + let word = this._editor.getModel().getWordAtPosition(s.getStartPosition()); + if (!word) { + return null; + } + searchText = word.word; + currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn); + } else { + searchText = this._editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); + } + if (input.changeFindSearchString) { + controller.setSearchString(searchText); + } + } + + if (input.highlightFindOptions) { + controller.highlightFindOptions(); + } + + return { + searchText: searchText, + matchCase: matchCase, + wholeWord: wholeWord, + currentMatch: currentMatch + }; + } +} + +function multiCursorFind(editor: ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { + let controller = MultiCursorSelectionController.get(editor); + if (!controller) { + return null; + } + return controller.multiCursorFind(input); +} + +export abstract class SelectNextFindMatchAction extends EditorAction { + protected _getNextMatch(editor: ICommonCodeEditor): Selection { + let r = multiCursorFind(editor, { + changeFindSearchString: true, + allowMultiline: true, + highlightFindOptions: true + }); + if (!r) { + return null; + } + if (r.currentMatch) { + return r.currentMatch; + } + + let allSelections = editor.getSelections(); + let lastAddedSelection = allSelections[allSelections.length - 1]; + + let nextMatch = editor.getModel().findNextMatch(r.searchText, lastAddedSelection.getEndPosition(), false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false); + + if (!nextMatch) { + return null; + } + + return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn); + } +} + +export abstract class SelectPreviousFindMatchAction extends EditorAction { + protected _getPreviousMatch(editor: ICommonCodeEditor): Selection { + let r = multiCursorFind(editor, { + changeFindSearchString: true, + allowMultiline: true, + highlightFindOptions: true + }); + if (!r) { + return null; + } + if (r.currentMatch) { + return r.currentMatch; + } + + let allSelections = editor.getSelections(); + let lastAddedSelection = allSelections[allSelections.length - 1]; + + let previousMatch = editor.getModel().findPreviousMatch(r.searchText, lastAddedSelection.getStartPosition(), false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false); + + if (!previousMatch) { + return null; + } + + return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn); + } +} + +@editorAction +export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction { + + constructor() { + super({ + id: 'editor.action.addSelectionToNextFindMatch', + label: nls.localize('addSelectionToNextFindMatch', "Add Selection To Next Find Match"), + alias: 'Add Selection To Next Find Match', + precondition: null, + kbOpts: { + kbExpr: EditorContextKeys.focus, + primary: KeyMod.CtrlCmd | KeyCode.KEY_D + } + }); + } + + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + const allSelections = editor.getSelections(); + + // If there are mulitple cursors, handle the case where they do not all select the same text. + if (allSelections.length > 1) { + const model = editor.getModel(); + const controller = CommonFindController.get(editor); + if (!controller) { + return; + } + const findState = controller.getState(); + const caseSensitive = findState.matchCase; + + let selectionsContainSameText = true; + + let selectedText = model.getValueInRange(allSelections[0]); + if (!caseSensitive) { + selectedText = selectedText.toLowerCase(); + } + for (let i = 1, len = allSelections.length; i < len; i++) { + let selection = allSelections[i]; + if (selection.isEmpty()) { + selectionsContainSameText = false; + break; + } + + let thisSelectedText = model.getValueInRange(selection); + if (!caseSensitive) { + thisSelectedText = thisSelectedText.toLowerCase(); + } + if (selectedText !== thisSelectedText) { + selectionsContainSameText = false; + break; + } + } + + if (!selectionsContainSameText) { + let resultingSelections: Selection[] = []; + for (let i = 0, len = allSelections.length; i < len; i++) { + let selection = allSelections[i]; + if (selection.isEmpty()) { + let word = editor.getModel().getWordAtPosition(selection.getStartPosition()); + if (word) { + resultingSelections[i] = new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); + continue; + } + } + resultingSelections[i] = selection; + } + editor.setSelections(resultingSelections); + return; + } + } + + let nextMatch = this._getNextMatch(editor); + + if (!nextMatch) { + return; + } + + editor.setSelections(allSelections.concat(nextMatch)); + editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + } +} + +@editorAction +export class AddSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction { + + constructor() { + super({ + id: 'editor.action.addSelectionToPreviousFindMatch', + label: nls.localize('addSelectionToPreviousFindMatch', "Add Selection To Previous Find Match"), + alias: 'Add Selection To Previous Find Match', + precondition: null + }); + } + + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + let previousMatch = this._getPreviousMatch(editor); + + if (!previousMatch) { + return; + } + + let allSelections = editor.getSelections(); + editor.setSelections(allSelections.concat(previousMatch)); + editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + } +} + +@editorAction +export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchAction { + + constructor() { + super({ + id: 'editor.action.moveSelectionToNextFindMatch', + label: nls.localize('moveSelectionToNextFindMatch', "Move Last Selection To Next Find Match"), + alias: 'Move Last Selection To Next Find Match', + precondition: null, + kbOpts: { + kbExpr: EditorContextKeys.focus, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D) + } + }); + } + + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + let nextMatch = this._getNextMatch(editor); + + if (!nextMatch) { + return; + } + + let allSelections = editor.getSelections(); + editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); + editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + } +} + +@editorAction +export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction { + + constructor() { + super({ + id: 'editor.action.moveSelectionToPreviousFindMatch', + label: nls.localize('moveSelectionToPreviousFindMatch', "Move Last Selection To Previous Find Match"), + alias: 'Move Last Selection To Previous Find Match', + precondition: null + }); + } + + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + let previousMatch = this._getPreviousMatch(editor); + + if (!previousMatch) { + return; + } + + let allSelections = editor.getSelections(); + editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); + editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + } +} + +export abstract class AbstractSelectHighlightsAction extends EditorAction { + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + const controller = CommonFindController.get(editor); + if (!controller) { + return null; + } + + let matches: FindMatch[] = null; + + const findState = controller.getState(); + if (findState.isRevealed && findState.isRegex && findState.searchString.length > 0) { + + matches = editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); + + } else { + + const r = multiCursorFind(editor, { + changeFindSearchString: true, + allowMultiline: true, + highlightFindOptions: true + }); + if (!r) { + return; + } + + matches = editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); + } + + if (matches.length > 0) { + const editorSelection = editor.getSelection(); + for (let i = 0, len = matches.length; i < len; i++) { + const match = matches[i]; + let intersection = match.range.intersectRanges(editorSelection); + if (intersection) { + // bingo! + matches.splice(i, 1); + matches.unshift(match); + break; + } + } + editor.setSelections(matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn))); + } + } +} + +@editorAction +export class SelectHighlightsAction extends AbstractSelectHighlightsAction { + constructor() { + super({ + id: 'editor.action.selectHighlights', + label: nls.localize('selectAllOccurrencesOfFindMatch', "Select All Occurrences of Find Match"), + alias: 'Select All Occurrences of Find Match', + precondition: null, + kbOpts: { + kbExpr: EditorContextKeys.focus, + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_L + } + }); + } +} + +@editorAction +export class CompatChangeAll extends AbstractSelectHighlightsAction { + constructor() { + super({ + id: 'editor.action.changeAll', + label: nls.localize('changeAll.label', "Change All Occurrences"), + alias: 'Change All Occurrences', + precondition: EditorContextKeys.writable, + kbOpts: { + kbExpr: EditorContextKeys.textFocus, + primary: KeyMod.CtrlCmd | KeyCode.F2 + }, + menuOpts: { + group: '1_modification', + order: 1.2 + } + }); + } +} + +class SelectionHighlighterState { + public readonly lastWordUnderCursor: Selection; + public readonly searchText: string; + public readonly matchCase: boolean; + public readonly wordSeparators: string; + + constructor(lastWordUnderCursor: Selection, searchText: string, matchCase: boolean, wordSeparators: string) { + this.searchText = searchText; + this.matchCase = matchCase; + this.wordSeparators = wordSeparators; + } + + /** + * Everything equals except for `lastWordUnderCursor` + */ + public static softEquals(a: SelectionHighlighterState, b: SelectionHighlighterState): boolean { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return ( + a.searchText === b.searchText + && a.matchCase === b.matchCase + && a.wordSeparators === b.wordSeparators + ); + } +} + +@commonEditorContribution +export class SelectionHighlighter extends Disposable implements IEditorContribution { + private static ID = 'editor.contrib.selectionHighlighter'; + + private editor: ICommonCodeEditor; + private _isEnabled: boolean; + private decorations: string[]; + private updateSoon: RunOnceScheduler; + private state: SelectionHighlighterState; + + constructor(editor: ICommonCodeEditor) { + super(); + this.editor = editor; + this._isEnabled = editor.getConfiguration().contribInfo.selectionHighlight; + this.decorations = []; + this.updateSoon = this._register(new RunOnceScheduler(() => this._update(), 300)); + this.state = null; + + this._register(editor.onDidChangeConfiguration((e) => { + this._isEnabled = editor.getConfiguration().contribInfo.selectionHighlight; + })); + this._register(editor.onDidChangeCursorSelection((e: ICursorSelectionChangedEvent) => { + + if (!this._isEnabled) { + // Early exit if nothing needs to be done! + // Leave some form of early exit check here if you wish to continue being a cursor position change listener ;) + return; + } + + if (e.selection.isEmpty()) { + if (e.reason === CursorChangeReason.Explicit) { + if (this.state && (!this.state.lastWordUnderCursor || !this.state.lastWordUnderCursor.containsPosition(e.selection.getStartPosition()))) { + // no longer valid + this._setState(null); + } + this.updateSoon.schedule(); + } else { + this._setState(null); + + } + } else { + this._update(); + } + })); + this._register(editor.onDidChangeModel((e) => { + this._setState(null); + })); + this._register(CommonFindController.get(editor).getState().addChangeListener((e) => { + this._update(); + })); + } + + public getId(): string { + return SelectionHighlighter.ID; + } + + private _update(): void { + this._setState(SelectionHighlighter._createState(this._isEnabled, this.editor)); + } + + private static _createState(isEnabled: boolean, editor: ICommonCodeEditor): SelectionHighlighterState { + const model = editor.getModel(); + if (!model) { + return null; + } + + const config = editor.getConfiguration(); + + let lastWordUnderCursor: Selection = null; + if (!isEnabled) { + return null; + } + + const r = multiCursorFind(editor, { + changeFindSearchString: false, + allowMultiline: false, + highlightFindOptions: false + }); + if (!r) { + return null; + } + + const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model); + if (r.currentMatch) { + // This is an empty selection + if (hasFindOccurrences) { + // Do not interfere with semantic word highlighting in the no selection case + return null; + } + + if (!config.contribInfo.occurrencesHighlight) { + return null; + } + + lastWordUnderCursor = r.currentMatch; + } + if (/^[ \t]+$/.test(r.searchText)) { + // whitespace only selection + return null; + } + if (r.searchText.length > 200) { + // very long selection + return null; + } + + const controller = CommonFindController.get(editor); + if (!controller) { + return null; + } + const findState = controller.getState(); + const caseSensitive = findState.matchCase; + + const selections = editor.getSelections(); + let firstSelectedText = model.getValueInRange(selections[0]); + if (!caseSensitive) { + firstSelectedText = firstSelectedText.toLowerCase(); + } + for (let i = 1; i < selections.length; i++) { + let selectedText = model.getValueInRange(selections[i]); + if (!caseSensitive) { + selectedText = selectedText.toLowerCase(); + } + if (firstSelectedText !== selectedText) { + // not all selections have the same text + return null; + } + } + + // Return early if the find widget shows the exact same matches + if (findState.isRevealed) { + let findStateSearchString = findState.searchString; + if (!caseSensitive) { + findStateSearchString = findStateSearchString.toLowerCase(); + } + + let mySearchString = r.searchText; + if (!caseSensitive) { + mySearchString = mySearchString.toLowerCase(); + } + + if (findStateSearchString === mySearchString && r.matchCase === findState.matchCase && r.wholeWord === findState.wholeWord && !findState.isRegex) { + return null; + } + } + + return new SelectionHighlighterState(lastWordUnderCursor, r.searchText, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null); + } + + + private _setState(state: SelectionHighlighterState): void { + if (SelectionHighlighterState.softEquals(this.state, state)) { + this.state = state; + return; + } + this.state = state; + + if (!this.state) { + if (this.decorations.length > 0) { + this.decorations = this.editor.deltaDecorations(this.decorations, []); + } + return; + } + + const model = this.editor.getModel(); + const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model); + + let allMatches = model.findMatches(this.state.searchText, true, false, this.state.matchCase, this.state.wordSeparators, false).map(m => m.range); + allMatches.sort(Range.compareRangesUsingStarts); + + let selections = this.editor.getSelections(); + selections.sort(Range.compareRangesUsingStarts); + + // do not overlap with selection (issue #64 and #512) + let matches: Range[] = []; + for (let i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len;) { + const match = allMatches[i]; + + if (j >= lenJ) { + // finished all editor selections + matches.push(match); + i++; + } else { + const cmp = Range.compareRangesUsingStarts(match, selections[j]); + if (cmp < 0) { + // match is before sel + matches.push(match); + i++; + } else if (cmp > 0) { + // sel is before match + j++; + } else { + // sel is equal to match + i++; + j++; + } + } + } + + const decorations = matches.map(r => { + return { + range: r, + // Show in overviewRuler only if model has no semantic highlighting + options: (hasFindOccurrences ? SelectionHighlighter._SELECTION_HIGHLIGHT : SelectionHighlighter._SELECTION_HIGHLIGHT_OVERVIEW) + }; + }); + + this.decorations = this.editor.deltaDecorations(this.decorations, decorations); + } + + private static _SELECTION_HIGHLIGHT_OVERVIEW = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + className: 'selectionHighlight', + overviewRuler: { + color: themeColorFromId(overviewRulerSelectionHighlightForeground), + darkColor: themeColorFromId(overviewRulerSelectionHighlightForeground), + position: OverviewRulerLane.Center + } + }); + + private static _SELECTION_HIGHLIGHT = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + className: 'selectionHighlight', + }); + + public dispose(): void { + this._setState(null); + super.dispose(); + } +} diff --git a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts index 7824a0df71e..6cd7cb571b2 100644 --- a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts @@ -5,10 +5,14 @@ 'use strict'; import * as assert from 'assert'; -import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; +import { withMockCodeEditor, MockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { Selection } from 'vs/editor/common/core/selection'; -import { InsertCursorAbove, InsertCursorBelow } from 'vs/editor/contrib/multicursor/common/multicursor'; -import { Handler } from 'vs/editor/common/editorCommon'; +import { Range } from 'vs/editor/common/core/range'; +import { InsertCursorAbove, InsertCursorBelow, MultiCursorSelectionController, SelectHighlightsAction, AddSelectionToNextFindMatchAction } from 'vs/editor/contrib/multicursor/common/multicursor'; +import { Handler, EndOfLineSequence } from 'vs/editor/common/editorCommon'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { TestFindController } from 'vs/editor/contrib/find/test/common/findController.test'; suite('Multicursor', () => { @@ -42,3 +46,425 @@ suite('Multicursor', () => { }); }); + +function fromRange(rng: Range): number[] { + return [rng.startLineNumber, rng.startColumn, rng.endLineNumber, rng.endColumn]; +} + +suite('Multicursor selection', () => { + let queryState: { [key: string]: any; } = {}; + let serviceCollection = new ServiceCollection(); + serviceCollection.set(IStorageService, { + get: (key: string) => queryState[key], + getBoolean: (key: string) => !!queryState[key], + store: (key: string, value: any) => { queryState[key] = value; } + }); + + test('issue #8817: Cursor position changes when you cancel multicursor', () => { + withMockCodeEditor([ + 'var x = (3 * 5)', + 'var y = (3 * 5)', + 'var z = (3 * 5)', + ], { serviceCollection: serviceCollection }, (editor, cursor) => { + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); + let selectHighlightsAction = new SelectHighlightsAction(); + + editor.setSelection(new Selection(2, 9, 2, 16)); + + selectHighlightsAction.run(null, editor); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [2, 9, 2, 16], + [1, 9, 1, 16], + [3, 9, 3, 16], + ]); + + editor.trigger('test', 'removeSecondaryCursors', null); + + assert.deepEqual(fromRange(editor.getSelection()), [2, 9, 2, 16]); + + multiCursorSelectController.dispose(); + findController.dispose(); + }); + }); + + test('issue #5400: "Select All Occurrences of Find Match" does not select all if find uses regex', () => { + withMockCodeEditor([ + 'something', + 'someething', + 'someeething', + 'nothing' + ], { serviceCollection: serviceCollection }, (editor, cursor) => { + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let selectHighlightsAction = new SelectHighlightsAction(); + + editor.setSelection(new Selection(1, 1, 1, 1)); + findController.getState().change({ searchString: 'some+thing', isRegex: true, isRevealed: true }, false); + + selectHighlightsAction.run(null, editor); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [1, 1, 1, 10], + [2, 1, 2, 11], + [3, 1, 3, 12], + ]); + + assert.equal(findController.getState().searchString, 'some+thing'); + + findController.dispose(); + }); + }); + + test('AddSelectionToNextFindMatchAction can work with multiline', () => { + withMockCodeEditor([ + '', + 'qwe', + 'rty', + '', + 'qwe', + '', + 'rty', + 'qwe', + 'rty' + ], { serviceCollection: serviceCollection }, (editor, cursor) => { + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); + let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); + + editor.setSelection(new Selection(2, 1, 3, 4)); + + addSelectionToNextFindMatch.run(null, editor); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [2, 1, 3, 4], + [8, 1, 9, 4] + ]); + + editor.trigger('test', 'removeSecondaryCursors', null); + + assert.deepEqual(fromRange(editor.getSelection()), [2, 1, 3, 4]); + + multiCursorSelectController.dispose(); + findController.dispose(); + }); + }); + + test('issue #6661: AddSelectionToNextFindMatchAction can work with touching ranges', () => { + withMockCodeEditor([ + 'abcabc', + 'abc', + 'abcabc', + ], { serviceCollection: serviceCollection }, (editor, cursor) => { + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); + let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); + + editor.setSelection(new Selection(1, 1, 1, 4)); + + addSelectionToNextFindMatch.run(null, editor); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [1, 1, 1, 4], + [1, 4, 1, 7] + ]); + + addSelectionToNextFindMatch.run(null, editor); + addSelectionToNextFindMatch.run(null, editor); + addSelectionToNextFindMatch.run(null, editor); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [1, 1, 1, 4], + [1, 4, 1, 7], + [2, 1, 2, 4], + [3, 1, 3, 4], + [3, 4, 3, 7] + ]); + + editor.trigger('test', Handler.Type, { text: 'z' }); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [1, 2, 1, 2], + [1, 3, 1, 3], + [2, 2, 2, 2], + [3, 2, 3, 2], + [3, 3, 3, 3] + ]); + assert.equal(editor.getValue(), [ + 'zz', + 'z', + 'zz', + ].join('\n')); + + multiCursorSelectController.dispose(); + findController.dispose(); + }); + }); + + test('issue #23541: Multiline Ctrl+D does not work in CRLF files', () => { + withMockCodeEditor([ + '', + 'qwe', + 'rty', + '', + 'qwe', + '', + 'rty', + 'qwe', + 'rty' + ], { serviceCollection: serviceCollection }, (editor, cursor) => { + + editor.getModel().setEOL(EndOfLineSequence.CRLF); + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); + let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); + + editor.setSelection(new Selection(2, 1, 3, 4)); + + addSelectionToNextFindMatch.run(null, editor); + assert.deepEqual(editor.getSelections().map(fromRange), [ + [2, 1, 3, 4], + [8, 1, 9, 4] + ]); + + editor.trigger('test', 'removeSecondaryCursors', null); + + assert.deepEqual(fromRange(editor.getSelection()), [2, 1, 3, 4]); + + multiCursorSelectController.dispose(); + findController.dispose(); + }); + }); + + function testAddSelectionToNextFindMatchAction(text: string[], callback: (editor: MockCodeEditor, action: AddSelectionToNextFindMatchAction, findController: TestFindController) => void): void { + withMockCodeEditor(text, { serviceCollection: serviceCollection }, (editor, cursor) => { + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); + + let action = new AddSelectionToNextFindMatchAction(); + + callback(editor, action, findController); + + multiCursorSelectController.dispose(); + findController.dispose(); + }); + } + + test('AddSelectionToNextFindMatchAction starting with single collapsed selection', () => { + const text = [ + 'abc pizza', + 'abc house', + 'abc bar' + ]; + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 2, 1, 2), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + }); + }); + + test('AddSelectionToNextFindMatchAction starting with two selections, one being collapsed 1)', () => { + const text = [ + 'abc pizza', + 'abc house', + 'abc bar' + ]; + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 1, 1, 4), + new Selection(2, 2, 2, 2), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + }); + }); + + test('AddSelectionToNextFindMatchAction starting with two selections, one being collapsed 2)', () => { + const text = [ + 'abc pizza', + 'abc house', + 'abc bar' + ]; + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 2, 1, 2), + new Selection(2, 1, 2, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + }); + }); + + test('AddSelectionToNextFindMatchAction starting with all collapsed selections', () => { + const text = [ + 'abc pizza', + 'abc house', + 'abc bar' + ]; + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 2, 1, 2), + new Selection(2, 2, 2, 2), + new Selection(3, 1, 3, 1), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + new Selection(3, 1, 3, 4), + ]); + }); + }); + + test('AddSelectionToNextFindMatchAction starting with all collapsed selections on different words', () => { + const text = [ + 'abc pizza', + 'abc house', + 'abc bar' + ]; + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 6, 1, 6), + new Selection(2, 6, 2, 6), + new Selection(3, 6, 3, 6), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 5, 1, 10), + new Selection(2, 5, 2, 10), + new Selection(3, 5, 3, 8), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 5, 1, 10), + new Selection(2, 5, 2, 10), + new Selection(3, 5, 3, 8), + ]); + }); + }); + + test('issue #20651: AddSelectionToNextFindMatchAction case insensitive', () => { + const text = [ + 'test', + 'testte', + 'Test', + 'testte', + 'test' + ]; + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 1, 1, 5), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(2, 1, 2, 5), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(2, 1, 2, 5), + new Selection(3, 1, 3, 5), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(2, 1, 2, 5), + new Selection(3, 1, 3, 5), + new Selection(4, 1, 4, 5), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(2, 1, 2, 5), + new Selection(3, 1, 3, 5), + new Selection(4, 1, 4, 5), + new Selection(5, 1, 5, 5), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(2, 1, 2, 5), + new Selection(3, 1, 3, 5), + new Selection(4, 1, 4, 5), + new Selection(5, 1, 5, 5), + ]); + }); + }); +}); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 44875020629..a20434dd807 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -49,7 +49,7 @@ import { getCodeEditor } from 'vs/editor/common/services/codeEditorService'; import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { FoldingController } from 'vs/editor/contrib/folding/browser/folding'; import { FindController } from 'vs/editor/contrib/find/browser/find'; -import { SelectionHighlighter } from 'vs/editor/contrib/find/common/findController'; +import { SelectionHighlighter } from 'vs/editor/contrib/multicursor/common/multicursor'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; From 0a7325ed39b4095743a0247e1ab4759c41313793 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sat, 21 Oct 2017 16:51:56 +0200 Subject: [PATCH 358/394] Move logic to MultiCursorSelectionController --- .../contrib/multicursor/common/multicursor.ts | 183 ++++++++++-------- .../test/common/multicursor.test.ts | 17 +- 2 files changed, 112 insertions(+), 88 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index ca4404ee09a..d14b51cde21 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -243,19 +243,9 @@ export class MultiCursorSelectionController extends Disposable implements IEdito currentMatch: currentMatch }; } -} -function multiCursorFind(editor: ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { - let controller = MultiCursorSelectionController.get(editor); - if (!controller) { - return null; - } - return controller.multiCursorFind(input); -} - -export abstract class SelectNextFindMatchAction extends EditorAction { - protected _getNextMatch(editor: ICommonCodeEditor): Selection { - let r = multiCursorFind(editor, { + private _getNextMatch(): Selection { + let r = this.multiCursorFind({ changeFindSearchString: true, allowMultiline: true, highlightFindOptions: true @@ -267,10 +257,10 @@ export abstract class SelectNextFindMatchAction extends EditorAction { return r.currentMatch; } - let allSelections = editor.getSelections(); + let allSelections = this._editor.getSelections(); let lastAddedSelection = allSelections[allSelections.length - 1]; - let nextMatch = editor.getModel().findNextMatch(r.searchText, lastAddedSelection.getEndPosition(), false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false); + let nextMatch = this._editor.getModel().findNextMatch(r.searchText, lastAddedSelection.getEndPosition(), false, r.matchCase, r.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); if (!nextMatch) { return null; @@ -278,11 +268,9 @@ export abstract class SelectNextFindMatchAction extends EditorAction { return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn); } -} -export abstract class SelectPreviousFindMatchAction extends EditorAction { - protected _getPreviousMatch(editor: ICommonCodeEditor): Selection { - let r = multiCursorFind(editor, { + private _getPreviousMatch(): Selection { + let r = this.multiCursorFind({ changeFindSearchString: true, allowMultiline: true, highlightFindOptions: true @@ -294,10 +282,10 @@ export abstract class SelectPreviousFindMatchAction extends EditorAction { return r.currentMatch; } - let allSelections = editor.getSelections(); + let allSelections = this._editor.getSelections(); let lastAddedSelection = allSelections[allSelections.length - 1]; - let previousMatch = editor.getModel().findPreviousMatch(r.searchText, lastAddedSelection.getStartPosition(), false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false); + let previousMatch = this._editor.getModel().findPreviousMatch(r.searchText, lastAddedSelection.getStartPosition(), false, r.matchCase, r.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); if (!previousMatch) { return null; @@ -305,31 +293,14 @@ export abstract class SelectPreviousFindMatchAction extends EditorAction { return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn); } -} -@editorAction -export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction { - - constructor() { - super({ - id: 'editor.action.addSelectionToNextFindMatch', - label: nls.localize('addSelectionToNextFindMatch', "Add Selection To Next Find Match"), - alias: 'Add Selection To Next Find Match', - precondition: null, - kbOpts: { - kbExpr: EditorContextKeys.focus, - primary: KeyMod.CtrlCmd | KeyCode.KEY_D - } - }); - } - - public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - const allSelections = editor.getSelections(); + public addSelectionToNextFindMatch(): void { + const allSelections = this._editor.getSelections(); // If there are mulitple cursors, handle the case where they do not all select the same text. if (allSelections.length > 1) { - const model = editor.getModel(); - const controller = CommonFindController.get(editor); + const model = this._editor.getModel(); + const controller = CommonFindController.get(this._editor); if (!controller) { return; } @@ -364,7 +335,7 @@ export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction for (let i = 0, len = allSelections.length; i < len; i++) { let selection = allSelections[i]; if (selection.isEmpty()) { - let word = editor.getModel().getWordAtPosition(selection.getStartPosition()); + let word = this._editor.getModel().getWordAtPosition(selection.getStartPosition()); if (word) { resultingSelections[i] = new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); continue; @@ -372,24 +343,102 @@ export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction } resultingSelections[i] = selection; } - editor.setSelections(resultingSelections); + this._editor.setSelections(resultingSelections); return; } } - let nextMatch = this._getNextMatch(editor); + let nextMatch = this._getNextMatch(); if (!nextMatch) { return; } - editor.setSelections(allSelections.concat(nextMatch)); - editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + this._editor.setSelections(allSelections.concat(nextMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + } + + public addSelectionToPreviousFindMatch(): void { + let previousMatch = this._getPreviousMatch(); + + if (!previousMatch) { + return; + } + + let allSelections = this._editor.getSelections(); + this._editor.setSelections(allSelections.concat(previousMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + } + + public moveSelectionToNextFindMatch(): void { + let nextMatch = this._getNextMatch(); + + if (!nextMatch) { + return; + } + + let allSelections = this._editor.getSelections(); + this._editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + } + + public moveSelectionToPreviousFindMatch(): void { + let previousMatch = this._getPreviousMatch(); + + if (!previousMatch) { + return; + } + + let allSelections = this._editor.getSelections(); + this._editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + } +} + +export abstract class MultiCursorSelectionControllerAction extends EditorAction { + + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + const controller = MultiCursorSelectionController.get(editor); + if (!controller) { + return; + } + this._run(controller); + } + + protected abstract _run(controller: MultiCursorSelectionController): void; +} + +function multiCursorFind(editor: ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { + let controller = MultiCursorSelectionController.get(editor); + if (!controller) { + return null; + } + return controller.multiCursorFind(input); +} + +@editorAction +export class AddSelectionToNextFindMatchAction extends MultiCursorSelectionControllerAction { + + constructor() { + super({ + id: 'editor.action.addSelectionToNextFindMatch', + label: nls.localize('addSelectionToNextFindMatch', "Add Selection To Next Find Match"), + alias: 'Add Selection To Next Find Match', + precondition: null, + kbOpts: { + kbExpr: EditorContextKeys.focus, + primary: KeyMod.CtrlCmd | KeyCode.KEY_D + } + }); + } + + protected _run(controller: MultiCursorSelectionController): void { + controller.addSelectionToNextFindMatch(); } } @editorAction -export class AddSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction { +export class AddSelectionToPreviousFindMatchAction extends MultiCursorSelectionControllerAction { constructor() { super({ @@ -400,21 +449,13 @@ export class AddSelectionToPreviousFindMatchAction extends SelectPreviousFindMat }); } - public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - let previousMatch = this._getPreviousMatch(editor); - - if (!previousMatch) { - return; - } - - let allSelections = editor.getSelections(); - editor.setSelections(allSelections.concat(previousMatch)); - editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + protected _run(controller: MultiCursorSelectionController): void { + controller.addSelectionToPreviousFindMatch(); } } @editorAction -export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchAction { +export class MoveSelectionToNextFindMatchAction extends MultiCursorSelectionControllerAction { constructor() { super({ @@ -429,21 +470,13 @@ export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchActio }); } - public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - let nextMatch = this._getNextMatch(editor); - - if (!nextMatch) { - return; - } - - let allSelections = editor.getSelections(); - editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); - editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + protected _run(controller: MultiCursorSelectionController): void { + controller.moveSelectionToNextFindMatch(); } } @editorAction -export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction { +export class MoveSelectionToPreviousFindMatchAction extends MultiCursorSelectionControllerAction { constructor() { super({ @@ -454,16 +487,8 @@ export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMa }); } - public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - let previousMatch = this._getPreviousMatch(editor); - - if (!previousMatch) { - return; - } - - let allSelections = editor.getSelections(); - editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); - editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + protected _run(controller: MultiCursorSelectionController): void { + controller.moveSelectionToPreviousFindMatch(); } } diff --git a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts index 6cd7cb571b2..986b96c2c1c 100644 --- a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts @@ -12,8 +12,7 @@ import { InsertCursorAbove, InsertCursorBelow, MultiCursorSelectionController, S import { Handler, EndOfLineSequence } from 'vs/editor/common/editorCommon'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { TestFindController } from 'vs/editor/contrib/find/test/common/findController.test'; - +import { CommonFindController } from 'vs/editor/contrib/find/common/findController'; suite('Multicursor', () => { @@ -67,7 +66,7 @@ suite('Multicursor selection', () => { 'var z = (3 * 5)', ], { serviceCollection: serviceCollection }, (editor, cursor) => { - let findController = editor.registerAndInstantiateContribution(TestFindController); + let findController = editor.registerAndInstantiateContribution(CommonFindController); let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let selectHighlightsAction = new SelectHighlightsAction(); @@ -97,7 +96,7 @@ suite('Multicursor selection', () => { 'nothing' ], { serviceCollection: serviceCollection }, (editor, cursor) => { - let findController = editor.registerAndInstantiateContribution(TestFindController); + let findController = editor.registerAndInstantiateContribution(CommonFindController); let selectHighlightsAction = new SelectHighlightsAction(); editor.setSelection(new Selection(1, 1, 1, 1)); @@ -129,7 +128,7 @@ suite('Multicursor selection', () => { 'rty' ], { serviceCollection: serviceCollection }, (editor, cursor) => { - let findController = editor.registerAndInstantiateContribution(TestFindController); + let findController = editor.registerAndInstantiateContribution(CommonFindController); let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); @@ -157,7 +156,7 @@ suite('Multicursor selection', () => { 'abcabc', ], { serviceCollection: serviceCollection }, (editor, cursor) => { - let findController = editor.registerAndInstantiateContribution(TestFindController); + let findController = editor.registerAndInstantiateContribution(CommonFindController); let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); @@ -214,7 +213,7 @@ suite('Multicursor selection', () => { editor.getModel().setEOL(EndOfLineSequence.CRLF); - let findController = editor.registerAndInstantiateContribution(TestFindController); + let findController = editor.registerAndInstantiateContribution(CommonFindController); let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let addSelectionToNextFindMatch = new AddSelectionToNextFindMatchAction(); @@ -235,10 +234,10 @@ suite('Multicursor selection', () => { }); }); - function testAddSelectionToNextFindMatchAction(text: string[], callback: (editor: MockCodeEditor, action: AddSelectionToNextFindMatchAction, findController: TestFindController) => void): void { + function testAddSelectionToNextFindMatchAction(text: string[], callback: (editor: MockCodeEditor, action: AddSelectionToNextFindMatchAction, findController: CommonFindController) => void): void { withMockCodeEditor(text, { serviceCollection: serviceCollection }, (editor, cursor) => { - let findController = editor.registerAndInstantiateContribution(TestFindController); + let findController = editor.registerAndInstantiateContribution(CommonFindController); let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let action = new AddSelectionToNextFindMatchAction(); From 5e28a89038ac695685a9d1fc65526ad5487d4e14 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 21 Oct 2017 09:27:40 -0700 Subject: [PATCH 359/394] Have terminal listen to fine grained events Fixes #36502 --- src/vs/workbench/parts/terminal/common/terminalService.ts | 6 +++++- .../parts/terminal/electron-browser/terminalPanel.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/terminal/common/terminalService.ts b/src/vs/workbench/parts/terminal/common/terminalService.ts index 44815065a04..6ca13f5b6fd 100644 --- a/src/vs/workbench/parts/terminal/common/terminalService.ts +++ b/src/vs/workbench/parts/terminal/common/terminalService.ts @@ -59,7 +59,11 @@ export abstract class TerminalService implements ITerminalService { this._onInstanceTitleChanged = new Emitter(); this._onInstancesChanged = new Emitter(); - this._configurationService.onDidChangeConfiguration(() => this.updateConfig()); + this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('terminal.integrated')) { + this.updateConfig(); + } + }); lifecycleService.onWillShutdown(event => event.veto(this._onWillShutdown())); this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService); this._findWidgetVisible = KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE.bindTo(this._contextKeyService); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index e862598502b..a67a1bceefb 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -74,7 +74,11 @@ export class TerminalPanel extends Panel { this._terminalService.setContainers(this.getContainer().getHTMLElement(), this._terminalContainer); this._register(this.themeService.onThemeChange(theme => this._updateTheme(theme))); - this._register(this._configurationService.onDidChangeConfiguration(() => this._updateFont())); + this._register(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('terminal.integrated') || e.affectsConfiguration('editor.fontFamily')) { + this._updateFont(); + } + })); this._updateFont(); this._updateTheme(); From a1b79983acafaf431a9545bdf88544eaf846740f Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 21 Oct 2017 23:32:43 -0700 Subject: [PATCH 360/394] Fix #36115 - add #region folding for PHP --- extensions/php/language-configuration.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index 0b35ccae67d..8172fcd09e5 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -26,5 +26,11 @@ "indentationRules": { "increaseIndentPattern": "({(?!.+}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch).*:)\\s*(/[/*].*)?$", "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" + }, + "folding": { + "markers": { + "start": "^\\s*(#|\/\/)region\\b", + "end": "^\\s*(#|\/\/)endregion\\b" + } } } \ No newline at end of file From a0aa7c6ed5e284458ba033329ea3c9e8ca306e00 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sun, 22 Oct 2017 09:45:18 +0200 Subject: [PATCH 361/394] Have Ctrl+D be disconnected from the find state when starting with a collapsed selection --- .../contrib/multicursor/common/multicursor.ts | 240 +++++++++++------- .../test/common/multicursor.test.ts | 69 +++++ 2 files changed, 217 insertions(+), 92 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index d14b51cde21..d07d282decf 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -5,10 +5,10 @@ 'use strict'; import * as nls from 'vs/nls'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { ICommonCodeEditor, ScrollType, IEditorContribution, FindMatch, TrackedRangeStickiness, OverviewRulerLane } from 'vs/editor/common/editorCommon'; +import { ICommonCodeEditor, ScrollType, IEditorContribution, FindMatch, TrackedRangeStickiness, OverviewRulerLane, IModel } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { editorAction, commonEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions'; import { Range } from 'vs/editor/common/core/range'; @@ -163,12 +163,22 @@ export interface IMultiCursorFindResult { currentMatch: Selection; } +class SearchSettings { + constructor( + public readonly wholeWord: boolean, + public readonly matchCase: boolean, + ) { } +} + @commonEditorContribution export class MultiCursorSelectionController extends Disposable implements IEditorContribution { private static ID = 'editor.contrib.multiCursorController'; private readonly _editor: ICommonCodeEditor; + private _isDisconnectedFromFindController: boolean; + private _ignoreSelectionChange: boolean; + private _disconnectDispose: IDisposable[]; public static get(editor: ICommonCodeEditor): MultiCursorSelectionController { return editor.getContribution(MultiCursorSelectionController.ID); @@ -177,6 +187,9 @@ export class MultiCursorSelectionController extends Disposable implements IEdito constructor(editor: ICommonCodeEditor) { super(); this._editor = editor; + this._isDisconnectedFromFindController = false; + this._ignoreSelectionChange = false; + this._disconnectDispose = []; } public dispose(): void { @@ -187,29 +200,67 @@ export class MultiCursorSelectionController extends Disposable implements IEdito return MultiCursorSelectionController.ID; } - public multiCursorFind(input: IMultiCursorFindInput): IMultiCursorFindResult { - let controller = CommonFindController.get(this._editor); - if (!controller) { - return null; + private _beginFindControllerDisconnect(): void { + if (this._isDisconnectedFromFindController) { + return; } - let state = controller.getState(); + this._isDisconnectedFromFindController = true; + this._disconnectDispose = [ + this._editor.onDidChangeCursorSelection((e) => { + if (this._ignoreSelectionChange) { + return; + } + this._endFindControllerDisconnect(); + }) + ]; + } + + private _endFindControllerDisconnect(): void { + if (!this._isDisconnectedFromFindController) { + return; + } + this._isDisconnectedFromFindController = false; + this._disconnectDispose = dispose(this._disconnectDispose); + } + + private _setSelections(selections: Selection[], revealRange: Range, scrollType: ScrollType): void { + this._ignoreSelectionChange = true; + this._editor.setSelections(selections); + this._ignoreSelectionChange = false; + this._editor.revealRangeInCenterIfOutsideViewport(revealRange, scrollType); + } + + private _getSearchSettings(findController: CommonFindController): SearchSettings { + if (this._isDisconnectedFromFindController) { + // find state disassociation + return new SearchSettings(true, true); + } + const selections = this._editor.getSelections(); + if (selections.length === 1 && selections[0].isEmpty()) { + // find state disassociation + return new SearchSettings(true, true); + } + const findState = findController.getState(); + return new SearchSettings(findState.wholeWord, findState.matchCase); + } + + public multiCursorFind(findController: CommonFindController, input: IMultiCursorFindInput): IMultiCursorFindResult { + const findState = findController.getState(); let searchText: string; let currentMatch: Selection; - // In any case, if the find widget was ever opened, the options are taken from it - let wholeWord = state.wholeWord; - let matchCase = state.matchCase; + const { wholeWord, matchCase } = this._getSearchSettings(findController); // Find widget owns what we search for if: // - focus is not in the editor (i.e. it is in the find widget) // - and the search widget is visible // - and the search string is non-empty - if (!this._editor.isFocused() && state.isRevealed && state.searchString.length > 0) { + if (!this._editor.isFocused() && findState.isRevealed && findState.searchString.length > 0) { // Find widget owns what is searched for - searchText = state.searchString; + searchText = findState.searchString; } else { // Selection owns what is searched for - let s = this._editor.getSelection(); + const s = this._editor.getSelection(); if (s.startLineNumber !== s.endLineNumber && !input.allowMultiline) { // multiline forbidden @@ -218,7 +269,7 @@ export class MultiCursorSelectionController extends Disposable implements IEdito if (s.isEmpty()) { // selection is empty => expand to current word - let word = this._editor.getModel().getWordAtPosition(s.getStartPosition()); + const word = this._editor.getModel().getWordAtPosition(s.getStartPosition()); if (!word) { return null; } @@ -228,12 +279,12 @@ export class MultiCursorSelectionController extends Disposable implements IEdito searchText = this._editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); } if (input.changeFindSearchString) { - controller.setSearchString(searchText); + findController.setSearchString(searchText); } } if (input.highlightFindOptions) { - controller.highlightFindOptions(); + findController.highlightFindOptions(); } return { @@ -244,8 +295,8 @@ export class MultiCursorSelectionController extends Disposable implements IEdito }; } - private _getNextMatch(): Selection { - let r = this.multiCursorFind({ + private _getNextMatch(findController: CommonFindController): Selection { + let r = this.multiCursorFind(findController, { changeFindSearchString: true, allowMultiline: true, highlightFindOptions: true @@ -269,8 +320,8 @@ export class MultiCursorSelectionController extends Disposable implements IEdito return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn); } - private _getPreviousMatch(): Selection { - let r = this.multiCursorFind({ + private _getPreviousMatch(findController: CommonFindController): Selection { + let r = this.multiCursorFind(findController, { changeFindSearchString: true, allowMultiline: true, highlightFindOptions: true @@ -294,126 +345,131 @@ export class MultiCursorSelectionController extends Disposable implements IEdito return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn); } - public addSelectionToNextFindMatch(): void { + private _getValueInRange(model: IModel, range: Range, toLowerCase: boolean): string { + const text = model.getValueInRange(range); + return (toLowerCase ? text.toLowerCase() : text); + } + + private _rangesContainSameText(ranges: Range[], matchCase: boolean): boolean { + const model = this._editor.getModel(); + const selectedText = this._getValueInRange(model, ranges[0], !matchCase); + for (let i = 1, len = ranges.length; i < len; i++) { + const range = ranges[i]; + if (range.isEmpty()) { + return false; + } + const thisSelectedText = this._getValueInRange(model, range, !matchCase); + if (selectedText !== thisSelectedText) { + return false; + } + } + return true; + } + + private _expandEmptyToWord(model: IModel, selection: Selection): Selection { + if (!selection.isEmpty()) { + return selection; + } + const word = model.getWordAtPosition(selection.getStartPosition()); + if (!word) { + return selection; + } + return new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); + } + + public addSelectionToNextFindMatch(findController: CommonFindController): void { const allSelections = this._editor.getSelections(); - // If there are mulitple cursors, handle the case where they do not all select the same text. + // If there are multiple cursors, handle the case where they do not all select the same text. if (allSelections.length > 1) { - const model = this._editor.getModel(); - const controller = CommonFindController.get(this._editor); - if (!controller) { - return; - } - const findState = controller.getState(); - const caseSensitive = findState.matchCase; - - let selectionsContainSameText = true; - - let selectedText = model.getValueInRange(allSelections[0]); - if (!caseSensitive) { - selectedText = selectedText.toLowerCase(); - } - for (let i = 1, len = allSelections.length; i < len; i++) { - let selection = allSelections[i]; - if (selection.isEmpty()) { - selectionsContainSameText = false; - break; - } - - let thisSelectedText = model.getValueInRange(selection); - if (!caseSensitive) { - thisSelectedText = thisSelectedText.toLowerCase(); - } - if (selectedText !== thisSelectedText) { - selectionsContainSameText = false; - break; - } - } - + const matchCase = this._getSearchSettings(findController).matchCase; + const selectionsContainSameText = this._rangesContainSameText(allSelections, matchCase); if (!selectionsContainSameText) { + const model = this._editor.getModel(); let resultingSelections: Selection[] = []; for (let i = 0, len = allSelections.length; i < len; i++) { - let selection = allSelections[i]; - if (selection.isEmpty()) { - let word = this._editor.getModel().getWordAtPosition(selection.getStartPosition()); - if (word) { - resultingSelections[i] = new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); - continue; - } - } - resultingSelections[i] = selection; + resultingSelections[i] = this._expandEmptyToWord(model, allSelections[i]); } this._editor.setSelections(resultingSelections); return; } } - let nextMatch = this._getNextMatch(); + let nextMatch = this._getNextMatch(findController); if (!nextMatch) { return; } - this._editor.setSelections(allSelections.concat(nextMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + if (allSelections.length === 1 && allSelections[0].isEmpty()) { + // Enter find state disassociation + this._beginFindControllerDisconnect(); + } + + this._setSelections(allSelections.concat(nextMatch), nextMatch, ScrollType.Smooth); } - public addSelectionToPreviousFindMatch(): void { - let previousMatch = this._getPreviousMatch(); + public addSelectionToPreviousFindMatch(findController: CommonFindController): void { + let previousMatch = this._getPreviousMatch(findController); if (!previousMatch) { return; } let allSelections = this._editor.getSelections(); - this._editor.setSelections(allSelections.concat(previousMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + this._setSelections(allSelections.concat(previousMatch), previousMatch, ScrollType.Smooth); } - public moveSelectionToNextFindMatch(): void { - let nextMatch = this._getNextMatch(); + public moveSelectionToNextFindMatch(findController: CommonFindController): void { + let nextMatch = this._getNextMatch(findController); if (!nextMatch) { return; } let allSelections = this._editor.getSelections(); - this._editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch), nextMatch, ScrollType.Smooth); } - public moveSelectionToPreviousFindMatch(): void { - let previousMatch = this._getPreviousMatch(); + public moveSelectionToPreviousFindMatch(findController: CommonFindController): void { + let previousMatch = this._getPreviousMatch(findController); if (!previousMatch) { return; } let allSelections = this._editor.getSelections(); - this._editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch), previousMatch, ScrollType.Smooth); } } export abstract class MultiCursorSelectionControllerAction extends EditorAction { public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - const controller = MultiCursorSelectionController.get(editor); - if (!controller) { + const multiCursorController = MultiCursorSelectionController.get(editor); + if (!multiCursorController) { return; } - this._run(controller); + const findController = CommonFindController.get(editor); + if (!findController) { + return null; + } + this._run(multiCursorController, findController); } - protected abstract _run(controller: MultiCursorSelectionController): void; + protected abstract _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void; } function multiCursorFind(editor: ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { - let controller = MultiCursorSelectionController.get(editor); - if (!controller) { + const multiCursorController = MultiCursorSelectionController.get(editor); + if (!multiCursorController) { return null; } - return controller.multiCursorFind(input); + const findController = CommonFindController.get(editor); + if (!findController) { + return null; + } + return multiCursorController.multiCursorFind(findController, input); } @editorAction @@ -432,8 +488,8 @@ export class AddSelectionToNextFindMatchAction extends MultiCursorSelectionContr }); } - protected _run(controller: MultiCursorSelectionController): void { - controller.addSelectionToNextFindMatch(); + protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { + multiCursorController.addSelectionToNextFindMatch(findController); } } @@ -449,8 +505,8 @@ export class AddSelectionToPreviousFindMatchAction extends MultiCursorSelectionC }); } - protected _run(controller: MultiCursorSelectionController): void { - controller.addSelectionToPreviousFindMatch(); + protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { + multiCursorController.addSelectionToPreviousFindMatch(findController); } } @@ -470,8 +526,8 @@ export class MoveSelectionToNextFindMatchAction extends MultiCursorSelectionCont }); } - protected _run(controller: MultiCursorSelectionController): void { - controller.moveSelectionToNextFindMatch(); + protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { + multiCursorController.moveSelectionToNextFindMatch(findController); } } @@ -487,8 +543,8 @@ export class MoveSelectionToPreviousFindMatchAction extends MultiCursorSelection }); } - protected _run(controller: MultiCursorSelectionController): void { - controller.moveSelectionToPreviousFindMatch(); + protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { + multiCursorController.moveSelectionToPreviousFindMatch(findController); } } diff --git a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts index 986b96c2c1c..15e2b99e867 100644 --- a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts @@ -466,4 +466,73 @@ suite('Multicursor selection', () => { ]); }); }); + + suite('Find state disassociation', () => { + + const text = [ + 'app', + 'apples', + 'whatsapp', + 'app', + 'App', + ' app' + ]; + + test('enters mode', () => { + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 2, 1, 2), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(4, 1, 4, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(4, 1, 4, 4), + new Selection(6, 2, 6, 5), + ]); + }); + }); + + test('leaves mode when selection changes', () => { + testAddSelectionToNextFindMatchAction(text, (editor, action, findController) => { + editor.setSelections([ + new Selection(1, 2, 1, 2), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(4, 1, 4, 4), + ]); + + // change selection + editor.setSelections([ + new Selection(1, 1, 1, 4), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(2, 1, 2, 4), + ]); + }); + }); + + }); }); From 089f675513b770cd5e83a5511b24579909eff537 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sun, 22 Oct 2017 10:42:09 +0200 Subject: [PATCH 362/394] SelectHighlightsAction also enters find widget state disconnection mode --- .../contrib/multicursor/common/multicursor.ts | 124 +++++++++--------- .../test/common/multicursor.test.ts | 39 +++++- 2 files changed, 97 insertions(+), 66 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index d07d282decf..fb328f3a082 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -223,11 +223,10 @@ export class MultiCursorSelectionController extends Disposable implements IEdito this._disconnectDispose = dispose(this._disconnectDispose); } - private _setSelections(selections: Selection[], revealRange: Range, scrollType: ScrollType): void { + private _setSelections(selections: Selection[]): void { this._ignoreSelectionChange = true; this._editor.setSelections(selections); this._ignoreSelectionChange = false; - this._editor.revealRangeInCenterIfOutsideViewport(revealRange, scrollType); } private _getSearchSettings(findController: CommonFindController): SearchSettings { @@ -406,7 +405,8 @@ export class MultiCursorSelectionController extends Disposable implements IEdito this._beginFindControllerDisconnect(); } - this._setSelections(allSelections.concat(nextMatch), nextMatch, ScrollType.Smooth); + this._setSelections(allSelections.concat(nextMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); } public addSelectionToPreviousFindMatch(findController: CommonFindController): void { @@ -417,7 +417,8 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } let allSelections = this._editor.getSelections(); - this._setSelections(allSelections.concat(previousMatch), previousMatch, ScrollType.Smooth); + this._setSelections(allSelections.concat(previousMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); } public moveSelectionToNextFindMatch(findController: CommonFindController): void { @@ -428,7 +429,8 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } let allSelections = this._editor.getSelections(); - this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch), nextMatch, ScrollType.Smooth); + this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); } public moveSelectionToPreviousFindMatch(findController: CommonFindController): void { @@ -439,7 +441,54 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } let allSelections = this._editor.getSelections(); - this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch), previousMatch, ScrollType.Smooth); + this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); + this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); + } + + public selectAll(findController: CommonFindController): void { + let matches: FindMatch[] = null; + + const findState = findController.getState(); + if (findState.isRevealed && findState.searchString.length > 0 && findState.isRegex) { + + matches = this._editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); + + } else { + + const r = this.multiCursorFind(findController, { + changeFindSearchString: true, + allowMultiline: true, + highlightFindOptions: true + }); + if (!r) { + return; + } + + matches = this._editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); + } + + if (matches.length > 0) { + const editorSelection = this._editor.getSelection(); + // Have the primary cursor remain the one where the action was invoked + for (let i = 0, len = matches.length; i < len; i++) { + const match = matches[i]; + const intersection = match.range.intersectRanges(editorSelection); + if (intersection) { + // bingo! + matches[i] = matches[0]; + matches[0] = match; + break; + } + } + + const allSelections = this._editor.getSelections(); + if (allSelections.length === 1 && allSelections[0].isEmpty()) { + // Enter find state disassociation + this._beginFindControllerDisconnect(); + } + + this._setSelections(matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn))); + } } } @@ -474,7 +523,6 @@ function multiCursorFind(editor: ICommonCodeEditor, input: IMultiCursorFindInput @editorAction export class AddSelectionToNextFindMatchAction extends MultiCursorSelectionControllerAction { - constructor() { super({ id: 'editor.action.addSelectionToNextFindMatch', @@ -487,7 +535,6 @@ export class AddSelectionToNextFindMatchAction extends MultiCursorSelectionContr } }); } - protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { multiCursorController.addSelectionToNextFindMatch(findController); } @@ -495,7 +542,6 @@ export class AddSelectionToNextFindMatchAction extends MultiCursorSelectionContr @editorAction export class AddSelectionToPreviousFindMatchAction extends MultiCursorSelectionControllerAction { - constructor() { super({ id: 'editor.action.addSelectionToPreviousFindMatch', @@ -504,7 +550,6 @@ export class AddSelectionToPreviousFindMatchAction extends MultiCursorSelectionC precondition: null }); } - protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { multiCursorController.addSelectionToPreviousFindMatch(findController); } @@ -512,7 +557,6 @@ export class AddSelectionToPreviousFindMatchAction extends MultiCursorSelectionC @editorAction export class MoveSelectionToNextFindMatchAction extends MultiCursorSelectionControllerAction { - constructor() { super({ id: 'editor.action.moveSelectionToNextFindMatch', @@ -525,7 +569,6 @@ export class MoveSelectionToNextFindMatchAction extends MultiCursorSelectionCont } }); } - protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { multiCursorController.moveSelectionToNextFindMatch(findController); } @@ -533,7 +576,6 @@ export class MoveSelectionToNextFindMatchAction extends MultiCursorSelectionCont @editorAction export class MoveSelectionToPreviousFindMatchAction extends MultiCursorSelectionControllerAction { - constructor() { super({ id: 'editor.action.moveSelectionToPreviousFindMatch', @@ -542,59 +584,13 @@ export class MoveSelectionToPreviousFindMatchAction extends MultiCursorSelection precondition: null }); } - protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { multiCursorController.moveSelectionToPreviousFindMatch(findController); } } -export abstract class AbstractSelectHighlightsAction extends EditorAction { - public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { - const controller = CommonFindController.get(editor); - if (!controller) { - return null; - } - - let matches: FindMatch[] = null; - - const findState = controller.getState(); - if (findState.isRevealed && findState.isRegex && findState.searchString.length > 0) { - - matches = editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); - - } else { - - const r = multiCursorFind(editor, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { - return; - } - - matches = editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); - } - - if (matches.length > 0) { - const editorSelection = editor.getSelection(); - for (let i = 0, len = matches.length; i < len; i++) { - const match = matches[i]; - let intersection = match.range.intersectRanges(editorSelection); - if (intersection) { - // bingo! - matches.splice(i, 1); - matches.unshift(match); - break; - } - } - editor.setSelections(matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn))); - } - } -} - @editorAction -export class SelectHighlightsAction extends AbstractSelectHighlightsAction { +export class SelectHighlightsAction extends MultiCursorSelectionControllerAction { constructor() { super({ id: 'editor.action.selectHighlights', @@ -607,10 +603,13 @@ export class SelectHighlightsAction extends AbstractSelectHighlightsAction { } }); } + protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { + multiCursorController.selectAll(findController); + } } @editorAction -export class CompatChangeAll extends AbstractSelectHighlightsAction { +export class CompatChangeAll extends MultiCursorSelectionControllerAction { constructor() { super({ id: 'editor.action.changeAll', @@ -627,6 +626,9 @@ export class CompatChangeAll extends AbstractSelectHighlightsAction { } }); } + protected _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void { + multiCursorController.selectAll(findController); + } } class SelectionHighlighterState { diff --git a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts index 15e2b99e867..1a7c90d18e9 100644 --- a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts @@ -97,6 +97,7 @@ suite('Multicursor selection', () => { ], { serviceCollection: serviceCollection }, (editor, cursor) => { let findController = editor.registerAndInstantiateContribution(CommonFindController); + let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let selectHighlightsAction = new SelectHighlightsAction(); editor.setSelection(new Selection(1, 1, 1, 1)); @@ -111,6 +112,7 @@ suite('Multicursor selection', () => { assert.equal(findController.getState().searchString, 'some+thing'); + multiCursorSelectController.dispose(); findController.dispose(); }); }); @@ -234,21 +236,25 @@ suite('Multicursor selection', () => { }); }); - function testAddSelectionToNextFindMatchAction(text: string[], callback: (editor: MockCodeEditor, action: AddSelectionToNextFindMatchAction, findController: CommonFindController) => void): void { + function testMulticursor(text: string[], callback: (editor: MockCodeEditor, findController: CommonFindController) => void): void { withMockCodeEditor(text, { serviceCollection: serviceCollection }, (editor, cursor) => { - let findController = editor.registerAndInstantiateContribution(CommonFindController); let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); - let action = new AddSelectionToNextFindMatchAction(); - - callback(editor, action, findController); + callback(editor, findController); multiCursorSelectController.dispose(); findController.dispose(); }); } + function testAddSelectionToNextFindMatchAction(text: string[], callback: (editor: MockCodeEditor, action: AddSelectionToNextFindMatchAction, findController: CommonFindController) => void): void { + testMulticursor(text, (editor, findController) => { + let action = new AddSelectionToNextFindMatchAction(); + callback(editor, action, findController); + }); + } + test('AddSelectionToNextFindMatchAction starting with single collapsed selection', () => { const text = [ 'abc pizza', @@ -534,5 +540,28 @@ suite('Multicursor selection', () => { }); }); + test('Select Highlights respects mode ', () => { + testMulticursor(text, (editor, findController) => { + let action = new SelectHighlightsAction(); + editor.setSelections([ + new Selection(1, 2, 1, 2), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(4, 1, 4, 4), + new Selection(6, 2, 6, 5), + ]); + + action.run(null, editor); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 4), + new Selection(4, 1, 4, 4), + new Selection(6, 2, 6, 5), + ]); + }); + }); + }); }); From e351726281bbd0b16e8331c40a4bf21937c7f5d7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sun, 22 Oct 2017 19:00:34 +0200 Subject: [PATCH 363/394] Pass filter flags correctly --- src/vs/editor/common/viewModel/splitLinesCollection.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index f57572f1e38..506fba70f96 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -720,14 +720,14 @@ export class SplitLinesCollection implements IViewModelLinesCollection { } else { // hit invisible line => flush request if (reqStart !== null) { - result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelLineIndex + 1, 1))); + result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelLineIndex + 1, 1), ownerId, filterOutValidation)); reqStart = null; } } } if (reqStart !== null) { - result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelEnd.lineNumber, modelEnd.column))); + result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelEnd.lineNumber, modelEnd.column), ownerId, filterOutValidation)); reqStart = null; } From c1be82537d9fda852a258851f48ea78b7fc8a7a3 Mon Sep 17 00:00:00 2001 From: 284km Date: Mon, 23 Oct 2017 09:11:38 +0900 Subject: [PATCH 364/394] Fix a typo (#36702) --- src/vs/editor/contrib/find/browser/findWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index 7cb6a00b5f0..77c25acb251 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -921,7 +921,7 @@ class SimpleCheckbox extends Widget { this._label = document.createElement('label'); this._label.className = 'label'; - // Connect the label and the checkbox. Checkbox will get checked when the label recieves a click. + // Connect the label and the checkbox. Checkbox will get checked when the label receives a click. this._label.htmlFor = this._checkbox.id; this._label.tabIndex = -1; From 10dae790e166a2b1b1fe11c8eae3c0e5dcad9a0a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 07:55:29 +0200 Subject: [PATCH 365/394] fix too permissive search.exclude --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 363bb9bcd4e..341a454f1ab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,7 +14,7 @@ "**/node_modules": true, "**/bower_components": true, ".build/**": true, - "out*/**": true, + "out/**": true, "i18n/**": true, "extensions/**/out/**": true, "test/smoke/out/**": true From 6ae0eb815ff272072493e602b4828a01dceebd79 Mon Sep 17 00:00:00 2001 From: Vinaya Date: Mon, 23 Oct 2017 09:16:56 +0300 Subject: [PATCH 366/394] Fix grammar: Current => Currently (#36694) Change in workbench.editor.openPositioning setting --- src/vs/workbench/electron-browser/main.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts index f56ae229cbe..26d262395d8 100644 --- a/src/vs/workbench/electron-browser/main.contribution.ts +++ b/src/vs/workbench/electron-browser/main.contribution.ts @@ -170,7 +170,7 @@ let workbenchProperties: { [path: string]: IJSONSchema; } = { 'type': 'string', 'enum': ['left', 'right', 'first', 'last'], 'default': 'right', - 'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorOpenPositioning' }, "Controls where editors open. Select 'left' or 'right' to open editors to the left or right of the current active one. Select 'first' or 'last' to open editors independently from the currently active one.") + 'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorOpenPositioning' }, "Controls where editors open. Select 'left' or 'right' to open editors to the left or right of the currently active one. Select 'first' or 'last' to open editors independently from the currently active one.") }, 'workbench.editor.revealIfOpen': { 'type': 'boolean', From 4b782829aa40a7822d66d9cbd5b3b2ab7c3ff381 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 08:15:59 +0200 Subject: [PATCH 367/394] more tests --- .../test/common/quickOpenScorer.test.ts | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts index b8b1fc11ca9..bcb22b89aa2 100644 --- a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts +++ b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts @@ -663,6 +663,58 @@ suite('Quick Open Scorer', () => { assert.equal(res[2], resourceB); }); + test('compareFilesByScore - avoid match scattering (bug #14879)', function () { + const resourceA = URI.file('pkg/search/gradient/testdata/constraint_attrMatchString.yml'); + const resourceB = URI.file('cmd/gradient/main.go'); + + let query = 'gradientmain'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + + test('compareFilesByScore - avoid match scattering (bug #14727 1)', function () { + const resourceA = URI.file('alpha-beta-cappa.txt'); + const resourceB = URI.file('abc.txt'); + + let query = 'abc'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + + test('compareFilesByScore - avoid match scattering (bug #14727 2)', function () { + const resourceA = URI.file('xerxes-yak-zubba/index.js'); + const resourceB = URI.file('xyz/index.js'); + + let query = 'xyz'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + + test('compareFilesByScore - avoid match scattering (bug #18381)', function () { + const resourceA = URI.file('AssymblyInfo.cs'); + const resourceB = URI.file('IAsynchronousTask.java'); + + let query = 'async'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + test('compareFilesByScore - prefer shorter hit (bug #20546)', function () { const resourceA = URI.file('editor/core/components/tests/list-view-spec.js'); const resourceB = URI.file('editor/core/components/list-view.js'); From 2ca58657e947d7f8c6ca826b3758b2069d7aa410 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 23 Oct 2017 09:38:58 +0200 Subject: [PATCH 368/394] Reduce SelectionHighlighter flashing when moving within the same word --- src/vs/editor/contrib/multicursor/common/multicursor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index fb328f3a082..e0b8c4fe317 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -638,6 +638,7 @@ class SelectionHighlighterState { public readonly wordSeparators: string; constructor(lastWordUnderCursor: Selection, searchText: string, matchCase: boolean, wordSeparators: string) { + this.lastWordUnderCursor = lastWordUnderCursor; this.searchText = searchText; this.matchCase = matchCase; this.wordSeparators = wordSeparators; From 9ee20ac2d8090bf729efc8a9e3f7bb2a3f85bb82 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 23 Oct 2017 10:30:14 +0200 Subject: [PATCH 369/394] add test ensuring getWorkspaceFolder doesn't fail on drive letter casing, #36221 --- .../electron-browser/api/extHostWorkspace.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts index ee457705998..73399a9bd37 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts @@ -212,6 +212,17 @@ suite('ExtHostWorkspace', function () { sub.dispose(); }); + test('`vscode.workspace.getWorkspaceFolder(file)` don\'t return workspace folder when file open from command line. #36221', function () { + let ws = new ExtHostWorkspace(new TestThreadService(), { + id: 'foo', name: 'Test', folders: [ + aWorkspaceFolderData(URI.file('c:/Users/marek/Desktop/vsc_test/'), 0) + ] + }); + + assert.ok(ws.getWorkspaceFolder(URI.file('c:/Users/marek/Desktop/vsc_test/a.txt'))); + assert.ok(ws.getWorkspaceFolder(URI.file('C:/Users/marek/Desktop/vsc_test/b.txt'))); + }); + function aWorkspaceFolderData(uri: URI, index: number, name: string = ''): IWorkspaceFolderData { return { uri, From 2e966de20493e5d0733345cfa3b06262d1a51602 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 11:05:22 +0200 Subject: [PATCH 370/394] easy on the error message (for #36703) --- src/vs/workbench/parts/files/browser/fileActions.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index c56c5a48fa7..5bfcb8ac062 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -1982,20 +1982,28 @@ export function validateFileName(parent: IFileStat, name: string, allowOverwriti // Invalid File name if (!paths.isValidBasename(name)) { - return nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", name); + return nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", trimLongName(name)); } // Max length restriction (on Windows) if (isWindows) { const fullPathLength = name.length + parent.resource.fsPath.length + 1 /* path segment */; if (fullPathLength > 255) { - return nls.localize('filePathTooLongError', "The name **{0}** results in a path that is too long. Please choose a shorter name.", name); + return nls.localize('filePathTooLongError', "The name **{0}** results in a path that is too long. Please choose a shorter name.", trimLongName(name)); } } return null; } +function trimLongName(name: string): string { + if (name && name.length > 255) { + return `${name.substr(0, 255)}...`; + } + + return name; +} + export function getWellFormedFileName(filename: string): string { if (!filename) { return filename; From 5aa422f20f6fa033b918bcb6f3e537ddca458ed5 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Mon, 23 Oct 2017 11:30:08 +0200 Subject: [PATCH 371/394] Fixes #36735: Cannot read property 'byIdentifier' of undefined --- .../parts/tasks/electron-browser/task.contribution.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 14c8cddf519..a476289267a 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -1411,7 +1411,9 @@ class TaskService extends EventEmitter implements ITaskService { let customTasksToDelete: Task[] = []; if (configurations || legacyTaskConfigurations) { let unUsedConfigurations: Set = new Set(); - Object.keys(configurations.byIdentifier).forEach(key => unUsedConfigurations.add(key)); + if (configurations) { + Object.keys(configurations.byIdentifier).forEach(key => unUsedConfigurations.add(key)); + } for (let task of contributed) { if (!ContributedTask.is(task)) { continue; From abbcf178753c2866a5755341172bef06baddccf4 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 23 Oct 2017 11:35:38 +0200 Subject: [PATCH 372/394] fixes #36725 --- .../workbench/parts/files/browser/views/explorerView.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 2c2d45cb9c6..06586cd00c2 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -144,6 +144,14 @@ export class ExplorerView extends ViewsViewletPanel { return this.contextService.getWorkspace().name; } + public get title(): string { + return this.name; + } + + public set title(value: string) { + // noop + } + public set name(value) { // noop } From d02a9cd78391205524889ce591e1a28d8928a2dd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 23 Oct 2017 11:37:29 +0200 Subject: [PATCH 373/394] Introduce MultiCursorSession for easier state handling --- .../contrib/multicursor/common/multicursor.ts | 510 +++++++++--------- .../test/common/multicursor.test.ts | 2 + .../test/common/mocks/mockCodeEditor.ts | 5 +- 3 files changed, 271 insertions(+), 246 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index e0b8c4fe317..060cac511fe 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -149,25 +149,163 @@ class InsertCursorAtEndOfEachLineSelected extends EditorAction { } } -export interface IMultiCursorFindInput { - changeFindSearchString: boolean; - allowMultiline: boolean; - highlightFindOptions: boolean; -} - -export interface IMultiCursorFindResult { - searchText: string; - matchCase: boolean; - wholeWord: boolean; - - currentMatch: Selection; -} - -class SearchSettings { +export class MultiCursorSessionResult { constructor( + public readonly selections: Selection[], + public readonly revealRange: Range, + public readonly revealScrollType: ScrollType + ) { } +} + +export class MultiCursorSession { + + public static create(editor: ICommonCodeEditor, findController: CommonFindController): MultiCursorSession { + const findState = findController.getState(); + + // Find widget owns entirely what we search for if: + // - focus is not in the editor (i.e. it is in the find widget) + // - and the search widget is visible + // - and the search string is non-empty + if (!editor.isFocused() && findState.isRevealed && findState.searchString.length > 0) { + // Find widget owns what is searched for + return new MultiCursorSession(editor, findController, false, findState.searchString, findState.wholeWord, findState.matchCase, null); + } + + // Otherwise, the selection gives the search text, and the find widget gives the search settings + // The exception is the find state disassociation case: when beginning with a single, collapsed selection + let isDisconnectedFromFindController = false; + let wholeWord: boolean; + let matchCase: boolean; + const selections = editor.getSelections(); + if (selections.length === 1 && selections[0].isEmpty()) { + isDisconnectedFromFindController = true; + wholeWord = true; + matchCase = true; + } else { + wholeWord = findState.wholeWord; + matchCase = findState.matchCase; + } + + // Selection owns what is searched for + const s = editor.getSelection(); + + let searchText: string; + let currentMatch: Selection = null; + + if (s.isEmpty()) { + // selection is empty => expand to current word + const word = editor.getModel().getWordAtPosition(s.getStartPosition()); + if (!word) { + return null; + } + searchText = word.word; + currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn); + } else { + searchText = editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); + } + + return new MultiCursorSession(editor, findController, isDisconnectedFromFindController, searchText, wholeWord, matchCase, currentMatch); + } + + constructor( + private readonly _editor: ICommonCodeEditor, + private readonly _findController: CommonFindController, + private readonly _isDisconnectedFromFindController: boolean, + public readonly searchText: string, public readonly wholeWord: boolean, public readonly matchCase: boolean, + public currentMatch: Selection ) { } + + public addSelectionToNextFindMatch(): MultiCursorSessionResult { + const nextMatch = this._getNextMatch(); + if (!nextMatch) { + return null; + } + + const allSelections = this._editor.getSelections(); + return new MultiCursorSessionResult(allSelections.concat(nextMatch), nextMatch, ScrollType.Smooth); + } + + public moveSelectionToNextFindMatch(): MultiCursorSessionResult { + const nextMatch = this._getNextMatch(); + if (!nextMatch) { + return null; + } + + const allSelections = this._editor.getSelections(); + return new MultiCursorSessionResult(allSelections.slice(0, allSelections.length - 1).concat(nextMatch), nextMatch, ScrollType.Smooth); + } + + private _getNextMatch(): Selection { + if (this.currentMatch) { + const result = this.currentMatch; + this.currentMatch = null; + return result; + } + + if (!this._isDisconnectedFromFindController) { + this._findController.highlightFindOptions(); + } + + const allSelections = this._editor.getSelections(); + const lastAddedSelection = allSelections[allSelections.length - 1]; + const nextMatch = this._editor.getModel().findNextMatch(this.searchText, lastAddedSelection.getEndPosition(), false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); + + if (!nextMatch) { + return null; + } + return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn); + } + + public addSelectionToPreviousFindMatch(): MultiCursorSessionResult { + const previousMatch = this._getPreviousMatch(); + if (!previousMatch) { + return null; + } + + const allSelections = this._editor.getSelections(); + return new MultiCursorSessionResult(allSelections.concat(previousMatch), previousMatch, ScrollType.Smooth); + } + + public moveSelectionToPreviousFindMatch(): MultiCursorSessionResult { + const previousMatch = this._getPreviousMatch(); + if (!previousMatch) { + return null; + } + + const allSelections = this._editor.getSelections(); + return new MultiCursorSessionResult(allSelections.slice(0, allSelections.length - 1).concat(previousMatch), previousMatch, ScrollType.Smooth); + } + + private _getPreviousMatch(): Selection { + if (this.currentMatch) { + const result = this.currentMatch; + this.currentMatch = null; + return result; + } + + if (!this._isDisconnectedFromFindController) { + this._findController.highlightFindOptions(); + } + + const allSelections = this._editor.getSelections(); + const lastAddedSelection = allSelections[allSelections.length - 1]; + const previousMatch = this._editor.getModel().findPreviousMatch(this.searchText, lastAddedSelection.getStartPosition(), false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); + + if (!previousMatch) { + return null; + } + return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn); + } + + public selectAll(): FindMatch[] { + if (!this._isDisconnectedFromFindController) { + this._findController.highlightFindOptions(); + } + + return this._editor.getModel().findMatches(this.searchText, true, false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); + } } @commonEditorContribution @@ -176,9 +314,9 @@ export class MultiCursorSelectionController extends Disposable implements IEdito private static ID = 'editor.contrib.multiCursorController'; private readonly _editor: ICommonCodeEditor; - private _isDisconnectedFromFindController: boolean; private _ignoreSelectionChange: boolean; - private _disconnectDispose: IDisposable[]; + private _session: MultiCursorSession; + private _sessionDispose: IDisposable[]; public static get(editor: ICommonCodeEditor): MultiCursorSelectionController { return editor.getContribution(MultiCursorSelectionController.ID); @@ -187,12 +325,13 @@ export class MultiCursorSelectionController extends Disposable implements IEdito constructor(editor: ICommonCodeEditor) { super(); this._editor = editor; - this._isDisconnectedFromFindController = false; this._ignoreSelectionChange = false; - this._disconnectDispose = []; + this._session = null; + this._sessionDispose = []; } public dispose(): void { + this._endSession(); super.dispose(); } @@ -200,27 +339,38 @@ export class MultiCursorSelectionController extends Disposable implements IEdito return MultiCursorSelectionController.ID; } - private _beginFindControllerDisconnect(): void { - if (this._isDisconnectedFromFindController) { - return; + private _beginSessionIfNeeded(findController: CommonFindController): void { + if (!this._session) { + // Create a new session + const session = MultiCursorSession.create(this._editor, findController); + if (!session) { + return; + } + + this._session = session; + this._sessionDispose = [ + this._editor.onDidChangeCursorSelection((e) => { + if (this._ignoreSelectionChange) { + return; + } + this._endSession(); + }), + this._editor.onDidBlurEditorText(() => { + this._endSession(); + }) + ]; + // TODO: seed find string + // if (input.changeFindSearchString) { + // findController.setSearchString(searchText); + // } + + // TODO: stop find matches } - this._isDisconnectedFromFindController = true; - this._disconnectDispose = [ - this._editor.onDidChangeCursorSelection((e) => { - if (this._ignoreSelectionChange) { - return; - } - this._endFindControllerDisconnect(); - }) - ]; } - private _endFindControllerDisconnect(): void { - if (!this._isDisconnectedFromFindController) { - return; - } - this._isDisconnectedFromFindController = false; - this._disconnectDispose = dispose(this._disconnectDispose); + private _endSession(): void { + this._session = null; + this._sessionDispose = dispose(this._sessionDispose); } private _setSelections(selections: Selection[]): void { @@ -229,121 +379,6 @@ export class MultiCursorSelectionController extends Disposable implements IEdito this._ignoreSelectionChange = false; } - private _getSearchSettings(findController: CommonFindController): SearchSettings { - if (this._isDisconnectedFromFindController) { - // find state disassociation - return new SearchSettings(true, true); - } - const selections = this._editor.getSelections(); - if (selections.length === 1 && selections[0].isEmpty()) { - // find state disassociation - return new SearchSettings(true, true); - } - const findState = findController.getState(); - return new SearchSettings(findState.wholeWord, findState.matchCase); - } - - public multiCursorFind(findController: CommonFindController, input: IMultiCursorFindInput): IMultiCursorFindResult { - const findState = findController.getState(); - let searchText: string; - let currentMatch: Selection; - - const { wholeWord, matchCase } = this._getSearchSettings(findController); - - // Find widget owns what we search for if: - // - focus is not in the editor (i.e. it is in the find widget) - // - and the search widget is visible - // - and the search string is non-empty - if (!this._editor.isFocused() && findState.isRevealed && findState.searchString.length > 0) { - // Find widget owns what is searched for - searchText = findState.searchString; - } else { - // Selection owns what is searched for - const s = this._editor.getSelection(); - - if (s.startLineNumber !== s.endLineNumber && !input.allowMultiline) { - // multiline forbidden - return null; - } - - if (s.isEmpty()) { - // selection is empty => expand to current word - const word = this._editor.getModel().getWordAtPosition(s.getStartPosition()); - if (!word) { - return null; - } - searchText = word.word; - currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn); - } else { - searchText = this._editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n'); - } - if (input.changeFindSearchString) { - findController.setSearchString(searchText); - } - } - - if (input.highlightFindOptions) { - findController.highlightFindOptions(); - } - - return { - searchText: searchText, - matchCase: matchCase, - wholeWord: wholeWord, - currentMatch: currentMatch - }; - } - - private _getNextMatch(findController: CommonFindController): Selection { - let r = this.multiCursorFind(findController, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { - return null; - } - if (r.currentMatch) { - return r.currentMatch; - } - - let allSelections = this._editor.getSelections(); - let lastAddedSelection = allSelections[allSelections.length - 1]; - - let nextMatch = this._editor.getModel().findNextMatch(r.searchText, lastAddedSelection.getEndPosition(), false, r.matchCase, r.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); - - if (!nextMatch) { - return null; - } - - return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn); - } - - private _getPreviousMatch(findController: CommonFindController): Selection { - let r = this.multiCursorFind(findController, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { - return null; - } - if (r.currentMatch) { - return r.currentMatch; - } - - let allSelections = this._editor.getSelections(); - let lastAddedSelection = allSelections[allSelections.length - 1]; - - let previousMatch = this._editor.getModel().findPreviousMatch(r.searchText, lastAddedSelection.getStartPosition(), false, r.matchCase, r.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); - - if (!previousMatch) { - return null; - } - - return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn); - } - private _getValueInRange(model: IModel, range: Range, toLowerCase: boolean): string { const text = model.getValueInRange(range); return (toLowerCase ? text.toLowerCase() : text); @@ -376,95 +411,92 @@ export class MultiCursorSelectionController extends Disposable implements IEdito return new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); } - public addSelectionToNextFindMatch(findController: CommonFindController): void { - const allSelections = this._editor.getSelections(); - - // If there are multiple cursors, handle the case where they do not all select the same text. - if (allSelections.length > 1) { - const matchCase = this._getSearchSettings(findController).matchCase; - const selectionsContainSameText = this._rangesContainSameText(allSelections, matchCase); - if (!selectionsContainSameText) { - const model = this._editor.getModel(); - let resultingSelections: Selection[] = []; - for (let i = 0, len = allSelections.length; i < len; i++) { - resultingSelections[i] = this._expandEmptyToWord(model, allSelections[i]); - } - this._editor.setSelections(resultingSelections); - return; - } - } - - let nextMatch = this._getNextMatch(findController); - - if (!nextMatch) { + private _applySessionResult(result: MultiCursorSessionResult): void { + if (!result) { return; } - - if (allSelections.length === 1 && allSelections[0].isEmpty()) { - // Enter find state disassociation - this._beginFindControllerDisconnect(); + this._setSelections(result.selections); + if (result.revealRange) { + this._editor.revealRangeInCenterIfOutsideViewport(result.revealRange, result.revealScrollType); } + } - this._setSelections(allSelections.concat(nextMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); + public getSession(findController: CommonFindController): MultiCursorSession { + if (this._session) { + return this._session; + } + // Create a new session + return MultiCursorSession.create(this._editor, findController); + } + + public addSelectionToNextFindMatch(findController: CommonFindController): void { + if (!this._session) { + // If there are multiple cursors, handle the case where they do not all select the same text. + const allSelections = this._editor.getSelections(); + if (allSelections.length > 1) { + const findState = findController.getState(); + const matchCase = findState.matchCase; + const selectionsContainSameText = this._rangesContainSameText(allSelections, matchCase); + if (!selectionsContainSameText) { + const model = this._editor.getModel(); + let resultingSelections: Selection[] = []; + for (let i = 0, len = allSelections.length; i < len; i++) { + resultingSelections[i] = this._expandEmptyToWord(model, allSelections[i]); + } + this._editor.setSelections(resultingSelections); + return; + } + } + } + this._beginSessionIfNeeded(findController); + if (this._session) { + this._applySessionResult(this._session.addSelectionToNextFindMatch()); + } } public addSelectionToPreviousFindMatch(findController: CommonFindController): void { - let previousMatch = this._getPreviousMatch(findController); - - if (!previousMatch) { - return; + this._beginSessionIfNeeded(findController); + if (this._session) { + this._applySessionResult(this._session.addSelectionToPreviousFindMatch()); } - - let allSelections = this._editor.getSelections(); - this._setSelections(allSelections.concat(previousMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); } public moveSelectionToNextFindMatch(findController: CommonFindController): void { - let nextMatch = this._getNextMatch(findController); - - if (!nextMatch) { - return; + this._beginSessionIfNeeded(findController); + if (this._session) { + this._applySessionResult(this._session.moveSelectionToNextFindMatch()); } - - let allSelections = this._editor.getSelections(); - this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(nextMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(nextMatch, ScrollType.Smooth); } public moveSelectionToPreviousFindMatch(findController: CommonFindController): void { - let previousMatch = this._getPreviousMatch(findController); - - if (!previousMatch) { - return; + this._beginSessionIfNeeded(findController); + if (this._session) { + this._applySessionResult(this._session.addSelectionToPreviousFindMatch()); } - - let allSelections = this._editor.getSelections(); - this._setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch)); - this._editor.revealRangeInCenterIfOutsideViewport(previousMatch, ScrollType.Smooth); } public selectAll(findController: CommonFindController): void { let matches: FindMatch[] = null; const findState = findController.getState(); - if (findState.isRevealed && findState.searchString.length > 0 && findState.isRegex) { + + // Special case: find widget owns entirely what we search for if: + // - focus is not in the editor (i.e. it is in the find widget) + // - and the search widget is visible + // - and the search string is non-empty + // - and we're searching for a regex + if (!this._editor.isFocused() && findState.isRevealed && findState.searchString.length > 0 && findState.isRegex) { matches = this._editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); } else { - const r = this.multiCursorFind(findController, { - changeFindSearchString: true, - allowMultiline: true, - highlightFindOptions: true - }); - if (!r) { + this._beginSessionIfNeeded(findController); + if (!this._session) { return; } - matches = this._editor.getModel().findMatches(r.searchText, true, false, r.matchCase, r.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); + matches = this._session.selectAll(); } if (matches.length > 0) { @@ -481,12 +513,6 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } } - const allSelections = this._editor.getSelections(); - if (allSelections.length === 1 && allSelections[0].isEmpty()) { - // Enter find state disassociation - this._beginFindControllerDisconnect(); - } - this._setSelections(matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn))); } } @@ -509,18 +535,6 @@ export abstract class MultiCursorSelectionControllerAction extends EditorAction protected abstract _run(multiCursorController: MultiCursorSelectionController, findController: CommonFindController): void; } -function multiCursorFind(editor: ICommonCodeEditor, input: IMultiCursorFindInput): IMultiCursorFindResult { - const multiCursorController = MultiCursorSelectionController.get(editor); - if (!multiCursorController) { - return null; - } - const findController = CommonFindController.get(editor); - if (!findController) { - return null; - } - return multiCursorController.multiCursorFind(findController, input); -} - @editorAction export class AddSelectionToNextFindMatchAction extends MultiCursorSelectionControllerAction { constructor() { @@ -723,27 +737,37 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut } private static _createState(isEnabled: boolean, editor: ICommonCodeEditor): SelectionHighlighterState { + if (!isEnabled) { + return null; + } + const model = editor.getModel(); if (!model) { return null; } - const config = editor.getConfiguration(); - - let lastWordUnderCursor: Selection = null; - if (!isEnabled) { + const s = editor.getSelection(); + if (s.startLineNumber !== s.endLineNumber) { + // multiline forbidden for perf reasons return null; } - const r = multiCursorFind(editor, { - changeFindSearchString: false, - allowMultiline: false, - highlightFindOptions: false - }); + const multiCursorController = MultiCursorSelectionController.get(editor); + if (!multiCursorController) { + return null; + } + + const findController = CommonFindController.get(editor); + if (!findController) { + return null; + } + + const r = multiCursorController.getSession(findController); if (!r) { return null; } + let lastWordUnderCursor: Selection = null; const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model); if (r.currentMatch) { // This is an empty selection @@ -752,6 +776,7 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut return null; } + const config = editor.getConfiguration(); if (!config.contribInfo.occurrencesHighlight) { return null; } @@ -767,13 +792,9 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut return null; } - const controller = CommonFindController.get(editor); - if (!controller) { - return null; - } - const findState = controller.getState(); + // TODO: better handling of this case + const findState = findController.getState(); const caseSensitive = findState.matchCase; - const selections = editor.getSelections(); let firstSelectedText = model.getValueInRange(selections[0]); if (!caseSensitive) { @@ -810,7 +831,6 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut return new SelectionHighlighterState(lastWordUnderCursor, r.searchText, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null); } - private _setState(state: SelectionHighlighterState): void { if (SelectionHighlighterState.softEquals(this.state, state)) { this.state = state; diff --git a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts index 1a7c90d18e9..93c8377b9d0 100644 --- a/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/common/multicursor.test.ts @@ -100,6 +100,8 @@ suite('Multicursor selection', () => { let multiCursorSelectController = editor.registerAndInstantiateContribution(MultiCursorSelectionController); let selectHighlightsAction = new SelectHighlightsAction(); + editor._isFocused = false; + editor.setSelection(new Selection(1, 1, 1, 1)); findController.getState().change({ searchString: 'some+thing', isRegex: true, isRevealed: true }, false); diff --git a/src/vs/editor/test/common/mocks/mockCodeEditor.ts b/src/vs/editor/test/common/mocks/mockCodeEditor.ts index afb99c73774..33621c3d209 100644 --- a/src/vs/editor/test/common/mocks/mockCodeEditor.ts +++ b/src/vs/editor/test/common/mocks/mockCodeEditor.ts @@ -18,6 +18,9 @@ import * as editorOptions from 'vs/editor/common/config/editorOptions'; import { IDisposable } from 'vs/base/common/lifecycle'; export class MockCodeEditor extends CommonCodeEditor { + + public _isFocused = true; + protected _createConfiguration(options: editorOptions.IEditorOptions): CommonEditorConfiguration { return new TestConfiguration(options); } @@ -25,7 +28,7 @@ export class MockCodeEditor extends CommonCodeEditor { public layout(dimension?: editorCommon.IDimension): void { } public focus(): void { } - public isFocused(): boolean { return true; } + public isFocused(): boolean { return this._isFocused; } public hasWidgetFocus(): boolean { return true; }; protected _enableEmptySelectionClipboard(): boolean { return false; } From 9df513f98e89bae4fab4414c9639828bd15ce892 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 23 Oct 2017 11:44:58 +0200 Subject: [PATCH 374/394] use native promise, no async-await, no winjs promise, #36427 --- .../electron-browser/snippets.contribution.ts | 2 +- .../snippets/electron-browser/snippetsFile.ts | 5 +- .../electron-browser/snippetsService.ts | 141 ++++++++++-------- .../electron-browser/snippetsService.test.ts | 82 +++++----- 4 files changed, 122 insertions(+), 108 deletions(-) diff --git a/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts b/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts index 5e51b4e6c97..02f11542192 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts @@ -26,7 +26,7 @@ export interface ISnippetsService { _serviceBrand: any; - getSnippets(languageId: LanguageId): TPromise; + getSnippets(languageId: LanguageId): Promise; getSnippetsSync(languageId: LanguageId): Snippet[]; } diff --git a/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.ts b/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.ts index 11bf43c590f..109a7175e8a 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.ts @@ -7,7 +7,6 @@ import { readFile } from 'vs/base/node/pfs'; import { parse as jsonParse } from 'vs/base/common/json'; -import { TPromise } from 'vs/base/common/winjs.base'; import { SnippetParser, Variable, Placeholder, Text } from 'vs/editor/contrib/snippet/browser/snippetParser'; import { EditorSnippetVariableResolver } from 'vs/editor/contrib/snippet/browser/snippetVariables'; import { forEach } from 'vs/base/common/collections'; @@ -36,8 +35,8 @@ export class SnippetFile { // } - static fromFile(filepath: string, source: string, isFromExtension?: boolean): TPromise { - return readFile(filepath).then(value => { + static fromFile(filepath: string, source: string, isFromExtension?: boolean): Promise { + return Promise.resolve(readFile(filepath)).then(value => { const data = jsonParse(value.toString()); const snippets: Snippet[] = []; if (typeof data === 'object') { diff --git a/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts b/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts index c469f02372b..22b1571da3a 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts @@ -20,7 +20,6 @@ import { join } from 'path'; import { mkdirp } from 'vs/base/node/pfs'; import { watch } from 'fs'; import { SnippetFile } from 'vs/workbench/parts/snippets/electron-browser/snippetsFile'; -import { TPromise } from 'vs/base/common/winjs.base'; import { Snippet, ISnippetsService } from 'vs/workbench/parts/snippets/electron-browser/snippets.contribution'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { ExtensionsRegistry, IExtensionPointUser } from 'vs/platform/extensions/common/extensionsRegistry'; @@ -114,21 +113,22 @@ class SnippetsService implements ISnippetsService { dispose(this._disposables); } - async getSnippets(languageId: LanguageId): TPromise { + getSnippets(languageId: LanguageId): Promise { let result: Snippet[] = []; - await TPromise.join([ + return Promise.all([ this._extensionService.onReady(), this._getOrLoadUserSnippets(languageId, result), this._getOrLoadExtensionSnippets(languageId, result) - ]); - return result; + ]).then(() => { + return result; + }); } getSnippetsSync(languageId: LanguageId): Snippet[] { // just kick off snippet loading for this language such // that subseqent calls to this method return more // correct results - this.getSnippets(languageId).done(undefined, undefined); + this.getSnippets(languageId).catch(undefined); // collect and return what we already have let userSnippets = this._userSnippets.get(languageId); @@ -138,8 +138,8 @@ class SnippetsService implements ISnippetsService { // --- extension snippet logic --- - private async _prepExtensionSnippets(): TPromise { - ExtensionsRegistry.registerExtensionPoint('snippets', [languagesExtPoint], schema.snippetsContribution).setHandler(async extensions => { + private _prepExtensionSnippets(): void { + ExtensionsRegistry.registerExtensionPoint('snippets', [languagesExtPoint], schema.snippetsContribution).setHandler(extensions => { for (const extension of extensions) { for (const contribution of extension.value) { if (schema.isValidSnippet(extension, contribution, this._modeService)) { @@ -156,10 +156,11 @@ class SnippetsService implements ISnippetsService { }); } - private async _getOrLoadExtensionSnippets(languageId: LanguageId, bucket: Snippet[]): TPromise { + private _getOrLoadExtensionSnippets(languageId: LanguageId, bucket: Snippet[]): Promise { if (this._extensionSnippets.has(languageId)) { bucket.push(...this._extensionSnippets.get(languageId)); + return undefined; } else if (this._pendingExtensionSnippets.has(languageId)) { const pending = this._pendingExtensionSnippets.get(languageId); @@ -168,22 +169,14 @@ class SnippetsService implements ISnippetsService { const snippets = []; this._extensionSnippets.set(languageId, snippets); - for (const [extension, filepath] of pending) { - let file: SnippetFile; - try { - file = await SnippetFile.fromFile(filepath, extension.description.displayName || extension.description.name, true); - } catch (e) { - extension.collector.warn(localize( - 'badFile', - "The snippet file \"{0}\" could not be read.", - filepath - )); - } - if (file) { + return Promise.all(pending.map(([extension, filepath]) => { + return SnippetFile.fromFile(filepath, extension.description.displayName || extension.description.name, true).then(file => { for (const snippet of file.data) { snippets.push(snippet); bucket.push(snippet); + if (snippet.isBogous) { + // warn about bad tabstop/variable usage extension.collector.warn(localize( 'badVariableUse', "The \"{0}\"-snippet very likely confuses snippet-variables and snippet-placeholders. See https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax for more details.", @@ -191,26 +184,42 @@ class SnippetsService implements ISnippetsService { )); } } - } - } + + }, err => { + // generic error + extension.collector.warn(localize( + 'badFile', + "The snippet file \"{0}\" could not be read.", + filepath + )); + }); + })); + + } else { + return undefined; } } // --- user snippet logic --- - private async _getOrLoadUserSnippets(languageId: LanguageId, bucket: Snippet[]): TPromise { + private _getOrLoadUserSnippets(languageId: LanguageId, bucket: Snippet[]): Promise { let snippets = this._userSnippets.get(languageId); - if (snippets === undefined) { - try { - snippets = (await SnippetFile.fromFile(this._getUserSnippetFilepath(languageId), localize('source.snippet', "User Snippet"))).data; - } catch (e) { - snippets = null; - } - this._userSnippets.set(languageId, snippets); - } - if (snippets) { + // has data bucket.push(...snippets); + return undefined; + + } else if (snippets === undefined) { + // not yet loaded + return SnippetFile.fromFile(this._getUserSnippetFilepath(languageId), localize('source.snippet', "User Snippet")).then(file => { + this._userSnippets.set(languageId, file.data); + }, err => { + this._userSnippets.set(languageId, null); + }); + + } else { + // previous failure + return undefined; } } @@ -291,49 +300,51 @@ export class SnippetSuggestProvider implements ISuggestSupport { // } - async provideCompletionItems(model: IModel, position: Position): TPromise { + provideCompletionItems(model: IModel, position: Position): Promise { const languageId = this._getLanguageIdAtPosition(model, position); - const snippets = await this._snippets.getSnippets(languageId); - const suggestions: SnippetSuggestion[] = []; + return this._snippets.getSnippets(languageId).then(snippets => { - const lowWordUntil = model.getWordUntilPosition(position).word.toLowerCase(); - const lowLineUntil = model.getLineContent(position.lineNumber).substr(Math.max(0, position.column - 100), position.column - 1).toLowerCase(); + const suggestions: SnippetSuggestion[] = []; - for (const snippet of snippets) { + const lowWordUntil = model.getWordUntilPosition(position).word.toLowerCase(); + const lowLineUntil = model.getLineContent(position.lineNumber).substr(Math.max(0, position.column - 100), position.column - 1).toLowerCase(); - const lowPrefix = snippet.prefix.toLowerCase(); - let overwriteBefore = 0; - let accetSnippet = true; + for (const snippet of snippets) { - if (lowWordUntil.length > 0 && startsWith(lowPrefix, lowWordUntil)) { - // cheap match on the (none-empty) current word - overwriteBefore = lowWordUntil.length; - accetSnippet = true; + const lowPrefix = snippet.prefix.toLowerCase(); + let overwriteBefore = 0; + let accetSnippet = true; - } else if (lowLineUntil.length > 0 && lowLineUntil.match(/[^\s]$/)) { - // compute overlap between snippet and (none-empty) line on text - overwriteBefore = overlap(lowLineUntil, snippet.prefix.toLowerCase()); - accetSnippet = overwriteBefore > 0 && !model.getWordAtPosition(new Position(position.lineNumber, position.column - overwriteBefore)); + if (lowWordUntil.length > 0 && startsWith(lowPrefix, lowWordUntil)) { + // cheap match on the (none-empty) current word + overwriteBefore = lowWordUntil.length; + accetSnippet = true; + + } else if (lowLineUntil.length > 0 && lowLineUntil.match(/[^\s]$/)) { + // compute overlap between snippet and (none-empty) line on text + overwriteBefore = overlap(lowLineUntil, snippet.prefix.toLowerCase()); + accetSnippet = overwriteBefore > 0 && !model.getWordAtPosition(new Position(position.lineNumber, position.column - overwriteBefore)); + } + + if (accetSnippet) { + suggestions.push(new SnippetSuggestion(snippet, overwriteBefore)); + } } - if (accetSnippet) { - suggestions.push(new SnippetSuggestion(snippet, overwriteBefore)); + // dismbiguate suggestions with same labels + let lastItem: SnippetSuggestion; + for (const item of suggestions.sort(SnippetSuggestion.compareByLabel)) { + if (lastItem && lastItem.label === item.label) { + // use the disambiguateLabel instead of the actual label + lastItem.label = localize('snippetSuggest.longLabel', "{0}, {1}", lastItem.label, lastItem.snippet.name); + item.label = localize('snippetSuggest.longLabel', "{0}, {1}", item.label, item.snippet.name); + } + lastItem = item; } - } - // dismbiguate suggestions with same labels - let lastItem: SnippetSuggestion; - for (const item of suggestions.sort(SnippetSuggestion.compareByLabel)) { - if (lastItem && lastItem.label === item.label) { - // use the disambiguateLabel instead of the actual label - lastItem.label = localize('snippetSuggest.longLabel', "{0}, {1}", lastItem.label, lastItem.snippet.name); - item.label = localize('snippetSuggest.longLabel', "{0}, {1}", item.label, item.snippet.name); - } - lastItem = item; - } - - return { suggestions }; + return { suggestions }; + }); } resolveCompletionItem?(model: IModel, position: Position, item: ISuggestion): ISuggestion { diff --git a/src/vs/workbench/parts/snippets/test/electron-browser/snippetsService.test.ts b/src/vs/workbench/parts/snippets/test/electron-browser/snippetsService.test.ts index bfeb7ee9116..169053ca38a 100644 --- a/src/vs/workbench/parts/snippets/test/electron-browser/snippetsService.test.ts +++ b/src/vs/workbench/parts/snippets/test/electron-browser/snippetsService.test.ts @@ -12,14 +12,13 @@ import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { Model } from 'vs/editor/common/model/model'; import { ISnippetsService, Snippet } from 'vs/workbench/parts/snippets/electron-browser/snippets.contribution'; -import { TPromise } from 'vs/base/common/winjs.base'; class SimpleSnippetService implements ISnippetsService { _serviceBrand: any; constructor(readonly snippets: Snippet[]) { } getSnippets() { - return TPromise.as(this.getSnippetsSync()); + return Promise.resolve(this.getSnippetsSync()); } getSnippetsSync(): Snippet[] { return this.snippets; @@ -56,31 +55,31 @@ suite('SnippetsService', function () { }); - test('snippet completions - simple', async function () { + test('snippet completions - simple', function () { const provider = new SnippetSuggestProvider(modeService, snippetService); const model = Model.createFromString('', undefined, modeService.getLanguageIdentifier('fooLang')); - const result = await provider.provideCompletionItems(model, new Position(1, 1)); - - assert.equal(result.incomplete, undefined); - assert.equal(result.suggestions.length, 2); + return provider.provideCompletionItems(model, new Position(1, 1)).then(result => { + assert.equal(result.incomplete, undefined); + assert.equal(result.suggestions.length, 2); + }); }); - test('snippet completions - with prefix', async function () { + test('snippet completions - with prefix', function () { const provider = new SnippetSuggestProvider(modeService, snippetService); const model = Model.createFromString('bar', undefined, modeService.getLanguageIdentifier('fooLang')); - const result = await provider.provideCompletionItems(model, new Position(1, 4)); - - assert.equal(result.incomplete, undefined); - assert.equal(result.suggestions.length, 1); - assert.equal(result.suggestions[0].label, 'bar'); - assert.equal(result.suggestions[0].insertText, 'barCodeSnippet'); + return provider.provideCompletionItems(model, new Position(1, 4)).then(result => { + assert.equal(result.incomplete, undefined); + assert.equal(result.suggestions.length, 1); + assert.equal(result.suggestions[0].label, 'bar'); + assert.equal(result.suggestions[0].insertText, 'barCodeSnippet'); + }); }); - test('Cannot use " { + assert.equal(result.suggestions.length, 1); + model.dispose(); - model = Model.createFromString('\t { + assert.equal(result.suggestions.length, 1); + model.dispose(); - model = Model.createFromString('a { + + assert.equal(result.suggestions.length, 0); + model.dispose(); + }); }); - test('No user snippets in suggestions, when inside the code, #30508', async function () { + test('No user snippets in suggestions, when inside the code, #30508', function () { snippetService = new SimpleSnippetService([{ prefix: 'foo', @@ -120,14 +123,15 @@ suite('SnippetsService', function () { const provider = new SnippetSuggestProvider(modeService, snippetService); let model = Model.createFromString('\n\t\n>/head>', undefined, modeService.getLanguageIdentifier('fooLang')); - let result = await provider.provideCompletionItems(model, new Position(1, 1)); - assert.equal(result.suggestions.length, 1); - - result = await provider.provideCompletionItems(model, new Position(2, 2)); - assert.equal(result.suggestions.length, 1); + return provider.provideCompletionItems(model, new Position(1, 1)).then(result => { + assert.equal(result.suggestions.length, 1); + return provider.provideCompletionItems(model, new Position(2, 2)); + }).then(result => { + assert.equal(result.suggestions.length, 1); + }); }); - test('SnippetSuggest - ensure extension snippets come last ', async function () { + test('SnippetSuggest - ensure extension snippets come last ', function () { snippetService = new SimpleSnippetService([{ prefix: 'second', codeSnippet: 'second', @@ -147,11 +151,11 @@ suite('SnippetsService', function () { const provider = new SnippetSuggestProvider(modeService, snippetService); let model = Model.createFromString('', undefined, modeService.getLanguageIdentifier('fooLang')); - let result = await provider.provideCompletionItems(model, new Position(1, 1)); - assert.equal(result.suggestions.length, 2); - - let [first, second] = result.suggestions; - assert.equal(first.label, 'first'); - assert.equal(second.label, 'second'); + return provider.provideCompletionItems(model, new Position(1, 1)).then(result => { + assert.equal(result.suggestions.length, 2); + let [first, second] = result.suggestions; + assert.equal(first.label, 'first'); + assert.equal(second.label, 'second'); + }); }); }); From c3cab83672fd55817938499209aa125698ca8686 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 23 Oct 2017 14:42:25 +0200 Subject: [PATCH 375/394] Add overrides to find widget toggles --- .../editor/contrib/find/common/findState.ts | 71 +++++++--- .../contrib/multicursor/common/multicursor.ts | 129 +++++++++--------- 2 files changed, 117 insertions(+), 83 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findState.ts b/src/vs/editor/contrib/find/common/findState.ts index 0dccd531f7a..000ee49bfd5 100644 --- a/src/vs/editor/contrib/find/common/findState.ts +++ b/src/vs/editor/contrib/find/common/findState.ts @@ -25,17 +25,36 @@ export interface FindReplaceStateChangedEvent { currentMatch: boolean; } +export const enum FindOptionOverride { + NotSet = 0, + True = 1, + False = 2 +} + export interface INewFindReplaceState { searchString?: string; replaceString?: string; isRevealed?: boolean; isReplaceRevealed?: boolean; isRegex?: boolean; + isRegexOverride?: FindOptionOverride; wholeWord?: boolean; + wholeWordOverride?: FindOptionOverride; matchCase?: boolean; + matchCaseOverride?: FindOptionOverride; searchScope?: Range; } +function effectiveOptionValue(override: FindOptionOverride, value: boolean): boolean { + if (override === FindOptionOverride.True) { + return true; + } + if (override === FindOptionOverride.False) { + return false; + } + return value; +} + export class FindReplaceState implements IDisposable { private static _CHANGED_EVENT = 'changed'; @@ -45,8 +64,11 @@ export class FindReplaceState implements IDisposable { private _isRevealed: boolean; private _isReplaceRevealed: boolean; private _isRegex: boolean; + private _isRegexOverride: FindOptionOverride; private _wholeWord: boolean; + private _wholeWordOverride: FindOptionOverride; private _matchCase: boolean; + private _matchCaseOverride: FindOptionOverride; private _searchScope: Range; private _matchesPosition: number; private _matchesCount: number; @@ -57,9 +79,9 @@ export class FindReplaceState implements IDisposable { public get replaceString(): string { return this._replaceString; } public get isRevealed(): boolean { return this._isRevealed; } public get isReplaceRevealed(): boolean { return this._isReplaceRevealed; } - public get isRegex(): boolean { return this._isRegex; } - public get wholeWord(): boolean { return this._wholeWord; } - public get matchCase(): boolean { return this._matchCase; } + public get isRegex(): boolean { return effectiveOptionValue(this._isRegexOverride, this._isRegex); } + public get wholeWord(): boolean { return effectiveOptionValue(this._wholeWordOverride, this._wholeWord); } + public get matchCase(): boolean { return effectiveOptionValue(this._matchCaseOverride, this._matchCase); } public get searchScope(): Range { return this._searchScope; } public get matchesPosition(): number { return this._matchesPosition; } public get matchesCount(): number { return this._matchesCount; } @@ -71,8 +93,11 @@ export class FindReplaceState implements IDisposable { this._isRevealed = false; this._isReplaceRevealed = false; this._isRegex = false; + this._isRegexOverride = FindOptionOverride.NotSet; this._wholeWord = false; + this._wholeWordOverride = FindOptionOverride.NotSet; this._matchCase = false; + this._matchCaseOverride = FindOptionOverride.NotSet; this._searchScope = null; this._matchesPosition = 0; this._matchesCount = 0; @@ -155,6 +180,10 @@ export class FindReplaceState implements IDisposable { }; let somethingChanged = false; + const oldEffectiveIsRegex = this.isRegex; + const oldEffectiveWholeWords = this.wholeWord; + const oldEffectiveMatchCase = this.matchCase; + if (typeof newState.searchString !== 'undefined') { if (this._searchString !== newState.searchString) { this._searchString = newState.searchString; @@ -184,25 +213,13 @@ export class FindReplaceState implements IDisposable { } } if (typeof newState.isRegex !== 'undefined') { - if (this._isRegex !== newState.isRegex) { - this._isRegex = newState.isRegex; - changeEvent.isRegex = true; - somethingChanged = true; - } + this._isRegex = newState.isRegex; } if (typeof newState.wholeWord !== 'undefined') { - if (this._wholeWord !== newState.wholeWord) { - this._wholeWord = newState.wholeWord; - changeEvent.wholeWord = true; - somethingChanged = true; - } + this._wholeWord = newState.wholeWord; } if (typeof newState.matchCase !== 'undefined') { - if (this._matchCase !== newState.matchCase) { - this._matchCase = newState.matchCase; - changeEvent.matchCase = true; - somethingChanged = true; - } + this._matchCase = newState.matchCase; } if (typeof newState.searchScope !== 'undefined') { if (!Range.equalsRange(this._searchScope, newState.searchScope)) { @@ -212,6 +229,24 @@ export class FindReplaceState implements IDisposable { } } + // Overrides get set when they explicitly come in and get reset anytime something else changes + this._isRegexOverride = (typeof newState.isRegexOverride !== 'undefined' ? newState.isRegexOverride : FindOptionOverride.NotSet); + this._wholeWordOverride = (typeof newState.wholeWordOverride !== 'undefined' ? newState.wholeWordOverride : FindOptionOverride.NotSet); + this._matchCaseOverride = (typeof newState.matchCaseOverride !== 'undefined' ? newState.matchCaseOverride : FindOptionOverride.NotSet); + + if (oldEffectiveIsRegex !== this.isRegex) { + somethingChanged = true; + changeEvent.isRegex = true; + } + if (oldEffectiveWholeWords !== this.wholeWord) { + somethingChanged = true; + changeEvent.wholeWord = true; + } + if (oldEffectiveMatchCase !== this.matchCase) { + somethingChanged = true; + changeEvent.matchCase = true; + } + if (somethingChanged) { this._eventEmitter.emit(FindReplaceState._CHANGED_EVENT, changeEvent); } diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index 060cac511fe..a45a8226d0d 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -22,6 +22,7 @@ import { CommonFindController } from 'vs/editor/contrib/find/common/findControll import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { overviewRulerSelectionHighlightForeground } from 'vs/platform/theme/common/colorRegistry'; import { themeColorFromId } from 'vs/platform/theme/common/themeService'; +import { INewFindReplaceState, FindOptionOverride } from 'vs/editor/contrib/find/common/findState'; @editorAction export class InsertCursorAbove extends EditorAction { @@ -209,8 +210,8 @@ export class MultiCursorSession { constructor( private readonly _editor: ICommonCodeEditor, - private readonly _findController: CommonFindController, - private readonly _isDisconnectedFromFindController: boolean, + public readonly findController: CommonFindController, + public readonly isDisconnectedFromFindController: boolean, public readonly searchText: string, public readonly wholeWord: boolean, public readonly matchCase: boolean, @@ -244,9 +245,7 @@ export class MultiCursorSession { return result; } - if (!this._isDisconnectedFromFindController) { - this._findController.highlightFindOptions(); - } + this.findController.highlightFindOptions(); const allSelections = this._editor.getSelections(); const lastAddedSelection = allSelections[allSelections.length - 1]; @@ -285,9 +284,7 @@ export class MultiCursorSession { return result; } - if (!this._isDisconnectedFromFindController) { - this._findController.highlightFindOptions(); - } + this.findController.highlightFindOptions(); const allSelections = this._editor.getSelections(); const lastAddedSelection = allSelections[allSelections.length - 1]; @@ -300,9 +297,7 @@ export class MultiCursorSession { } public selectAll(): FindMatch[] { - if (!this._isDisconnectedFromFindController) { - this._findController.highlightFindOptions(); - } + this.findController.highlightFindOptions(); return this._editor.getModel().findMatches(this.searchText, true, false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, Constants.MAX_SAFE_SMALL_INTEGER); } @@ -348,6 +343,15 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } this._session = session; + + const newState: INewFindReplaceState = { searchString: this._session.searchText }; + if (this._session.isDisconnectedFromFindController) { + newState.wholeWordOverride = FindOptionOverride.True; + newState.matchCaseOverride = FindOptionOverride.True; + newState.isRegexOverride = FindOptionOverride.False; + } + findController.getState().change(newState, false); + this._sessionDispose = [ this._editor.onDidChangeCursorSelection((e) => { if (this._ignoreSelectionChange) { @@ -357,20 +361,27 @@ export class MultiCursorSelectionController extends Disposable implements IEdito }), this._editor.onDidBlurEditorText(() => { this._endSession(); + }), + findController.getState().addChangeListener((e) => { + if (e.matchCase || e.wholeWord) { + this._endSession(); + } }) ]; - // TODO: seed find string - // if (input.changeFindSearchString) { - // findController.setSearchString(searchText); - // } - - // TODO: stop find matches } } private _endSession(): void { - this._session = null; this._sessionDispose = dispose(this._sessionDispose); + if (this._session && this._session.isDisconnectedFromFindController) { + const newState: INewFindReplaceState = { + wholeWordOverride: FindOptionOverride.NotSet, + matchCaseOverride: FindOptionOverride.NotSet, + isRegexOverride: FindOptionOverride.NotSet, + }; + this._session.findController.getState().change(newState, false); + } + this._session = null; } private _setSelections(selections: Selection[]): void { @@ -379,27 +390,6 @@ export class MultiCursorSelectionController extends Disposable implements IEdito this._ignoreSelectionChange = false; } - private _getValueInRange(model: IModel, range: Range, toLowerCase: boolean): string { - const text = model.getValueInRange(range); - return (toLowerCase ? text.toLowerCase() : text); - } - - private _rangesContainSameText(ranges: Range[], matchCase: boolean): boolean { - const model = this._editor.getModel(); - const selectedText = this._getValueInRange(model, ranges[0], !matchCase); - for (let i = 1, len = ranges.length; i < len; i++) { - const range = ranges[i]; - if (range.isEmpty()) { - return false; - } - const thisSelectedText = this._getValueInRange(model, range, !matchCase); - if (selectedText !== thisSelectedText) { - return false; - } - } - return true; - } - private _expandEmptyToWord(model: IModel, selection: Selection): Selection { if (!selection.isEmpty()) { return selection; @@ -422,11 +412,7 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } public getSession(findController: CommonFindController): MultiCursorSession { - if (this._session) { - return this._session; - } - // Create a new session - return MultiCursorSession.create(this._editor, findController); + return this._session; } public addSelectionToNextFindMatch(findController: CommonFindController): void { @@ -436,7 +422,7 @@ export class MultiCursorSelectionController extends Disposable implements IEdito if (allSelections.length > 1) { const findState = findController.getState(); const matchCase = findState.matchCase; - const selectionsContainSameText = this._rangesContainSameText(allSelections, matchCase); + const selectionsContainSameText = modelRangesContainSameText(this._editor.getModel(), allSelections, matchCase); if (!selectionsContainSameText) { const model = this._editor.getModel(); let resultingSelections: Selection[] = []; @@ -740,29 +726,37 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut if (!isEnabled) { return null; } - const model = editor.getModel(); if (!model) { return null; } - const s = editor.getSelection(); if (s.startLineNumber !== s.endLineNumber) { // multiline forbidden for perf reasons return null; } - const multiCursorController = MultiCursorSelectionController.get(editor); if (!multiCursorController) { return null; } - const findController = CommonFindController.get(editor); if (!findController) { return null; } + let r = multiCursorController.getSession(findController); + if (!r) { + const allSelections = editor.getSelections(); + if (allSelections.length > 1) { + const findState = findController.getState(); + const matchCase = findState.matchCase; + const selectionsContainSameText = modelRangesContainSameText(editor.getModel(), allSelections, matchCase); + if (!selectionsContainSameText) { + return null; + } + } - const r = multiCursorController.getSession(findController); + r = MultiCursorSession.create(editor, findController); + } if (!r) { return null; } @@ -795,21 +789,6 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut // TODO: better handling of this case const findState = findController.getState(); const caseSensitive = findState.matchCase; - const selections = editor.getSelections(); - let firstSelectedText = model.getValueInRange(selections[0]); - if (!caseSensitive) { - firstSelectedText = firstSelectedText.toLowerCase(); - } - for (let i = 1; i < selections.length; i++) { - let selectedText = model.getValueInRange(selections[i]); - if (!caseSensitive) { - selectedText = selectedText.toLowerCase(); - } - if (firstSelectedText !== selectedText) { - // not all selections have the same text - return null; - } - } // Return early if the find widget shows the exact same matches if (findState.isRevealed) { @@ -911,3 +890,23 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut super.dispose(); } } + +function modelRangesContainSameText(model: IModel, ranges: Range[], matchCase: boolean): boolean { + const selectedText = getValueInRange(model, ranges[0], !matchCase); + for (let i = 1, len = ranges.length; i < len; i++) { + const range = ranges[i]; + if (range.isEmpty()) { + return false; + } + const thisSelectedText = getValueInRange(model, range, !matchCase); + if (selectedText !== thisSelectedText) { + return false; + } + } + return true; +} + +function getValueInRange(model: IModel, range: Range, toLowerCase: boolean): string { + const text = model.getValueInRange(range); + return (toLowerCase ? text.toLowerCase() : text); +} From 6779069b83446ef063cce1e48b617a98a333db60 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 23 Oct 2017 15:01:27 +0200 Subject: [PATCH 376/394] Make sure both composites are known to this composite bar in move --- src/vs/workbench/browser/parts/compositebar/compositeBar.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 7682c32759b..bbc33698401 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -403,6 +403,10 @@ export class CompositeBar implements ICompositeBar { } public move(compositeId: string, toCompositeId: string): void { + // Make sure both composites are known to this composite bar + if (this.options.composites.filter(c => c.id === compositeId || c.id === toCompositeId).length !== 2) { + return; + } // Make sure a moved composite gets pinned if (!this.isPinned(compositeId)) { this.pin(compositeId, false /* defer update, we take care of it */); From 27a2bfef88ed40dcb3f4f8358dfe7dd3f25a2f82 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 14:19:41 +0200 Subject: [PATCH 377/394] more tests (for #35572) --- src/vs/base/common/filters.ts | 2 +- .../parts/quickopen/common/quickOpenScorer.ts | 51 ++++++++++++++----- .../test/common/quickOpenScorer.test.ts | 13 +++++ 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index a943fc15c03..64abb96b9ad 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -421,7 +421,7 @@ function printTable(table: number[][], pattern: string, patternLen: number, word return ret; } -export function isSeparatorAtPos(value: string, index: number): boolean { +function isSeparatorAtPos(value: string, index: number): boolean { if (index < 0 || index >= value.length) { return false; } diff --git a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts index 7667f60d43d..5636beb5f50 100644 --- a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts +++ b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts @@ -6,10 +6,11 @@ 'use strict'; import { compareAnything } from 'vs/base/common/comparers'; -import { matchesPrefix, IMatch, createMatches, matchesCamelCase, isSeparatorAtPos, isUpper } from 'vs/base/common/filters'; +import { matchesPrefix, IMatch, createMatches, matchesCamelCase, isUpper } from 'vs/base/common/filters'; import { isEqual, nativeSep } from 'vs/base/common/paths'; import { isWindows } from 'vs/base/common/platform'; import { stripWildcards } from 'vs/base/common/strings'; +import { CharCode } from 'vs/base/common/charCode'; export type Score = [number /* score */, number[] /* match positions */]; export type ScorerCache = { [key: string]: IItemScore }; @@ -189,22 +190,26 @@ function computeCharScore(query: string, queryLower: string, queryIndex: number, // } } - // After separator bonus - else if (isSeparatorAtPos(target, targetIndex - 1)) { - score += 4; + else { - // if (DEBUG) { - // console.log('After separtor bonus: +4'); - // } - } + // After separator bonus + const separatorBonus = scoreSeparatorAtPos(target.charCodeAt(targetIndex - 1)); + if (separatorBonus) { + score += separatorBonus; - // Inside word upper case bonus - else if (isUpper(target.charCodeAt(targetIndex))) { - score += 1; + // if (DEBUG) { + // console.log('After separtor bonus: +4'); + // } + } - // if (DEBUG) { - // console.log('Inside word upper case bonus: +1'); - // } + // Inside word upper case bonus (camel case) + else if (isUpper(target.charCodeAt(targetIndex))) { + score += 1; + + // if (DEBUG) { + // console.log('Inside word upper case bonus: +1'); + // } + } } // if (DEBUG) { @@ -214,6 +219,24 @@ function computeCharScore(query: string, queryLower: string, queryIndex: number, return score; } +function scoreSeparatorAtPos(charCode: number): number { + switch (charCode) { + case CharCode.Slash: + case CharCode.Backslash: + return 5; // prefer path separators... + case CharCode.Underline: + case CharCode.Dash: + case CharCode.Period: + case CharCode.Space: + case CharCode.SingleQuote: + case CharCode.DoubleQuote: + case CharCode.Colon: + return 4; // ...over other separators + default: + return 0; + } +} + // function printMatrix(query: string, target: string, matches: number[], scores: number[]): void { // console.log('\t' + target.split('').join('\t')); // for (let queryIndex = 0; queryIndex < query.length; queryIndex++) { diff --git a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts index bcb22b89aa2..d9760c58368 100644 --- a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts +++ b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts @@ -715,6 +715,19 @@ suite('Quick Open Scorer', () => { assert.equal(res[0], resourceB); }); + test('compareFilesByScore - avoid match scattering (bug #35572)', function () { + const resourceA = URI.file('static/app/source/angluar/-admin/-organization/-settings/layout/layout.js'); + const resourceB = URI.file('static/app/source/angular/-admin/-project/-settings/_settings/settings.js'); + + let query = 'partisettings'; + + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + + res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); + assert.equal(res[0], resourceB); + }); + test('compareFilesByScore - prefer shorter hit (bug #20546)', function () { const resourceA = URI.file('editor/core/components/tests/list-view-spec.js'); const resourceB = URI.file('editor/core/components/list-view.js'); From 2186c66c188890f82c1653fdff80b43bae3bd4c7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 14:19:52 +0200 Subject: [PATCH 378/394] :lipstick: --- src/vs/workbench/electron-browser/main.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts index 26d262395d8..6387586a777 100644 --- a/src/vs/workbench/electron-browser/main.contribution.ts +++ b/src/vs/workbench/electron-browser/main.contribution.ts @@ -132,9 +132,9 @@ let workbenchProperties: { [path: string]: IJSONSchema; } = { 'type': 'string', 'enum': ['default', 'short', 'medium', 'long'], 'enumDescriptions': [ - nls.localize('workbench.editor.labelFormat.default', "Show the name of the file. When tabs are enabled and two files have the same name in one group the distinguinshing sections of each file's path are added. When tabs are disabled, the path relative to workspace root is shown if the editor is active."), + nls.localize('workbench.editor.labelFormat.default', "Show the name of the file. When tabs are enabled and two files have the same name in one group the distinguinshing sections of each file's path are added. When tabs are disabled, the path relative to the workspace folder is shown if the editor is active."), nls.localize('workbench.editor.labelFormat.short', "Show the name of the file followed by it's directory name."), - nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by it's path relative to the workspace root."), + nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by it's path relative to the workspace folder."), nls.localize('workbench.editor.labelFormat.long', "Show the name of the file followed by it's absolute path.") ], 'default': 'default', From 761b992cc18deb649c4bcf1192b278df8453bae7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 15:01:13 +0200 Subject: [PATCH 379/394] config change handling :lipstick: --- src/vs/platform/files/common/files.ts | 2 ++ src/vs/workbench/browser/labels.ts | 24 +++++++++++++++---- .../browser/parts/editor/editorPart.ts | 1 - .../browser/parts/editor/editorStatus.ts | 8 +++---- .../parts/quickopen/quickOpenController.ts | 10 ++++---- src/vs/workbench/browser/quickopen.ts | 5 ++-- src/vs/workbench/common/editor.ts | 2 ++ .../common/editor/editorStacksModel.ts | 14 +++++------ src/vs/workbench/electron-browser/window.ts | 8 +++++-- .../workbench/electron-browser/workbench.ts | 20 +++++++--------- .../mode/common/workbenchModeService.ts | 4 ++-- .../textfile/common/textFileService.ts | 12 ++++++---- .../textfile/test/textFileService.test.ts | 6 ++--- .../workbench/test/workbenchTestServices.ts | 4 ++-- 14 files changed, 68 insertions(+), 52 deletions(-) diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index abd11cd556a..11c8359fdd2 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -588,6 +588,8 @@ export const HotExitConfiguration = { export const CONTENT_CHANGE_EVENT_BUFFER_DELAY = 1000; +export const FILES_ASSOCIATIONS_CONFIG = 'files.associations'; + export interface IFilesConfiguration { files: { associations: { [filepattern: string]: string }; diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index bf7bf9f97d6..5d2192810e8 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -22,7 +22,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IDecorationsService, IResourceDecorationChangeEvent } from 'vs/workbench/services/decorations/browser/decorations'; import { Schemas } from 'vs/base/common/network'; -import { FileKind } from 'vs/platform/files/common/files'; +import { FileKind, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IModel } from 'vs/editor/common/editorCommon'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -64,11 +64,25 @@ export class ResourceLabel extends IconLabel { } private registerListeners(): void { - this.extensionService.onReady().then(() => this.render(true /* clear cache */)); // update when extensions are loaded with potentially new languages - this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.render(true /* clear cache */))); // update when file.associations change - this.toDispose.push(this.modelService.onModelModeChanged(e => this.onModelModeChanged(e))); // react to model mode changes - this.toDispose.push(this.decorationsService.onDidChangeDecorations(this.onFileDecorationsChanges, this)); // react to file decoration changes + + // update when extensions are loaded with potentially new languages + this.extensionService.onReady().then(() => this.render(true /* clear cache */)); + + // react to model mode changes + this.toDispose.push(this.modelService.onModelModeChanged(e => this.onModelModeChanged(e))); + + // react to file decoration changes + this.toDispose.push(this.decorationsService.onDidChangeDecorations(this.onFileDecorationsChanges, this)); + + // react to theme changes this.toDispose.push(this.themeService.onThemeChange(() => this.render(false))); + + // react to files.associations changes + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(FILES_ASSOCIATIONS_CONFIG)) { + this.render(true /* clear cache */); + } + })); } private onModelModeChanged(e: { model: IModel; oldModeId: string; }): void { diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index fead4e1c3b3..3e15e6118d3 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -218,7 +218,6 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService if (configuration && configuration.workbench && configuration.workbench.editor) { const editorConfig = configuration.workbench.editor; - // Pin all preview editors of the user chose to disable preview const newPreviewEditors = editorConfig.enablePreview; if (this.tabOptions.previewEditors !== newPreviewEditors && !newPreviewEditors) { diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index ee23ffe9df8..2ffc03718df 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -33,7 +33,7 @@ import { IEditor as IBaseEditor, IEditorInput } from 'vs/platform/editor/common/ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { SUPPORTED_ENCODINGS, IFileService, IFilesConfiguration } from 'vs/platform/files/common/files'; +import { SUPPORTED_ENCODINGS, IFileService, IFilesConfiguration, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -785,8 +785,6 @@ export class ChangeModeAction extends Action { public static ID = 'workbench.action.editor.changeLanguageMode'; public static LABEL = nls.localize('changeMode', "Change Language Mode"); - private static FILE_ASSOCIATION_KEY = 'files.associations'; - constructor( actionId: string, actionLabel: string, @@ -964,7 +962,7 @@ export class ChangeModeAction extends Action { TPromise.timeout(50 /* quick open is sensitive to being opened so soon after another */).done(() => { this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || basename) }).done(language => { if (language) { - const fileAssociationsConfig = this.configurationService.inspect(ChangeModeAction.FILE_ASSOCIATION_KEY); + const fileAssociationsConfig = this.configurationService.inspect(FILES_ASSOCIATIONS_CONFIG); let associationKey: string; if (extension && basename[0] !== '.') { @@ -987,7 +985,7 @@ export class ChangeModeAction extends Action { currentAssociations[associationKey] = language.id; - this.configurationService.updateValue(ChangeModeAction.FILE_ASSOCIATION_KEY, currentAssociations, target); + this.configurationService.updateValue(FILES_ASSOCIATIONS_CONFIG, currentAssociations, target); } }); }); diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 3a666cfbc1c..b9efab5784e 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -36,7 +36,7 @@ import { Component } from 'vs/workbench/common/component'; import Event, { Emitter } from 'vs/base/common/event'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { KeyMod } from 'vs/base/common/keyCodes'; -import { QuickOpenHandler, QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions, EditorQuickOpenEntry, IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen'; +import { QuickOpenHandler, QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions, EditorQuickOpenEntry, CLOSE_ON_FOCUS_LOST_CONFIG } from 'vs/workbench/browser/quickopen'; import errors = require('vs/base/common/errors'); import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPickOpenEntry, IFilePickOpenEntry, IInputOptions, IQuickOpenService, IPickOptions, IShowOptions, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen'; @@ -131,22 +131,22 @@ export class QuickOpenController extends Component implements IQuickOpenService this._onShow = new Emitter(); this._onHide = new Emitter(); - this.updateConfiguration(this.configurationService.getConfiguration()); + this.updateConfiguration(); this.registerListeners(); } private registerListeners(): void { - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration(this.configurationService.getConfiguration()))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.updateConfiguration())); this.toUnbind.push(this.partService.onTitleBarVisibilityChange(() => this.positionQuickOpenWidget())); this.toUnbind.push(browser.onDidChangeZoomLevel(() => this.positionQuickOpenWidget())); } - private updateConfiguration(settings: IWorkbenchQuickOpenConfiguration): void { + private updateConfiguration(): void { if (this.environmentService.args['sticky-quickopen']) { this.closeOnFocusLost = false; } else { - this.closeOnFocusLost = settings.workbench && settings.workbench.quickOpen && settings.workbench.quickOpen.closeOnFocusLost; + this.closeOnFocusLost = this.configurationService.getValue(CLOSE_ON_FOCUS_LOST_CONFIG); } } diff --git a/src/vs/workbench/browser/quickopen.ts b/src/vs/workbench/browser/quickopen.ts index 07d0289da9e..8c7cf7bea1e 100644 --- a/src/vs/workbench/browser/quickopen.ts +++ b/src/vs/workbench/browser/quickopen.ts @@ -22,11 +22,10 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IConstructorSignature0, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +export const CLOSE_ON_FOCUS_LOST_CONFIG = 'workbench.quickOpen.closeOnFocusLost'; + export interface IWorkbenchQuickOpenConfiguration { workbench: { - quickOpen: { - closeOnFocusLost: boolean; - }, commandPalette: { history: number; preserveInput: boolean; diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2df8fc14a2d..6ec676c9306 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -804,6 +804,8 @@ export const EditorOpenPositioning = { LAST: 'last' }; +export const OPEN_POSITIONING_CONFIG = 'workbench.editor.openPositioning'; + export interface IWorkbenchEditorConfiguration { /* __GDPR__FRAGMENT__ "IWorkbenchEditorConfiguration" : { diff --git a/src/vs/workbench/common/editor/editorStacksModel.ts b/src/vs/workbench/common/editor/editorStacksModel.ts index 148a01d2c41..20f09e32702 100644 --- a/src/vs/workbench/common/editor/editorStacksModel.ts +++ b/src/vs/workbench/common/editor/editorStacksModel.ts @@ -6,11 +6,11 @@ 'use strict'; import Event, { Emitter, once } from 'vs/base/common/event'; -import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IStacksModelChangeEvent, IWorkbenchEditorConfiguration, EditorOpenPositioning, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IStacksModelChangeEvent, EditorOpenPositioning, SideBySideEditorInput, OPEN_POSITIONING_CONFIG } from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -84,7 +84,7 @@ export class EditorGroup implements IEditorGroup { this.mru = []; this.toDispose = []; this.mapResourceToEditorCount = new ResourceMap(); - this.onConfigurationUpdated(configurationService.getConfiguration()); + this.onConfigurationUpdated(); this._onEditorActivated = new Emitter(); this._onEditorOpened = new Emitter(); @@ -110,13 +110,11 @@ export class EditorGroup implements IEditorGroup { } private registerListeners(): void { - this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getConfiguration()))); + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e))); } - private onConfigurationUpdated(config: IWorkbenchEditorConfiguration): void { - if (config && config.workbench && config.workbench.editor) { - this.editorOpenPositioning = config.workbench.editor.openPositioning; - } + private onConfigurationUpdated(event?: IConfigurationChangeEvent): void { + this.editorOpenPositioning = this.configurationService.getValue(OPEN_POSITIONING_CONFIG); } public get id(): GroupIdentifier { diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index aeefa814e9f..e40bc555cb2 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -46,7 +46,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; const TextInputActions: IAction[] = [ new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && TPromise.as(true)), @@ -261,7 +261,11 @@ export class ElectronWindow extends Themable { } } - private onDidUpdateConfiguration(e): void { + private onDidUpdateConfiguration(event: IConfigurationChangeEvent): void { + if (!event.affectsConfiguration('window.zoomLevel')) { + return; + } + const windowConfig: IWindowsConfiguration = this.configurationService.getConfiguration(); let newZoomLevel = 0; diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 0ca26a15f24..f2d871d7eb6 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -15,7 +15,6 @@ import DOM = require('vs/base/browser/dom'); import { Builder, $ } from 'vs/base/browser/builder'; import { Delayer, RunOnceScheduler } from 'vs/base/common/async'; import * as browser from 'vs/base/browser/browser'; -import assert = require('vs/base/common/assert'); import { StopWatch } from 'vs/base/common/stopwatch'; import { startTimer } from 'vs/base/node/startupTimers'; import errors = require('vs/base/common/errors'); @@ -267,9 +266,6 @@ export class Workbench implements IPartService { * once. Use the shutdown function to free up resources created by the workbench on startup. */ public startup(callbacks?: IWorkbenchCallbacks): void { - assert.ok(!this.workbenchStarted, 'Can not start a workbench that was already started'); - assert.ok(!this.workbenchShutdown, 'Can not start a workbench that was shutdown'); - try { this.workbenchStarted = true; this.callbacks = callbacks; @@ -1224,26 +1220,18 @@ export class Workbench implements IPartService { } public getEditorPart(): EditorPart { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.editorPart; } public getSidebarPart(): SidebarPart { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.sidebarPart; } public getPanelPart(): PanelPart { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.panelPart; } public getInstantiationService(): IInstantiationService { - assert.ok(this.workbenchStarted, 'Workbench is not started. Call startup() first.'); - return this.instantiationService; } @@ -1265,6 +1253,7 @@ export class Workbench implements IPartService { public toggleZenMode(skipLayout?: boolean): void { this.zenMode.active = !this.zenMode.active; + // Check if zen mode transitioned to full screen and if now we are out of zen mode -> we need to go out of full screen let toggleFullScreen = false; if (this.zenMode.active) { @@ -1279,9 +1268,11 @@ export class Workbench implements IPartService { if (config.hideActivityBar) { this.setActivityBarHidden(true, true); } + if (config.hideStatusBar) { this.setStatusBarHidden(true, true); } + if (config.hideTabs) { this.editorPart.hideTabs(true); } @@ -1289,9 +1280,11 @@ export class Workbench implements IPartService { if (this.zenMode.wasPanelVisible) { this.setPanelHidden(false, true).done(undefined, errors.onUnexpectedError); } + if (this.zenMode.wasSideBarVisible) { this.setSideBarHidden(false, true).done(undefined, errors.onUnexpectedError); } + // Status bar and activity bar visibility come from settings -> update their visibility. this.onDidUpdateConfiguration(true); this.editorPart.hideTabs(false); @@ -1299,13 +1292,16 @@ export class Workbench implements IPartService { if (activeEditor) { activeEditor.focus(); } + toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen(); } + this.inZenMode.set(this.zenMode.active); if (!skipLayout) { this.layout(); } + if (toggleFullScreen) { this.windowService.toggleFullScreen().done(undefined, errors.onUnexpectedError); } diff --git a/src/vs/workbench/services/mode/common/workbenchModeService.ts b/src/vs/workbench/services/mode/common/workbenchModeService.ts index ad3c007b72c..62023d035bb 100644 --- a/src/vs/workbench/services/mode/common/workbenchModeService.ts +++ b/src/vs/workbench/services/mode/common/workbenchModeService.ts @@ -9,7 +9,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; import mime = require('vs/base/common/mime'); -import { IFilesConfiguration } from 'vs/platform/files/common/files'; +import { IFilesConfiguration, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IExtensionPointUser, ExtensionMessageCollector, IExtensionPoint, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; @@ -124,7 +124,7 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { }); this._configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('files.associations')) { + if (e.affectsConfiguration(FILES_ASSOCIATIONS_CONFIG)) { this.updateMime(); } }); diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 27a19245296..21b9c241b60 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -85,7 +85,7 @@ export abstract class TextFileService implements ITextFileService { const configuration = this.configurationService.getConfiguration(); this.currentFilesAssociationConfig = configuration && configuration.files && configuration.files.associations; - this.onConfigurationChange(configuration); + this.onFilesConfigurationChange(configuration); /* __GDPR__ "autoSave" : { @@ -123,8 +123,12 @@ export abstract class TextFileService implements ITextFileService { this.lifecycleService.onWillShutdown(event => event.veto(this.beforeShutdown(event.reason))); this.lifecycleService.onShutdown(this.dispose, this); - // Configuration changes - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration()))); + // Files configuration changes + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('files')) { + this.onFilesConfigurationChange(this.configurationService.getConfiguration()); + } + })); } private beforeShutdown(reason: ShutdownReason): boolean | TPromise { @@ -316,7 +320,7 @@ export abstract class TextFileService implements ITextFileService { return this.backupFileService.discardAllWorkspaceBackups(); } - protected onConfigurationChange(configuration: IFilesConfiguration): void { + protected onFilesConfigurationChange(configuration: IFilesConfiguration): void { const wasAutoSaveEnabled = (this.getAutoSaveMode() !== AutoSaveMode.OFF); const autoSaveMode = (configuration && configuration.files && configuration.files.autoSave) || AutoSaveConfiguration.OFF; diff --git a/src/vs/workbench/services/textfile/test/textFileService.test.ts b/src/vs/workbench/services/textfile/test/textFileService.test.ts index 38b5749c179..6416edee36b 100644 --- a/src/vs/workbench/services/textfile/test/textFileService.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileService.test.ts @@ -104,7 +104,7 @@ suite('Files - TextFileService', () => { const service = accessor.textFileService; service.setConfirmResult(ConfirmResult.DONT_SAVE); - service.onConfigurationChange({ files: { hotExit: 'off' } }); + service.onFilesConfigurationChange({ files: { hotExit: 'off' } }); model.load().done(() => { model.textEditorModel.setValue('foo'); @@ -137,7 +137,7 @@ suite('Files - TextFileService', () => { const service = accessor.textFileService; service.setConfirmResult(ConfirmResult.SAVE); - service.onConfigurationChange({ files: { hotExit: 'off' } }); + service.onFilesConfigurationChange({ files: { hotExit: 'off' } }); model.load().done(() => { model.textEditorModel.setValue('foo'); @@ -377,7 +377,7 @@ suite('Files - TextFileService', () => { const service = accessor.textFileService; // Set hot exit config - service.onConfigurationChange({ files: { hotExit: setting } }); + service.onFilesConfigurationChange({ files: { hotExit: setting } }); // Set empty workspace if required if (!workspace) { accessor.contextService.setWorkspace(new Workspace('empty:1508317022751')); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index f371d3afeca..1fcdca0f09c 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -233,8 +233,8 @@ export class TestTextFileService extends TextFileService { return this.confirmResult; } - public onConfigurationChange(configuration: any): void { - super.onConfigurationChange(configuration); + public onFilesConfigurationChange(configuration: any): void { + super.onFilesConfigurationChange(configuration); } protected cleanupBackupsBeforeShutdown(): TPromise { From 03116df7b0bcf4c3025ebf3e62eea3927ac78c4b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 15:09:21 +0200 Subject: [PATCH 380/394] ResourceGlobMatcher is reacting to all configuration change events (fixes #36478) --- src/vs/platform/files/common/files.ts | 1 + src/vs/workbench/common/resources.ts | 16 ++++++++++------ .../parts/files/browser/views/explorerView.ts | 8 ++++++-- .../services/history/browser/history.ts | 12 ++++++++---- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 11c8359fdd2..543bc5045f3 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -589,6 +589,7 @@ export const HotExitConfiguration = { export const CONTENT_CHANGE_EVENT_BUFFER_DELAY = 1000; export const FILES_ASSOCIATIONS_CONFIG = 'files.associations'; +export const FILES_EXCLUDE_CONFIG = 'files.exclude'; export interface IFilesConfiguration { files: { diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 9ffaef6c14f..3a4d1381e61 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -11,8 +11,8 @@ import paths = require('vs/base/common/paths'); import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ParsedExpression, IExpression } from 'vs/base/common/glob'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob'; import { basename } from 'vs/base/common/paths'; import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -73,7 +73,7 @@ export class ResourceGlobMatcher { constructor( private globFn: (root?: URI) => IExpression, - private parseFn: (expression: IExpression) => ParsedExpression, + private shouldUpdate: (event: IConfigurationChangeEvent) => boolean, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IConfigurationService private configurationService: IConfigurationService ) { @@ -95,7 +95,11 @@ export class ResourceGlobMatcher { } private registerListeners(): void { - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.updateExcludes(true))); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => { + if (this.shouldUpdate(e)) { + this.updateExcludes(true); + } + })); this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateExcludes(true))); } @@ -108,7 +112,7 @@ export class ResourceGlobMatcher { if (!this.mapRootToExpressionConfig.has(folder.uri.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(folder.uri.toString()), rootExcludes)) { changed = true; - this.mapRootToParsedExpression.set(folder.uri.toString(), this.parseFn(rootExcludes)); + this.mapRootToParsedExpression.set(folder.uri.toString(), parse(rootExcludes)); this.mapRootToExpressionConfig.set(folder.uri.toString(), objects.clone(rootExcludes)); } }); @@ -132,7 +136,7 @@ export class ResourceGlobMatcher { if (!this.mapRootToExpressionConfig.has(ResourceGlobMatcher.NO_ROOT) || !objects.equals(this.mapRootToExpressionConfig.get(ResourceGlobMatcher.NO_ROOT), globalExcludes)) { changed = true; - this.mapRootToParsedExpression.set(ResourceGlobMatcher.NO_ROOT, this.parseFn(globalExcludes)); + this.mapRootToParsedExpression.set(ResourceGlobMatcher.NO_ROOT, parse(globalExcludes)); this.mapRootToExpressionConfig.set(ResourceGlobMatcher.NO_ROOT, objects.clone(globalExcludes)); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 06586cd00c2..4bfa0322764 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -19,7 +19,7 @@ import { memoize } from 'vs/base/common/decorators'; import { ITree } from 'vs/base/parts/tree/browser/tree'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, SortOrderConfiguration, SortOrder } from 'vs/workbench/parts/files/common/files'; -import { FileOperation, FileOperationEvent, IResolveFileOptions, FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files'; +import { FileOperation, FileOperationEvent, IResolveFileOptions, FileChangeType, FileChangesEvent, IFileService, FILES_EXCLUDE_CONFIG } from 'vs/platform/files/common/files'; import { RefreshViewExplorerAction, NewFolderAction, NewFileAction } from 'vs/workbench/parts/files/browser/fileActions'; import { FileDragAndDrop, FileFilter, FileSorter, FileController, FileRenderer, FileDataSource, FileViewletState, FileAccessibilityProvider } from 'vs/workbench/parts/files/browser/views/explorerViewer'; import { toResource } from 'vs/workbench/common/editor'; @@ -115,7 +115,11 @@ export class ExplorerView extends ViewsViewletPanel { this.filesExplorerFocusedContext = FilesExplorerFocusedContext.bindTo(contextKeyService); this.explorerFocusedContext = ExplorerFocusedContext.bindTo(contextKeyService); - this.fileEventsFilter = instantiationService.createInstance(ResourceGlobMatcher, (root: URI) => this.getFileEventsExcludes(root), (expression: glob.IExpression) => glob.parse(expression)); + this.fileEventsFilter = instantiationService.createInstance( + ResourceGlobMatcher, + (root: URI) => this.getFileEventsExcludes(root), + (event: IConfigurationChangeEvent) => event.affectsConfiguration(FILES_EXCLUDE_CONFIG) + ); } private getFileEventsExcludes(root?: URI): glob.IExpression { diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 96778df112d..0c40b27b376 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -13,7 +13,7 @@ import { IEditor as IBaseEditor, IEditorInput, ITextEditorOptions, IResourceInpu import { Extensions as EditorExtensions, EditorInput, IEditorCloseEvent, IEditorGroup, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import { FileChangesEvent, IFileService, FileChangeType } from 'vs/platform/files/common/files'; +import { FileChangesEvent, IFileService, FileChangeType, FILES_EXCLUDE_CONFIG } from 'vs/platform/files/common/files'; import { Selection } from 'vs/editor/common/core/selection'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -21,12 +21,12 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { once, debounceEvent } from 'vs/base/common/event'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IWindowsService } from 'vs/platform/windows/common/windows'; import { getCodeEditor } from 'vs/editor/common/services/codeEditorService'; import { getExcludes, ISearchConfiguration } from 'vs/platform/search/common/search'; -import { parse, IExpression } from 'vs/base/common/glob'; +import { IExpression } from 'vs/base/common/glob'; import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ResourceGlobMatcher } from 'vs/workbench/common/resources'; @@ -211,7 +211,11 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic this.recentlyClosedFiles = []; this.loaded = false; this.registry = Registry.as(Extensions.Editors); - this.resourceFilter = instantiationService.createInstance(ResourceGlobMatcher, (root: URI) => this.getExcludes(root), (expression: IExpression) => parse(expression)); + this.resourceFilter = instantiationService.createInstance( + ResourceGlobMatcher, + (root: URI) => this.getExcludes(root), + (event: IConfigurationChangeEvent) => event.affectsConfiguration(FILES_EXCLUDE_CONFIG) || event.affectsConfiguration('search.exclude') + ); this.registerListeners(); } From bd0338b04aaf81dd9bf0b710aa976628e528df10 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 23 Oct 2017 15:10:13 +0200 Subject: [PATCH 381/394] node-debug@1.18.2 --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index beb618c5195..83499a05144 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -45,7 +45,7 @@ const nodeModules = ['electron', 'original-fs'] // Build const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.18.1' }, + { name: 'ms-vscode.node-debug', version: '1.18.2' }, { name: 'ms-vscode.node-debug2', version: '1.18.3' } ]; From 1d130910234be0b2f6c0006d02b5d59873a89cd7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 15:25:20 +0200 Subject: [PATCH 382/394] fix missing NFC normalization --- .../windows/electron-browser/windowService.ts | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/vs/platform/windows/electron-browser/windowService.ts b/src/vs/platform/windows/electron-browser/windowService.ts index 0cf353eb6f2..0523a4b15b1 100644 --- a/src/vs/platform/windows/electron-browser/windowService.ts +++ b/src/vs/platform/windows/electron-browser/windowService.ts @@ -140,31 +140,37 @@ export class WindowService implements IWindowService { } showSaveDialog(options: Electron.SaveDialogOptions, callback?: (fileName: string) => void): string { + + function normalizePath(path: string): string { + if (path && isMacintosh) { + path = normalizeNFC(path); // normalize paths returned from the OS + } + + return path; + } + if (callback) { - return remote.dialog.showSaveDialog(remote.getCurrentWindow(), options, callback); + return remote.dialog.showSaveDialog(remote.getCurrentWindow(), options, path => callback(normalizePath(path))); } - let path = remote.dialog.showSaveDialog(remote.getCurrentWindow(), options); // https://github.com/electron/electron/issues/4936 - - if (path && isMacintosh) { - path = normalizeNFC(path); // normalize paths returned from the OS - } - - return path; + return normalizePath(remote.dialog.showSaveDialog(remote.getCurrentWindow(), options)); // https://github.com/electron/electron/issues/4936 } showOpenDialog(options: Electron.OpenDialogOptions, callback?: (fileNames: string[]) => void): string[] { + + function normalizePaths(paths: string[]): string[] { + if (paths && paths.length > 0 && isMacintosh) { + paths = paths.map(path => normalizeNFC(path)); // normalize paths returned from the OS + } + + return paths; + } + if (callback) { - return remote.dialog.showOpenDialog(remote.getCurrentWindow(), options, callback); + return remote.dialog.showOpenDialog(remote.getCurrentWindow(), options, paths => callback(normalizePaths(paths))); } - let paths = remote.dialog.showOpenDialog(remote.getCurrentWindow(), options); // https://github.com/electron/electron/issues/4936 - - if (paths && paths.length > 0 && isMacintosh) { - paths = paths.map(path => normalizeNFC(path)); // normalize paths returned from the OS - } - - return paths; + return normalizePaths(remote.dialog.showOpenDialog(remote.getCurrentWindow(), options)); // https://github.com/electron/electron/issues/4936 } updateTouchBar(items: ICommandAction[][]): TPromise { From 04398d1ce1cc7eca7feeebbecc94905a3a40916f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 15:31:17 +0200 Subject: [PATCH 383/394] open workspace: option click to open in new window --- src/vs/code/electron-main/menus.ts | 2 +- src/vs/code/electron-main/windows.ts | 11 ++++++----- src/vs/platform/windows/electron-main/windows.ts | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 18e32ff6fd4..69d49d836fd 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -357,7 +357,7 @@ export class CodeMenu { } const open = new MenuItem(this.likeAction('workbench.action.files.openFileFolder', { label: this.mnemonicLabel(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")), click: (menuItem, win, event) => this.windowsService.pickFileFolderAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }) })); - const openWorkspace = new MenuItem(this.likeAction('workbench.action.openWorkspace', { label: this.mnemonicLabel(nls.localize({ key: 'miOpenWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open Workspace...")), click: () => this.windowsService.openWorkspace() })); + const openWorkspace = new MenuItem(this.likeAction('workbench.action.openWorkspace', { label: this.mnemonicLabel(nls.localize({ key: 'miOpenWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open Workspace...")), click: (menuItem, win, event) => this.windowsService.openWorkspace(void 0, { forceNewWindow: this.isOptionClick(event) }) })); const openFolder = new MenuItem(this.likeAction('workbench.action.files.openFolder', { label: this.mnemonicLabel(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")), click: (menuItem, win, event) => this.windowsService.pickFolderAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }) })); let openFile: Electron.MenuItem; diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 0698760579e..436856c01d5 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -1339,8 +1339,8 @@ export class WindowsManager implements IWindowsMainService { return result; } - public openWorkspace(win?: CodeWindow): void { - this.workspacesManager.openWorkspace(win); + public openWorkspace(win?: CodeWindow, options?: { forceNewWindow?: boolean }): void { + this.workspacesManager.openWorkspace(win, options); } private onBeforeWindowUnload(e: IWindowUnloadEvent): void { @@ -1618,7 +1618,7 @@ class FileDialog { }); } - public getFileOrFolderPaths(options: IInternalNativeOpenDialogOptions, clb: (paths: string[]) => void): void { + private getFileOrFolderPaths(options: IInternalNativeOpenDialogOptions, clb: (paths: string[]) => void): void { // Ensure dialog options if (!options.dialogOptions) { @@ -1755,7 +1755,7 @@ class WorkspacesManager { }); } - public openWorkspace(window = this.windowsMainService.getLastActiveWindow()): void { + public openWorkspace(window = this.windowsMainService.getLastActiveWindow(), options?: { forceNewWindow?: boolean }): void { let defaultPath: string; if (window && window.openedWorkspace && !this.workspacesService.isUntitledWorkspace(window.openedWorkspace)) { defaultPath = dirname(window.openedWorkspace.configPath); @@ -1771,7 +1771,8 @@ class WorkspacesManager { filters: WORKSPACE_FILTER, properties: ['openFile'], defaultPath - } + }, + forceNewWindow: options && options.forceNewWindow }); } diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index ba04b4766e7..7ce06d4a2f0 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -60,7 +60,7 @@ export interface IWindowsMainService { // methods ready(initialUserEnv: IProcessEnvironment): void; reload(win: ICodeWindow, cli?: ParsedArgs): void; - openWorkspace(win?: ICodeWindow): void; + openWorkspace(win?: ICodeWindow, options?: { forceNewWindow?: boolean }): void; createAndEnterWorkspace(win: ICodeWindow, folderPaths?: string[], path?: string): TPromise; saveAndEnterWorkspace(win: ICodeWindow, path: string): TPromise; closeWorkspace(win: ICodeWindow): void; From 07cd0c39c44f58243e7ea3c9177626e61dc42713 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 23 Oct 2017 15:34:10 +0200 Subject: [PATCH 384/394] use correct namespace for registerDebugConfigurationProvider; fixes #36118 --- src/vs/vscode.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 09c84d07fc1..93ea663a0be 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6032,8 +6032,8 @@ declare module 'vscode' { /** * A debug configuration provider allows to add the initial debug configurations to a newly created launch.json - * and allows to resolve a launch configuration before it is used to start a new debug session. - * A debug configuration provider is registered via #workspace.registerDebugConfigurationProvider. + * and to resolve a launch configuration before it is used to start a new debug session. + * A debug configuration provider is registered via #debug.registerDebugConfigurationProvider. */ export interface DebugConfigurationProvider { /** From 8902bad243a29b8b02a71c7730e6c64d2a20da09 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 23 Oct 2017 16:05:10 +0200 Subject: [PATCH 385/394] don't always listen to cursor changes, #36427 --- .../electron-browser/tabCompletion.ts | 99 ++++++++++++------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts b/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts index 5784ed551bb..2a88a06104f 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { RawContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { RawContextKey, IContextKeyService, ContextKeyExpr, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ISnippetsService, Snippet } from 'vs/workbench/parts/snippets/electron-browser/snippets.contribution'; import { getNonWhitespacePrefix, SnippetSuggestion } from 'vs/workbench/parts/snippets/electron-browser/snippetsService'; @@ -20,6 +20,7 @@ import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetCon import { showSimpleSuggestions } from 'vs/editor/contrib/suggest/browser/suggest'; import { IConfigurationRegistry, Extensions as ConfigExt } from 'vs/platform/configuration/common/configurationRegistry'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @commonEditorContribution export class TabCompletionController implements editorCommon.IEditorContribution { @@ -31,44 +32,25 @@ export class TabCompletionController implements editorCommon.IEditorContribution return editor.getContribution(TabCompletionController.ID); } - private readonly _editor: editorCommon.ICommonCodeEditor; - private readonly _snippetController: SnippetController2; - private readonly _dispoables: IDisposable[] = []; + private readonly _hasSnippets: IContextKey; + private _snippets: Snippet[] = []; + private _selectionListener: IDisposable; + private _configListener: IDisposable; constructor( - editor: editorCommon.ICommonCodeEditor, + private readonly _editor: editorCommon.ICommonCodeEditor, + @ISnippetsService private readonly _snippetService: ISnippetsService, + @IConfigurationService private readonly _configurationService: IConfigurationService, @IContextKeyService contextKeyService: IContextKeyService, - @ISnippetsService snippetService: ISnippetsService ) { - this._editor = editor; - this._snippetController = SnippetController2.get(editor); - - const hasSnippets = TabCompletionController.ContextKey.bindTo(contextKeyService); - this._dispoables.push(editor.onDidChangeCursorSelection(e => { - - this._snippets.length = 0; - let selectFn: (snippet: Snippet) => boolean; - - if (e.selection.isEmpty()) { - // empty selection -> real text (no whitespace) left of cursor - const prefix = getNonWhitespacePrefix(editor.getModel(), editor.getPosition()); - selectFn = prefix && (snippet => endsWith(prefix, snippet.prefix)); - - } else if (e.selection.startLineNumber === e.selection.endLineNumber && editor.getModel().getValueLengthInRange(e.selection) <= 100) { - // actual selection -> snippet must be a full match - const selected = editor.getModel().getValueInRange(e.selection); - selectFn = snippet => selected === snippet.prefix; + this._hasSnippets = TabCompletionController.ContextKey.bindTo(contextKeyService); + this._configListener = this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('editor.tabCompletion')) { + this._update(); } - - if (selectFn) { - const model = editor.getModel(); - model.tokenizeIfCheap(e.selection.positionLineNumber); - const id = model.getLanguageIdAtPosition(e.selection.positionLineNumber, e.selection.positionColumn); - this._snippets = snippetService.getSnippetsSync(id).filter(selectFn); - } - hasSnippets.set(this._snippets.length > 0); - })); + }); + this._update(); } getId(): string { @@ -76,7 +58,51 @@ export class TabCompletionController implements editorCommon.IEditorContribution } dispose(): void { - dispose(this._dispoables); + dispose(this._configListener); + dispose(this._selectionListener); + } + + private _update(): void { + const enabled = this._configurationService.getValue('editor.tabCompletion'); + if (!enabled) { + dispose(this._selectionListener); + } else { + this._selectionListener = this._editor.onDidChangeCursorSelection(e => this._updateSnippets()); + this._updateSnippets(); + } + } + + private _updateSnippets(): void { + + let selection = this._editor.getSelection(); + let model = this._editor.getModel(); + let selectFn: (snippet: Snippet) => boolean; + + if (!selection || !model) { + // too early + this._hasSnippets.set(false); + this._snippets = undefined; + return; + } + + if (selection.isEmpty()) { + // empty selection -> real text (no whitespace) left of cursor + const prefix = getNonWhitespacePrefix(model, this._editor.getPosition()); + selectFn = prefix && (snippet => endsWith(prefix, snippet.prefix)); + + } else if (selection.startLineNumber === selection.endLineNumber && model.getValueLengthInRange(selection) <= 100) { + // actual selection -> snippet must be a full match + const selected = model.getValueInRange(selection); + selectFn = snippet => selected === snippet.prefix; + } + + if (selectFn) { + model.tokenizeIfCheap(selection.positionLineNumber); + const id = model.getLanguageIdAtPosition(selection.positionLineNumber, selection.positionColumn); + this._snippets = this._snippetService.getSnippetsSync(id).filter(selectFn); + } + + this._hasSnippets.set(this._snippets.length > 0); } performSnippetCompletions(): void { @@ -84,7 +110,7 @@ export class TabCompletionController implements editorCommon.IEditorContribution if (this._snippets.length === 1) { // one -> just insert const [snippet] = this._snippets; - this._snippetController.insert(snippet.codeSnippet, snippet.prefix.length, 0); + SnippetController2.get(this._editor).insert(snippet.codeSnippet, snippet.prefix.length, 0); } else if (this._snippets.length > 1) { // two or more -> show IntelliSense box @@ -104,8 +130,7 @@ CommonEditorRegistry.registerEditorCommand(new TabCompletionCommand({ kbExpr: ContextKeyExpr.and( EditorContextKeys.textFocus, EditorContextKeys.tabDoesNotMoveFocus, - SnippetController2.InSnippetMode.toNegated(), - ContextKeyExpr.has('config.editor.tabCompletion') + SnippetController2.InSnippetMode.toNegated() ), primary: KeyCode.Tab } From 5327840a82b7cef935b82e3c83b4b0422c62b413 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 16:17:38 +0200 Subject: [PATCH 386/394] improve touch support for editor groups (for #22523) --- .../parts/activitybar/activitybarActions.ts | 2 +- .../parts/editor/noTabsTitleControl.ts | 19 ++++++++- .../browser/parts/editor/tabsTitleControl.ts | 42 ++++++++++++++----- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index a2b0e9c3711..851a4865613 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -123,7 +123,7 @@ export class GlobalActivityActionItem extends ActivityActionItem { } }); - this.$container.on(TouchEventType.Tap, (e: MouseEvent) => { + this.$container.on(TouchEventType.Tap, (e: GestureEvent) => { DOM.EventHelper.stop(e, true); const event = new StandardMouseEvent(e); diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 2c08851ca89..0db19a83116 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -13,10 +13,12 @@ import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; import { ResourceLabel } from 'vs/workbench/browser/labels'; import { Verbosity } from 'vs/platform/editor/common/editor'; import { TAB_ACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; +import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch'; export class NoTabsTitleControl extends TitleControl { private titleContainer: HTMLElement; private editorLabel: ResourceLabel; + private titleTouchSupport: Gesture; public setContext(group: IEditorGroup): void { super.setContext(group); @@ -29,12 +31,18 @@ export class NoTabsTitleControl extends TitleControl { this.titleContainer = parent; + // Gesture Support + this.titleTouchSupport = new Gesture(this.titleContainer); + // Pin on double click this.toUnbind.push(DOM.addDisposableListener(this.titleContainer, DOM.EventType.DBLCLICK, (e: MouseEvent) => this.onTitleDoubleClick(e))); // Detect mouse click this.toUnbind.push(DOM.addDisposableListener(this.titleContainer, DOM.EventType.CLICK, (e: MouseEvent) => this.onTitleClick(e))); + // Detect touch + this.toUnbind.push(DOM.addDisposableListener(this.titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleClick(e))); + // Editor Label this.editorLabel = this.instantiationService.createInstance(ResourceLabel, this.titleContainer, void 0); this.toUnbind.push(this.editorLabel); @@ -50,6 +58,7 @@ export class NoTabsTitleControl extends TitleControl { // Context Menu this.toUnbind.push(DOM.addDisposableListener(this.titleContainer, DOM.EventType.CONTEXT_MENU, (e: Event) => this.onContextMenu({ group: this.context, editor: this.context.activeEditor }, e, this.titleContainer))); + this.toUnbind.push(DOM.addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => this.onContextMenu({ group: this.context, editor: this.context.activeEditor }, e, this.titleContainer))); } private onTitleLabelClick(e: MouseEvent): void { @@ -70,7 +79,7 @@ export class NoTabsTitleControl extends TitleControl { this.editorGroupService.pinEditor(group, group.activeEditor); } - private onTitleClick(e: MouseEvent): void { + private onTitleClick(e: MouseEvent | GestureEvent): void { if (!this.context) { return; } @@ -78,7 +87,7 @@ export class NoTabsTitleControl extends TitleControl { const group = this.context; // Close editor on middle mouse click - if (e.button === 1 /* Middle Button */) { + if (e instanceof MouseEvent && e.button === 1 /* Middle Button */) { this.closeEditorAction.run({ group, editor: group.activeEditor }).done(null, errors.onUnexpectedError); } @@ -150,4 +159,10 @@ export class NoTabsTitleControl extends TitleControl { default: return Verbosity.MEDIUM; } } + + public dispose(): void { + super.dispose(); + + this.titleTouchSupport.dispose(); + } } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index e598d3383e3..2c0f4612a48 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -17,6 +17,7 @@ import { ActionRunner, IAction } from 'vs/base/common/actions'; import { Position, IEditorInput, Verbosity, IUntitledResourceInput } from 'vs/platform/editor/common/editor'; import { IEditorGroup, toResource } from 'vs/workbench/common/editor'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch'; import { KeyCode } from 'vs/base/common/keyCodes'; import { ResourceLabel } from 'vs/workbench/browser/labels'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -503,6 +504,9 @@ export class TabsTitleControl extends TitleControl { tabContainer.setAttribute('role', 'presentation'); // cannot use role "tab" here due to https://github.com/Microsoft/vscode/issues/8659 DOM.addClass(tabContainer, 'tab'); + // Gesture Support + const gestureSupport = new Gesture(tabContainer); + // Tab Editor Label const editorLabel = this.instantiationService.createInstance(ResourceLabel, tabContainer, void 0); this.editorLabels.push(editorLabel); @@ -518,7 +522,7 @@ export class TabsTitleControl extends TitleControl { // Eventing const disposable = this.hookTabListeners(tabContainer, index); - this.tabDisposeables.push(combinedDisposable([disposable, bar, editorLabel])); + this.tabDisposeables.push(combinedDisposable([disposable, bar, editorLabel, gestureSupport])); return tabContainer; } @@ -568,15 +572,32 @@ export class TabsTitleControl extends TitleControl { private hookTabListeners(tab: HTMLElement, index: number): IDisposable { const disposables: IDisposable[] = []; - // Open on Click - disposables.push(DOM.addDisposableListener(tab, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => { + function handleClickOrTouch(e: MouseEvent | GestureEvent): void { tab.blur(); + if (e instanceof MouseEvent && e.button !== 0) { + return; // only for left mouse click + } + const { editor, position } = this.toTabContext(index); - if (e.button === 0 /* Left Button */ && !this.isTabActionBar((e.target || e.srcElement) as HTMLElement)) { + if (!this.isTabActionBar((e.target || e.srcElement) as HTMLElement)) { setTimeout(() => this.editorService.openEditor(editor, null, position).done(null, errors.onUnexpectedError)); // timeout to keep focus in editor after mouse up } - })); + } + + function showContextMenu(e: StandardKeyboardEvent | GestureEvent): void { + DOM.EventHelper.stop(e); + + const { group, editor } = this.toTabContext(index); + + this.onContextMenu({ group, editor }, e, tab); + } + + // Open on Click + disposables.push(DOM.addDisposableListener(tab, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => handleClickOrTouch(e))); + + // Open on Touch + disposables.push(DOM.addDisposableListener(tab, TouchEventType.Tap, (e: GestureEvent) => handleClickOrTouch(e))); // Close on mouse middle click disposables.push(DOM.addDisposableListener(tab, DOM.EventType.MOUSE_UP, (e: MouseEvent) => { @@ -592,14 +613,15 @@ export class TabsTitleControl extends TitleControl { disposables.push(DOM.addDisposableListener(tab, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { const event = new StandardKeyboardEvent(e); if (event.shiftKey && event.keyCode === KeyCode.F10) { - DOM.EventHelper.stop(e); - - const { group, editor } = this.toTabContext(index); - - this.onContextMenu({ group, editor }, e, tab); + showContextMenu(event); } })); + // Context menu on touch context menu gesture + disposables.push(DOM.addDisposableListener(tab, TouchEventType.Contextmenu, (e: GestureEvent) => { + showContextMenu(e); + })); + // Keyboard accessibility disposables.push(DOM.addDisposableListener(tab, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { const event = new StandardKeyboardEvent(e); From a38db8e0a5ca9b651fd0484faefb17d706400cac Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2017 16:27:44 +0200 Subject: [PATCH 387/394] fix function scope --- .../browser/parts/activitybar/activitybarActions.ts | 2 +- .../workbench/browser/parts/editor/tabsTitleControl.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 851a4865613..dcb5207ab72 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/activityaction'; import DOM = require('vs/base/browser/dom'); -import { EventType as TouchEventType } from 'vs/base/browser/touch'; +import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 2c0f4612a48..9b50b863a52 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -572,7 +572,7 @@ export class TabsTitleControl extends TitleControl { private hookTabListeners(tab: HTMLElement, index: number): IDisposable { const disposables: IDisposable[] = []; - function handleClickOrTouch(e: MouseEvent | GestureEvent): void { + const handleClickOrTouch = (e: MouseEvent | GestureEvent) => { tab.blur(); if (e instanceof MouseEvent && e.button !== 0) { @@ -583,15 +583,15 @@ export class TabsTitleControl extends TitleControl { if (!this.isTabActionBar((e.target || e.srcElement) as HTMLElement)) { setTimeout(() => this.editorService.openEditor(editor, null, position).done(null, errors.onUnexpectedError)); // timeout to keep focus in editor after mouse up } - } + }; - function showContextMenu(e: StandardKeyboardEvent | GestureEvent): void { + const showContextMenu = (e: Event) => { DOM.EventHelper.stop(e); const { group, editor } = this.toTabContext(index); this.onContextMenu({ group, editor }, e, tab); - } + }; // Open on Click disposables.push(DOM.addDisposableListener(tab, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => handleClickOrTouch(e))); @@ -613,7 +613,7 @@ export class TabsTitleControl extends TitleControl { disposables.push(DOM.addDisposableListener(tab, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { const event = new StandardKeyboardEvent(e); if (event.shiftKey && event.keyCode === KeyCode.F10) { - showContextMenu(event); + showContextMenu(e); } })); From 6c19d7f820c0eb88da37dee55535839cbd5b94d9 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Mon, 23 Oct 2017 08:04:16 -0700 Subject: [PATCH 388/394] Increase timeout for search tests --- .../services/search/test/node/search.test.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index c2ce634c8d1..acc6ae56808 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -27,9 +27,12 @@ const MULTIROOT_QUERIES: IFolderSearch[] = [ { folder: MORE_FIXTURES } ]; +const testTimeout = 5000; + suite('FileSearchEngine', () => { test('Files: *.js', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.js' @@ -48,6 +51,7 @@ suite('FileSearchEngine', () => { }); test('Files: maxResults', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, maxResults: 1 @@ -66,6 +70,7 @@ suite('FileSearchEngine', () => { }); test('Files: maxResults without Ripgrep', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, maxResults: 1, @@ -85,6 +90,7 @@ suite('FileSearchEngine', () => { }); test('Files: exists', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, includePattern: { '**/file.txt': true }, @@ -105,6 +111,7 @@ suite('FileSearchEngine', () => { }); test('Files: not exists', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, includePattern: { '**/nofile.txt': true }, @@ -125,6 +132,7 @@ suite('FileSearchEngine', () => { }); test('Files: exists without Ripgrep', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, includePattern: { '**/file.txt': true }, @@ -146,6 +154,7 @@ suite('FileSearchEngine', () => { }); test('Files: not exists without Ripgrep', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, includePattern: { '**/nofile.txt': true }, @@ -167,6 +176,7 @@ suite('FileSearchEngine', () => { }); test('Files: examples/com*', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: normalize(join('examples', 'com*'), true) @@ -185,6 +195,7 @@ suite('FileSearchEngine', () => { }); test('Files: examples (fuzzy)', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: 'xl' @@ -203,6 +214,7 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: MULTIROOT_QUERIES, filePattern: 'file' @@ -221,6 +233,7 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot with includePattern and maxResults', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: MULTIROOT_QUERIES, maxResults: 1, @@ -244,6 +257,7 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot with includePattern and exists', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: MULTIROOT_QUERIES, exists: true, @@ -268,6 +282,7 @@ suite('FileSearchEngine', () => { }); test('Files: NPE (CamelCase)', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: 'NullPE' @@ -286,6 +301,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.*', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.*' @@ -304,6 +320,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.as', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.as' @@ -322,6 +339,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.* without derived', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: 'site.*', @@ -344,6 +362,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude folder without wildcard', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.*', @@ -363,6 +382,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude folder with leading wildcard', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.*', @@ -382,6 +402,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude folder with trailing wildcard', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.*', @@ -401,6 +422,7 @@ suite('FileSearchEngine', () => { }); test('Files: *.* exclude with unicode', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '*.*', @@ -420,6 +442,7 @@ suite('FileSearchEngine', () => { }); test('Files: multiroot with exclude', function (done: () => void) { + this.timeout(testTimeout); const folderQueries: IFolderSearch[] = [ { folder: EXAMPLES_FIXTURES, @@ -453,6 +476,7 @@ suite('FileSearchEngine', () => { }); test('Files: Unicode and Spaces', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: '汉语' @@ -474,6 +498,7 @@ suite('FileSearchEngine', () => { }); test('Files: no results', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: 'nofilematch' @@ -492,6 +517,7 @@ suite('FileSearchEngine', () => { }); test('Files: absolute path to file ignores excludes', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: path.normalize(path.join(require.toUrl('./fixtures'), 'site.css')), @@ -514,6 +540,7 @@ suite('FileSearchEngine', () => { }); test('Files: relative path matched once', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: path.normalize(path.join('examples', 'company.js')) @@ -535,6 +562,7 @@ suite('FileSearchEngine', () => { }); test('Files: relative path to file ignores excludes', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, filePattern: path.normalize(path.join('examples', 'company.js')), @@ -557,6 +585,7 @@ suite('FileSearchEngine', () => { }); test('Files: Include pattern, single files', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: ROOT_FOLDER_QUERY, includePattern: { @@ -580,6 +609,7 @@ suite('FileSearchEngine', () => { }); test('Files: extraFiles only', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: [], extraFiles: [ @@ -606,6 +636,7 @@ suite('FileSearchEngine', () => { }); test('Files: extraFiles only (with include)', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: [], extraFiles: [ @@ -633,6 +664,7 @@ suite('FileSearchEngine', () => { }); test('Files: extraFiles only (with exclude)', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: [], extraFiles: [ @@ -657,6 +689,7 @@ suite('FileSearchEngine', () => { }); test('Files: no dupes in nested folders', function (done: () => void) { + this.timeout(testTimeout); let engine = new FileSearchEngine({ folderQueries: [ { folder: EXAMPLES_FIXTURES }, @@ -681,6 +714,7 @@ suite('FileSearchEngine', () => { suite('FileWalker', () => { test('Find: exclude subfolder', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -708,6 +742,7 @@ suite('FileWalker', () => { }); test('Find: folder excludes', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -734,6 +769,7 @@ suite('FileWalker', () => { }); test('Find: exclude multiple folders', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -764,6 +800,7 @@ suite('FileWalker', () => { }); test('Find: exclude folder path suffix', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -791,6 +828,7 @@ suite('FileWalker', () => { }); test('Find: exclude subfolder path suffix', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -818,6 +856,7 @@ suite('FileWalker', () => { }); test('Find: exclude folder path', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; @@ -845,6 +884,7 @@ suite('FileWalker', () => { }); test('Find: exclude combination of paths', function (done: () => void) { + this.timeout(testTimeout); if (platform.isWindows) { done(); return; From ef63dd8b3bd5f4e1bdf50d6db0761e67853954c2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 23 Oct 2017 17:14:39 +0200 Subject: [PATCH 389/394] Revert "[theming] editor.selectionForeground is not working. Fixes #36490" This reverts commit 3a3f0e41968ddd3cef6c1e4a090ca8ef8bc6b049. See #36760 --- src/vs/editor/browser/viewParts/lines/viewLine.ts | 15 +++++++-------- .../editor/browser/viewParts/lines/viewLines.ts | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 37625d0dbaf..8c5c4ff20e3 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -15,9 +15,8 @@ import { IVisibleLine } from 'vs/editor/browser/view/viewLayer'; import { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil'; import { HorizontalRange } from 'vs/editor/common/view/renderingContext'; import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; -import { ITheme } from 'vs/platform/theme/common/themeService'; +import { ThemeType, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; import { IStringBuilder } from 'vs/editor/common/core/stringBuilder'; -import { editorSelectionForeground } from 'vs/platform/theme/common/colorRegistry'; const canUseFastRenderedViewLine = (function () { if (platform.isNative) { @@ -70,7 +69,7 @@ export class DomReadingContext { } export class ViewLineOptions { - public readonly useSelectionForegroundColor: boolean; + public readonly themeType: ThemeType; public readonly renderWhitespace: 'none' | 'boundary' | 'all'; public readonly renderControlCharacters: boolean; public readonly spaceWidth: number; @@ -79,8 +78,8 @@ export class ViewLineOptions { public readonly stopRenderingLineAfter: number; public readonly fontLigatures: boolean; - constructor(config: IConfiguration, theme: ITheme) { - this.useSelectionForegroundColor = !!theme.getColor(editorSelectionForeground); + constructor(config: IConfiguration, themeType: ThemeType) { + this.themeType = themeType; this.renderWhitespace = config.editor.viewInfo.renderWhitespace; this.renderControlCharacters = config.editor.viewInfo.renderControlCharacters; this.spaceWidth = config.editor.fontInfo.spaceWidth; @@ -95,7 +94,7 @@ export class ViewLineOptions { public equals(other: ViewLineOptions): boolean { return ( - this.useSelectionForegroundColor === other.useSelectionForegroundColor + this.themeType === other.themeType && this.renderWhitespace === other.renderWhitespace && this.renderControlCharacters === other.renderControlCharacters && this.spaceWidth === other.spaceWidth @@ -151,7 +150,7 @@ export class ViewLine implements IVisibleLine { this._options = newOptions; } public onSelectionChanged(): boolean { - if (alwaysRenderInlineSelection || this._options.useSelectionForegroundColor) { + if (alwaysRenderInlineSelection || this._options.themeType === HIGH_CONTRAST) { this._isMaybeInvalid = true; return true; } @@ -170,7 +169,7 @@ export class ViewLine implements IVisibleLine { const options = this._options; const actualInlineDecorations = LineDecoration.filter(lineData.inlineDecorations, lineNumber, lineData.minColumn, lineData.maxColumn); - if (alwaysRenderInlineSelection || options.useSelectionForegroundColor) { + if (alwaysRenderInlineSelection || options.themeType === HIGH_CONTRAST) { const selections = viewportData.selections; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 9c873fa9496..14341b3c952 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -96,7 +96,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, this._isViewportWrapping = conf.editor.wrappingInfo.isViewportWrapping; this._revealHorizontalRightPadding = conf.editor.viewInfo.revealHorizontalRightPadding; this._canUseLayerHinting = conf.editor.canUseLayerHinting; - this._viewLineOptions = new ViewLineOptions(conf, this._context.theme); + this._viewLineOptions = new ViewLineOptions(conf, this._context.theme.type); PartFingerprints.write(this.domNode, PartFingerprint.ViewLines); this.domNode.setClassName('view-lines'); @@ -170,7 +170,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, private _onOptionsMaybeChanged(): boolean { const conf = this._context.configuration; - let newViewLineOptions = new ViewLineOptions(conf, this._context.theme); + let newViewLineOptions = new ViewLineOptions(conf, this._context.theme.type); if (!this._viewLineOptions.equals(newViewLineOptions)) { this._viewLineOptions = newViewLineOptions; From c59e0af0e7115881e7d40a7b36ba365a70186248 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 23 Oct 2017 18:14:23 +0200 Subject: [PATCH 390/394] improve DebugConfigurationProvider.resolveDebugConfiguration doc --- src/vs/vscode.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 93ea663a0be..ccc90b2f958 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6050,11 +6050,12 @@ declare module 'vscode' { * Resolves a [debug configuration](#DebugConfiguration) by filling in missing values or by adding/changing/removing attributes. * If more than one debug configuration provider is registered for the same type, the resolveDebugConfiguration calls are chained * in arbitrary order and the initial debug configuration is piped through the chain. + * Returning the value 'undefined' prevents the debug session from starting. * * @param folder The workspace folder from which the configuration originates from or undefined for a folderless setup. * @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve. * @param token A cancellation token. - * @return The resolved debug configuration. + * @return The resolved debug configuration or undefined. */ resolveDebugConfiguration?(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): ProviderResult; } From 7245efcdd73cee829af1717b24ad65ce5dac254b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 23 Oct 2017 11:05:53 -0700 Subject: [PATCH 391/394] Enforce a minimum terminal font size of 6 Fixes #36370 --- .../electron-browser/terminalConfigHelper.ts | 11 +++++------ .../terminalConfigHelper.test.ts | 16 +++++++--------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index 753f9d5e055..62281821b81 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -28,6 +28,8 @@ interface IFullTerminalConfiguration { const DEFAULT_LINE_HEIGHT = 1.0; +const MINIMUM_FONT_SIZE = 6; + /** * Encapsulates terminal configuration logic, the primary purpose of this file is so that platform * specific test cases can be written. @@ -99,10 +101,7 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { } } - let fontSize = this._toInteger(terminalConfig.fontSize, 0); - if (fontSize <= 0) { - fontSize = EDITOR_FONT_DEFAULTS.fontSize; - } + let fontSize = this._toInteger(terminalConfig.fontSize, MINIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize); const lineHeight = terminalConfig.lineHeight ? Math.max(terminalConfig.lineHeight, 1) : DEFAULT_LINE_HEIGHT; if (excludeDimensions) { @@ -180,10 +179,10 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { } } - private _toInteger(source: any, minimum?: number): number { + private _toInteger(source: any, minimum: number, fallback: number): number { let r = parseInt(source, 10); if (isNaN(r)) { - r = 0; + return fallback; } if (typeof minimum === 'number') { r = Math.max(minimum, r); diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts index 2fb9993bf0a..be088071437 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -78,23 +78,22 @@ suite('Workbench - TerminalConfigHelper', () => { configurationService = new MockConfigurationService({ editor: { fontFamily: 'foo', - fontSize: 1 + fontSize: 9 }, terminal: { integrated: { fontFamily: 'bar', - fontSize: 2 + fontSize: 10 } } }); configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, null, null, null); configHelper.panelContainer = fixture; - assert.equal(configHelper.getFont().fontSize, 2, 'terminal.integrated.fontSize should be selected over editor.fontSize'); + assert.equal(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize'); configurationService = new MockConfigurationService({ editor: { - fontFamily: 'foo', - fontSize: 0 + fontFamily: 'foo' }, terminal: { integrated: { @@ -105,23 +104,22 @@ suite('Workbench - TerminalConfigHelper', () => { }); configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, null, null, null); configHelper.panelContainer = fixture; - assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when editor.fontSize is 0 and terminal.integrated.fontSize not set'); + assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); configurationService = new MockConfigurationService({ editor: { fontFamily: 'foo', - fontSize: 0 }, terminal: { integrated: { fontFamily: 0, - fontSize: -10 + fontSize: null } } }); configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, null, null, null); configHelper.panelContainer = fixture; - assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when editor.fontSize is < 0 and terminal.integrated.fontSize not set'); + assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set'); }); test('TerminalConfigHelper - getFont lineHeight', function () { From 4b414da4a27225796a63ba5f9ca2d1041aa128a9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 23 Oct 2017 11:57:58 -0700 Subject: [PATCH 392/394] Uplevel xterm.js Fixes #36328 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0f5827cf0a1..f855a4d012d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -596,7 +596,7 @@ "xterm": { "version": "2.9.1", "from": "Tyriar/xterm.js#vscode-release/1.18", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#e5b11bc3ffad1b66c49e705eac924b87717e313e" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#80718295b8f73d809686741a251aa529317c1d35" }, "yauzl": { "version": "2.8.0", From 8676abb2be87ae5840ffa2f424c0c10125ff9d75 Mon Sep 17 00:00:00 2001 From: Daniel Ye Date: Mon, 23 Oct 2017 12:23:49 -0700 Subject: [PATCH 393/394] 2017-10-23. Merged in translations from Transifex. --- .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/chs/extensions/emmet/package.i18n.json | 11 +++------ .../chs/extensions/git/out/commands.i18n.json | 7 +++--- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/chs/extensions/git/package.i18n.json | 6 +++-- .../extensions/typescript/package.i18n.json | 5 ++-- .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 14 +++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 7 ++---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 11 +++++++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 4 ++-- .../electron-browser/replViewer.i18n.json | 2 +- .../browser/extensionsActions.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 5 ++-- .../browser/files.contribution.i18n.json | 6 ++++- .../files/browser/views/emptyView.i18n.json | 4 +++- .../browser/views/explorerViewer.i18n.json | 3 +++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 4 ++++ .../browser/search.contribution.i18n.json | 2 +- .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 2 ++ .../terminal.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../terminalLinkHandler.i18n.json | 2 +- .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 24 +++++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../themes/common/colorThemeSchema.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 3 ++- .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 9 ++----- i18n/cht/extensions/emmet/package.i18n.json | 10 +------- .../cht/extensions/git/out/commands.i18n.json | 4 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 1 - .../common/view/editorColorRegistry.i18n.json | 2 +- .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 1 + .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 14 +++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 ---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 3 --- .../electron-browser/replViewer.i18n.json | 3 +-- .../parts/files/browser/fileActions.i18n.json | 3 --- .../files/browser/views/emptyView.i18n.json | 2 +- .../browser/markersFileDecorations.i18n.json | 8 +++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../browser/search.contribution.i18n.json | 1 - .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 24 +++++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 11 ++++----- i18n/deu/extensions/emmet/package.i18n.json | 10 +------- .../deu/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/deu/extensions/git/package.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 1 - .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 ---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 3 --- .../electron-browser/replViewer.i18n.json | 3 +-- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 5 ++-- .../browser/files.contribution.i18n.json | 2 ++ .../files/browser/views/emptyView.i18n.json | 4 +++- .../browser/views/explorerViewer.i18n.json | 3 +++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 4 ++++ .../browser/search.contribution.i18n.json | 1 - .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 22 +++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../themes/common/colorThemeSchema.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 3 ++- .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/esn/extensions/emmet/package.i18n.json | 10 +------- .../esn/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 1 - .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 6 +---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 3 --- .../electron-browser/replViewer.i18n.json | 3 +-- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 5 ++-- .../files/browser/views/emptyView.i18n.json | 3 ++- .../browser/views/explorerViewer.i18n.json | 2 ++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 2 ++ .../browser/search.contribution.i18n.json | 2 +- .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 21 ++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/fra/extensions/emmet/package.i18n.json | 11 +++------ .../fra/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/fra/extensions/git/package.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 5 ++-- .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 7 ++---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 11 +++++++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 6 ++--- .../electron-browser/replViewer.i18n.json | 2 +- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 5 ++-- .../browser/files.contribution.i18n.json | 6 ++++- .../files/browser/views/emptyView.i18n.json | 4 +++- .../browser/views/explorerViewer.i18n.json | 3 +++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 4 ++++ .../browser/search.contribution.i18n.json | 2 +- .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 2 ++ .../terminal.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 20 ++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../themes/common/colorThemeSchema.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 3 ++- .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/hun/extensions/emmet/package.i18n.json | 11 +++------ .../hun/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/hun/extensions/git/package.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 5 ++-- .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 14 +++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 7 ++---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 11 +++++++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 6 ++--- .../electron-browser/replViewer.i18n.json | 2 +- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 5 ++-- .../browser/files.contribution.i18n.json | 6 ++++- .../files/browser/views/emptyView.i18n.json | 4 +++- .../browser/views/explorerViewer.i18n.json | 3 +++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 4 ++++ .../browser/search.contribution.i18n.json | 2 +- .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 2 ++ .../terminal.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 24 +++++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../themes/common/colorThemeSchema.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 3 ++- .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/ita/extensions/emmet/package.i18n.json | 11 +++------ .../ita/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/ita/extensions/git/package.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 5 ++-- .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 1 + .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 ---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 3 --- .../electron-browser/replViewer.i18n.json | 3 +-- .../parts/files/browser/fileActions.i18n.json | 3 --- .../files/browser/views/emptyView.i18n.json | 2 +- .../browser/markersFileDecorations.i18n.json | 8 +++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../browser/search.contribution.i18n.json | 1 - .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 20 ++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/jpn/extensions/emmet/package.i18n.json | 11 +++------ .../jpn/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/jpn/extensions/git/package.i18n.json | 8 ++++--- .../extensions/typescript/package.i18n.json | 5 ++-- .../contrib/find/browser/findWidget.i18n.json | 3 +-- .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 +--- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 11 +++++++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 6 ++--- .../electron-browser/replViewer.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 7 +++--- .../browser/files.contribution.i18n.json | 6 ++++- .../files/browser/views/emptyView.i18n.json | 4 +++- .../browser/views/explorerViewer.i18n.json | 3 +++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 4 ++++ .../browser/search.contribution.i18n.json | 2 +- .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 2 ++ .../terminal.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 20 ++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../themes/common/colorThemeSchema.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 3 ++- .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 7 ------ i18n/kor/extensions/emmet/package.i18n.json | 10 +------- .../kor/extensions/git/out/commands.i18n.json | 4 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 1 - .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 1 + .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 ---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 3 --- .../electron-browser/replViewer.i18n.json | 3 +-- .../parts/files/browser/fileActions.i18n.json | 3 --- .../files/browser/views/emptyView.i18n.json | 2 +- .../browser/markersFileDecorations.i18n.json | 8 +++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../browser/search.contribution.i18n.json | 1 - .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 20 ++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 14 +++++------ i18n/ptb/extensions/emmet/package.i18n.json | 11 +++------ .../ptb/extensions/git/out/commands.i18n.json | 5 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ i18n/ptb/extensions/git/package.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 5 ++-- .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 3 +++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 14 +++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 7 ++---- .../debug/browser/debugQuickOpen.i18n.json | 1 + .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 11 +++++++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 6 ++--- .../electron-browser/replViewer.i18n.json | 2 +- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 5 ++-- .../browser/files.contribution.i18n.json | 6 ++++- .../files/browser/views/emptyView.i18n.json | 4 +++- .../browser/views/explorerViewer.i18n.json | 3 +++ .../browser/markersFileDecorations.i18n.json | 11 +++++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../dirtydiffDecorator.i18n.json | 4 ++++ .../browser/search.contribution.i18n.json | 2 +- .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../task.contribution.i18n.json | 2 ++ .../terminal.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 21 ++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../themes/common/colorThemeSchema.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 3 ++- .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 7 ------ i18n/rus/extensions/emmet/package.i18n.json | 10 +------- .../rus/extensions/git/out/commands.i18n.json | 4 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 1 - .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 1 + .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 ---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 3 --- .../electron-browser/replViewer.i18n.json | 3 +-- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 3 --- .../files/browser/views/emptyView.i18n.json | 2 +- .../browser/markersFileDecorations.i18n.json | 8 +++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../browser/search.contribution.i18n.json | 1 - .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 22 +++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ .../out/settingsDocumentHelper.i18n.json | 7 ------ i18n/trk/extensions/emmet/package.i18n.json | 10 +------- .../trk/extensions/git/out/commands.i18n.json | 4 ++-- .../extensions/git/out/repository.i18n.json | 2 ++ .../extensions/typescript/package.i18n.json | 1 - .../contrib/find/browser/findWidget.i18n.json | 1 - .../find/common/findController.i18n.json | 6 ----- .../multicursor/common/multicursor.i18n.json | 8 ++++++- .../theme/common/colorRegistry.i18n.json | 1 - .../actions/workspaceActions.i18n.json | 2 ++ .../activitybar/activitybarPart.i18n.json | 1 - .../parts/compositebar/compositeBar.i18n.json | 8 +++++++ .../compositeBarActions.i18n.json | 13 ++++++++++ .../editor/editor.contribution.i18n.json | 3 ++- .../parts/statusbar/statusbarPart.i18n.json | 1 - .../main.contribution.i18n.json | 5 ---- .../debug/browser/debugQuickOpen.i18n.json | 2 ++ .../parts/debug/browser/debugStatus.i18n.json | 8 +++++++ .../debug/browser/debugViewlet.i18n.json | 6 +++++ .../debugConfigurationManager.i18n.json | 1 - .../electron-browser/debugService.i18n.json | 6 ++--- .../electron-browser/replViewer.i18n.json | 3 +-- .../fileActions.contribution.i18n.json | 2 +- .../parts/files/browser/fileActions.i18n.json | 3 --- .../files/browser/views/emptyView.i18n.json | 2 +- .../browser/markersFileDecorations.i18n.json | 8 +++++++ .../browser/preferencesRenderers.i18n.json | 1 - .../browser/commandsHandler.i18n.json | 1 - .../browser/search.contribution.i18n.json | 1 - .../search/browser/searchActions.i18n.json | 1 - .../snippetsService.i18n.json | 2 +- .../terminalActions.i18n.json | 1 - .../electron-browser/terminalPanel.i18n.json | 1 - .../terminalService.i18n.json | 3 +-- .../configurationExtensionPoint.i18n.json | 24 +++++++++++++++++++ .../editor/common/editorService.i18n.json | 8 +++++++ .../colorThemeStore.i18n.json | 15 ++++++++++++ .../fileIconThemeData.i18n.json | 8 +++++++ .../fileIconThemeStore.i18n.json | 15 ++++++++++++ .../workbenchThemeService.i18n.json | 16 ------------- .../node/workspaceEditingService.i18n.json | 9 +++++++ 541 files changed, 2047 insertions(+), 874 deletions(-) create mode 100644 i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json create mode 100644 i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json create mode 100644 i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/editor/common/editorService.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json diff --git a/i18n/chs/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/chs/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index f1f362da927..4b77210ee8f 100644 --- a/i18n/chs/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/chs/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "例如 myFile.txt", - "activeEditorMedium": "例如 myFolder/myFile.txt", - "activeEditorLong": "例如 /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "例如 myFolder1、myFolder2、myFolder3", - "rootPath": "例如 /Users/Development/myProject", - "folderName": "例如 myFolder", - "folderPath": "例如 /Users/Development/myFolder", + "activeEditorShort": "文件名 (例如 myFile.txt)", + "activeEditorMedium": "相对于工作区文件夹的文件路径 (例如 myFolder/myFile.txt)", + "activeEditorLong": "文件的完整路径 (例如 /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "工作区名称 (例如 myFolder 或 myWorkspace)", + "rootPath": "工作区路径 (例如 /Users/Development/myWorkspace)", + "folderName": "文件所在工作区文件夹的名称 (例如 myFolder)", + "folderPath": "文件所在工作区文件夹的路径 (例如 /Users/Development/myFolder)", "appName": "例如 VS Code", "dirty": "一个更新的指示器,指示活动编辑器是否更新", "separator": "一个条件分隔符(\"-\"),仅在左右是具有值的变量时才显示", diff --git a/i18n/chs/extensions/emmet/package.i18n.json b/i18n/chs/extensions/emmet/package.i18n.json index fe933ada874..f5fda686eff 100644 --- a/i18n/chs/extensions/emmet/package.i18n.json +++ b/i18n/chs/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "增加 10", "command.decrementNumberByTen": "减少 10", "emmetSyntaxProfiles": "为指定的语法定义配置文件或使用带有特定规则的配置文件。", - "emmetExclude": "不应展开 Emmet 缩写的语言数组。", - "emmetExtensionsPath": "含有 Emmet 配置文件和片段的文件夹路径。", - "emmetShowExpandedAbbreviation": "显示扩展的 Emmet 缩写作为建议。\n\"inMarkupAndStylesheetFilesOnly\" 选项适用于 html、haml、jade、slim、xml、xsl、css、scss、sass、less 和 stylus。\n\"always\" 选项适用于 markup/css 文件的所有部分。", - "emmetShowAbbreviationSuggestions": "显示可能的 Emmet 缩写作为建议。在风格表中或将 emmet.showExpandedAbbreviation 设置为 \"never\" 时不适用。", - "emmetIncludeLanguages": "启用使用默认不支持的语言的 Emmet 缩写。在此添加该语言与支持 Emmet 的语言之间的映射。示例: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "要用于 Emmet 代码片段的变量", - "emmetTriggerExpansionOnTab": "启用后,按 TAB 键时,将展开 Emmet 缩写。", "emmetPreferences": "用于修改 Emmet 某些操作和解析程序的行为的首选项。", "emmetPreferencesIntUnit": "整数值的默认单位", "emmetPreferencesFloatUnit": "浮点数值的默认单位", @@ -44,5 +37,7 @@ "emmetPreferencesCssBetween": "展开 CSS 缩写时在 CSS 属性之间放置的符号", "emmetPreferencesSassBetween": "在 Sass 文件中展开 CSS 缩写时在 CSS 属性之间放置的符号", "emmetPreferencesStylusBetween": "在 Stylus 文件中展开 CSS 缩写时在 CSS 属性之间放置的符号", - "emmetShowSuggestionsAsSnippets": "若为 \"true\",Emmet 建议将会显示为代码片段,根据editor.snippetSuggestions 设置进行排列。" + "emmetPreferencesFilterCommentBefore": "使用注释过滤器时,应置于匹配元素前注释的定义。", + "emmetPreferencesFilterCommentAfter": "使用注释过滤器时,应置于匹配元素后注释的定义。", + "emmetPreferencesFilterCommentTrigger": "用半角逗号 (\",\") 隔开的属性名缩写的数组,将由注释筛选器应用" } \ No newline at end of file diff --git a/i18n/chs/extensions/git/out/commands.i18n.json b/i18n/chs/extensions/git/out/commands.i18n.json index 5b826945eab..c28138c3ddb 100644 --- a/i18n/chs/extensions/git/out/commands.i18n.json +++ b/i18n/chs/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "正在克隆 GIT 存储库...", "openrepo": "打开存储库", "proposeopen": "是否要打开已克隆存储库?", - "path to init": "文件夹路径", - "provide path": "请提供用于初始化 Git 存储库的文件夹路径", + "init repo": "初始化存储库", + "create repo": "初始化存储库", + "are you sure": "将在“{0}”中创建 Git 存储库。确定要继续吗?", "HEAD not available": "“{0}”的 HEAD 版本不可用。", "confirm stage files with merge conflicts": "确定要暂存含有合并冲突的 {0} 个文件吗?", "confirm stage file with merge conflicts": "确定要暂存含有合并冲突的 {0} 吗?", @@ -60,7 +61,7 @@ "push with tags success": "已成功带标签进行推送。", "nobranch": "请签出一个分支以推送到远程。", "pick remote": "选取要将分支“{0}”发布到的远程:", - "sync is unpredictable": "此操作从“{0}”推送和拉取提交。", + "sync is unpredictable": "此操作将推送提交至“{0}”,并从中拉取提交。", "ok": "确定", "never again": "好,永不再显示", "no remotes to publish": "存储库未配置任何要发布到的远程存储库。", diff --git a/i18n/chs/extensions/git/out/repository.i18n.json b/i18n/chs/extensions/git/out/repository.i18n.json index 8b700b3abe3..130408fe060 100644 --- a/i18n/chs/extensions/git/out/repository.i18n.json +++ b/i18n/chs/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "已被我们删除", "both added": "两者均已添加", "both modified": "二者均已修改", + "untracked, short": "U", + "modified, short": "M", "commit": "提交", "merge changes": "合并更改", "staged changes": "暂存的更改", diff --git a/i18n/chs/extensions/git/package.i18n.json b/i18n/chs/extensions/git/package.i18n.json index 35849ac0289..319483d9eeb 100644 --- a/i18n/chs/extensions/git/package.i18n.json +++ b/i18n/chs/extensions/git/package.i18n.json @@ -15,6 +15,8 @@ "command.stageAll": "暂存所有更改", "command.stageSelectedRanges": "暂存所选范围", "command.revertSelectedRanges": "还原所选更改", + "command.stageChange": "暂存更改", + "command.revertChange": "还原更改", "command.unstage": "取消暂存更改", "command.unstageAll": "取消暂存所有更改", "command.unstageSelectedRanges": "取消暂存所选范围", @@ -53,11 +55,11 @@ "config.enableLongCommitWarning": "是否针对长段提交消息进行警告", "config.confirmSync": "同步 Git 存储库前进行确认", "config.countBadge": "控制 Git 徽章计数器。“all”计算所有更改。“tracked”只计算跟踪的更改。“off”关闭此功能。", - "config.checkoutType": "控制运行“签出到...”时列出的分支的类型。“all”显示所有 refs,“local”只显示本地分支,“tags”只显示标签,“remote”只显示远程分支。", + "config.checkoutType": "控制运行“签出到...”命令时列出的分支的类型。\"all\" 显示所有 refs,\"local\" 只显示本地分支,\"tags\" 只显示标记,\"remote\" 只显示远程分支。", "config.ignoreLegacyWarning": "忽略旧版 Git 警告", "config.ignoreLimitWarning": "忽略“存储库中存在大量更改”的警告", "config.defaultCloneDirectory": "克隆 Git 存储库的默认位置", "config.enableSmartCommit": "在没有暂存的更改时提交所有更改。", "config.enableCommitSigning": "启用使用 GPG 签名的提交", - "config.discardAllScope": "控制运行\"放弃所有更改\"命令时放弃的更改。\"all\" 放弃所有更改。 \"tracked\" 只放弃跟踪的文件。 \"prompt\" 每次运行此操作时显示提示对话框。" + "config.discardAllScope": "控制运行“放弃所有更改”命令时放弃的更改类型。\"all\" 放弃所有更改。\"tracked\" 只放弃跟踪的文件。\"prompt\" 表示在每次运行此操作时显示提示对话框。" } \ No newline at end of file diff --git a/i18n/chs/extensions/typescript/package.i18n.json b/i18n/chs/extensions/typescript/package.i18n.json index 03246f64123..2fcc5d4f672 100644 --- a/i18n/chs/extensions/typescript/package.i18n.json +++ b/i18n/chs/extensions/typescript/package.i18n.json @@ -44,7 +44,8 @@ "typescript.npm": "指定用于自动获取类型的 NPM 可执行文件的路径。要求 TypeScript >= 2.3.4。", "typescript.check.npmIsInstalled": "检查是否安装了 NPM 以自动获取类型。", "javascript.nameSuggestions": "启用/禁用在 JavaScript 建议列表中包含文件中的唯一名称。", - "typescript.tsc.autoDetect": "控制自动检测 tsc 任务是否打开。", + "typescript.tsc.autoDetect": "控制 tsc 任务的自动检测。\"off\" 关闭此功能。\"build\" 仅创建单次运行编译任务。\"watch\" 仅创建编译及监视任务。\"on\" 创建构建及监视任务。默认值为 \"on\"。", "typescript.problemMatchers.tsc.label": "TypeScript 问题", - "typescript.problemMatchers.tscWatch.label": "TypeScript 问题(观看模式)" + "typescript.problemMatchers.tscWatch.label": "TypeScript 问题(观看模式)", + "typescript.quickSuggestionsForPaths": "当输入导入路径时启用或禁用快速建议。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/chs/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 214239c0607..8cd6a9a0ef4 100644 --- a/i18n/chs/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "替换", "label.replaceAllButton": "全部替换", "label.toggleReplaceButton": "切换替换模式", - "title.matchesCountLimit": "仅前 999 个结果突出显示,但所有查找操作均针对整个文本。", "label.matchesLocation": "第 {0} 个(共 {1} 个)", "label.noResults": "无结果" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/chs/src/vs/editor/contrib/find/common/findController.i18n.json index 8f77be77375..385ba32bfeb 100644 --- a/i18n/chs/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "查找下一个选择", "previousSelectionMatchFindAction": "查找上一个选择", "startReplace": "替换", - "addSelectionToNextFindMatch": "将选择添加到下一个查找匹配项", - "addSelectionToPreviousFindMatch": "将选择内容添加到上一查找匹配项", - "moveSelectionToNextFindMatch": "将上次选择移动到下一个查找匹配项", - "moveSelectionToPreviousFindMatch": "将上个选择内容移动到上一查找匹配项", - "selectAllOccurrencesOfFindMatch": "选择所有找到的查找匹配项", - "changeAll.label": "更改所有匹配项", "showNextFindTermAction": "显示下一个搜索结果", "showPreviousFindTermAction": "显示上一个搜索结果" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/chs/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 88bbf6c3a12..3c402b850dd 100644 --- a/i18n/chs/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "在上面添加光标", "mutlicursor.insertBelow": "在下面添加光标", - "mutlicursor.insertAtEndOfEachLineSelected": "在行尾添加光标" + "mutlicursor.insertAtEndOfEachLineSelected": "在行尾添加光标", + "addSelectionToNextFindMatch": "将选择添加到下一个查找匹配项", + "addSelectionToPreviousFindMatch": "将选择内容添加到上一查找匹配项", + "moveSelectionToNextFindMatch": "将上次选择移动到下一个查找匹配项", + "moveSelectionToPreviousFindMatch": "将上个选择内容移动到上一查找匹配项", + "selectAllOccurrencesOfFindMatch": "选择所有找到的查找匹配项", + "changeAll.label": "更改所有匹配项" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json index 0784d4fbc11..6f4c25c20dd 100644 --- a/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "颜色格式无效。请使用 #RGB、#RGBA、#RRGGBB 或 #RRGGBBAA", "schema.colors": "工作台中使用的颜色。", "foreground": "整体前景色。此颜色仅在不被组件覆盖时适用。", "errorForeground": "错误信息的整体前景色。此颜色仅在不被组件覆盖时适用。", diff --git a/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 47a9c28f390..16082cd725c 100644 --- a/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "将文件夹添加到工作区...", "add": "添加(&&A)", "addFolderToWorkspaceTitle": "将文件夹添加到工作区", + "globalRemoveFolderFromWorkspace": "将文件夹从工作区删除…", "newWorkspace": "新建工作区...", "select": "选择(&&S)", "selectWorkspace": "选择文件夹作为工作区", "removeFolderFromWorkspace": "将文件夹从工作区删除", + "openFolderSettings": "打开文件夹设置", "saveWorkspaceAsAction": "将工作区另存为...", "save": "保存(&&S)", "saveWorkspace": "保存工作区", "openWorkspaceAction": "打开工作区...", "openWorkspaceConfigFile": "打开工作区配置文件", + "openFolderAsWorkspaceInNewWindow": "在新窗口中将文件夹作为工作区打开", "workspaceFolderPickerPlaceholder": "选择工作区文件夹" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index 9b17b8e6572..ab430ed5a0d 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "隐藏活动栏", - "activityBarAriaLabel": "活动视图切换器", "globalActions": "全局动作" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..738f1c78726 --- /dev/null +++ b/i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "活动视图切换器" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..bcd8d15ce40 --- /dev/null +++ b/i18n/chs/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "其他视图", + "numberBadge": "{0} ({1})", + "manageExtension": "管理扩展", + "titleKeybinding": "{0} ({1})", + "hide": "隐藏", + "toggle": "切换已固定的视图" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 96695e518e9..a2f0727f579 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "在第二组中显示编辑器", "groupThreePicker": "在第三组中显示编辑器", "allEditorsPicker": "显示所有已打开的编辑器", - "view": "查看" + "view": "查看", + "file": "文件" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 11e4c9243b7..fbfbe4e5483 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "命令“{0}”当前未启用,无法运行。", "manageExtension": "管理扩展" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json index b2ac4ce4c5a..dd88bf14419 100644 --- a/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,15 @@ "workspaces": "工作区", "developer": "开发者", "showEditorTabs": "控制打开的编辑器是否显示在选项卡中。", - "workbench.editor.labelFormat.default": "显示文件名。当启用选项卡且在同一组内有两个相同名称的文件时,将添加每个文件路径中可以用于区分的部分。在选项卡被禁用且编辑器活动时,将显示相对于工作区根目录的路径。", "workbench.editor.labelFormat.short": "在文件的目录名之后显示文件名。", - "workbench.editor.labelFormat.medium": "在文件相对当前工作空间根的路径之后显示文件名。", "workbench.editor.labelFormat.long": "在文件的绝对路径之后显示文件名。", "tabDescription": "控制编辑器标签的格式。修改这项设置会让文件的路径更容易理解:\n- short: \"parent\"\n- medium: \"workspace/src/parent\"\n- long: \"/home/user/workspace/src/parent\"\n- default: 当与另一选项卡标题相同时为 \".../parent\"。选项卡被禁用时则为相对工作区路径", "editorTabCloseButton": "控制编辑器的选项卡关闭按钮的位置,或当设置为 \"off\" 时禁用关闭它们。", "showIcons": "控制打开的编辑器是否随图标一起显示。这还需启用图标主题。", "enablePreview": "控制是否将打开的编辑器显示为预览。预览编辑器将会重用至其被保留(例如,通过双击或编辑),且其字体样式将为斜体。", "enablePreviewFromQuickOpen": "控制 Quick Open 中打开的编辑器是否显示为预览。预览编辑器可以重新使用,直到将其保留(例如,通过双击或编辑)。", - "editorOpenPositioning": "控制打开编辑器的位置。选择“左侧”或“右侧”以在当前活动位置的左侧或右侧打开编辑器。选择“第一个”或“最后一个”以从当前活动位置独立打开编辑器。", "revealIfOpen": "控制打开时编辑器是否显示在任何可见组中。如果禁用,编辑器会优先在当前活动编辑器组中打开。如果启用,会显示已打开的编辑器而不是在当前活动编辑器组中再次打开。请注意,有些情况下会忽略此设置,例如强制编辑器在特定组中或在当前活动组的边侧打开时。", - "commandHistory": "控制命令面板中保留最近使用命令的数量。设置为 0 则禁用命令历史记录。", + "commandHistory": "控制命令面板中保留最近使用命令的数量。设置为 0 时禁用命令历史功能。", "preserveInput": "控制是否在再次打开命令面板时恢复上一次的输入内容。", "closeOnFocusLost": "控制 Quick Open 是否应在失去焦点时自动关闭。", "openDefaultSettings": "控制打开设置时是否打开显示所有默认设置的编辑器。", @@ -50,7 +47,7 @@ "restoreWindows": "控制重启后重新打开窗口的方式。选择 \"none\" 则永远在启动时打开一个空工作区,\"one\" 则重新打开最后使用的窗口,\"folders\" 则重新打开所有含有文件夹的窗口,\"all\" 则重新打开上次会话的所有窗口。", "restoreFullscreen": "如果窗口已退出全屏模式,控制其是否应还原为全屏模式。", "zoomLevel": "调整窗口的缩放级别。原始大小是 0,每次递增(例如 1)或递减(例如 -1)表示放大或缩小 20%。也可以输入小数以便以更精细的粒度调整缩放级别。", - "title": "基于活动编辑器控制窗口标题。变量基于上下文进行替换:\n${activeEditorShort}: 例如 myFile.txt\n${activeEditorMedium}: 例如 myFolder/myFile.txt\n${activeEditorLong}: 例如 /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: 例如 myFolder\n${folderPath}: 例如 /Users/Development/myFolder\n${rootName}: 例如 myFolder1, myFolder2, myFolder3\n${rootPath}: 例如 /Users/Development/myWorkspace\n${appName}: 例如 VS Code\n${dirty}: 更新的指示器(如果活动编辑器已更新)\n${separator}: 仅在被带值的变量包围时显示的条件分隔符(\" - \")", + "title": "根据活动编辑器控制窗口标题。变量基于上下文进行替换:\n${activeEditorShort}: 文件名 (如 myFile.txt)\n${activeEditorMedium}: 相对于工作区文件夹的文件路径 (如 myFolder/myFile.txt)\n${activeEditorLong}: 文件的完整路径 (如 /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 文件所在工作区文件夹名称 (如 myFolder)\n${folderPath}: 文件所在工作区文件夹路径 (如 /Users/Development/myFolder)\n${rootName}: 工作区名称 (如 myFolder 或 myWorkspace)\n${rootPath}: 工作区路径 (如 /Users/Development/myWorkspace)\n${appName}: 如 VS Code\n${dirty}: 活动编辑器有更新时显示的更新指示器\n${separator}: 仅在被有值变量包围时显示的分隔符 (\" - \")", "window.newWindowDimensions.default": "在屏幕中心打开新窗口。", "window.newWindowDimensions.inherit": "以与上一个活动窗口相同的尺寸打开新窗口。", "window.newWindowDimensions.maximized": "打开最大化的新窗口。", diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 1b158fedfe7..6c03799a8b6 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0},调试", "debugAriaLabel": "键入启动配置的名称以运行。", + "addConfigTo": "添加配置 ({0})...", + "addConfiguration": "添加配置...", "noConfigurationsMatching": "无任何调试配置匹配", "noConfigurationsFound": "找不到任何调试配置。请创建一个 \"launch.json\" 文件。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..d8dee095caa --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "调试" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..fcbe0434d7e --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debugFocusVariablesView": "聚焦于变量视图", + "debugFocusWatchView": "聚焦于监视视图", + "debugFocusCallStackView": "聚焦于调用堆栈视图", + "debugFocusBreakpointsView": "聚焦于断点视图" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 327f1b6fd82..fd6211c4e06 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "用于生成初始 \"launch.json\" 的配置。", "vscode.extension.contributes.debuggers.languages": "可能被视为“默认调试程序”的调试扩展的语言列表。", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "如果指定的 VS Code 将调用此命令以确定调试适配器的可执行路径和要传递的参数。", - "vscode.extension.contributes.debuggers.startSessionCommand": "如果指定的 VS Code 将为针对此扩展的“调试”或“运行”操作调用此命令。", "vscode.extension.contributes.debuggers.configurationSnippets": "用于在 \"launch.json\" 中添加新配置的代码段。", "vscode.extension.contributes.debuggers.configurationAttributes": "用于验证 \"launch.json\" 的 JSON 架构配置。", "vscode.extension.contributes.debuggers.windows": "Windows 特定的设置。", diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 0a2caf6c161..8a42e364b44 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,8 +12,8 @@ "breakpointRemoved": "已删除断点,行 {0},文件 {1}", "compoundMustHaveConfigurations": "复合项必须拥有 \"configurations\" 属性集,才能启动多个配置。", "configMissing": "\"launch.json\" 中缺少配置“{0}”。", - "debugRequestNotSupported": "所选的调试配置有一个不支持的属性值“{0}”: “{1}”。", - "debugRequesMissing": "所选的调试配置缺少属性“{0}”。", + "debugRequestNotSupported": "所选调试配置的属性“{0}”的值“{1}”不受支持。", + "debugRequesMissing": "在所选的调试配置中缺少属性 '{0}' 。", "debugTypeNotSupported": "配置的类型“{0}”不受支持。", "debugTypeMissing": "所选的启动配置缺少属性 \"type\"。", "preLaunchTaskErrors": "preLaunchTask“{0}”期间检测到多个生成错误。", diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 16828d670d2..1de1dd184f1 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -8,5 +8,5 @@ "replVariableAriaLabel": "变量 {0} 具有值 {1}、读取 Eval 打印循环,调试", "replExpressionAriaLabel": "表达式 {0} 具有值 {1},读取 Eval 打印循环,调试", "replValueOutputAriaLabel": "{0},读取 Eval 打印循环,调试", - "replKeyValueOutputAriaLabel": "输出变量 {0} 具有值 {1},读取 Eval 打印循环,调试" + "replRawObjectAriaLabel": "Repl(交互式解释器)变量 {0} 具有值 {1},读取 求值 输出 循环,调试" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index e137dd70e6b..eb4a6b8039f 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -44,7 +44,7 @@ "showOutdatedExtensions": "显示过时扩展", "showPopularExtensions": "显示常用的扩展", "showRecommendedExtensions": "显示推荐的扩展", - "showWorkspaceRecommendedExtensions": "显示工作区建议的扩展名", + "showWorkspaceRecommendedExtensions": "显示根据工作区推荐的扩展", "showRecommendedKeymapExtensions": "显示推荐键映射", "showRecommendedKeymapExtensionsShort": "键映射", "showLanguageExtensions": "显示语言扩展", diff --git a/i18n/chs/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/chs/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 95ca006c03e..9e7feeb37b4 100644 --- a/i18n/chs/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "是否确实要删除“{0}”?", "undoBin": "可以从回收站还原。", "undoTrash": "可以从回收站还原。", + "doNotAskAgain": "不再询问", "confirmDeleteMessageFolder": "是否确定要永久删除“{0}”及其内容?", "confirmDeleteMessageFile": "是否确定要永久删除“{0}”?", "irreversible": "此操作不可逆!", @@ -37,8 +38,6 @@ "openToSide": "打开到侧边", "compareSource": "选择以进行比较", "globalCompareFile": "比较活动文件与...", - "pickHistory": "选择要进行比较的之前已打开的文件", - "unableToFileToCompare": "无法将所选文件与“{0}”进行比较。", "openFileToCompare": "首先打开文件以将其与另外一个文件比较。", "compareWith": "将“{0}”与“{1}”比较", "compareFiles": "比较文件", @@ -47,7 +46,7 @@ "saveAs": "另存为...", "saveAll": "全部保存", "saveAllInGroup": "保存组中的全部内容", - "saveFiles": "保存已更新文件", + "saveFiles": "保存所有文件", "revert": "还原文件", "focusOpenEditors": "专注于“打开的编辑器”视图", "focusFilesExplorer": "关注文件资源浏览器", diff --git a/i18n/chs/src/vs/workbench/parts/files/browser/files.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/files/browser/files.contribution.i18n.json index 7f0b0600897..32f442dc95c 100644 --- a/i18n/chs/src/vs/workbench/parts/files/browser/files.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/browser/files.contribution.i18n.json @@ -40,10 +40,14 @@ "dynamicHeight": "控制打开的编辑器部分的高度是否应动态适应元素数量。", "autoReveal": "控制资源管理器是否应在打开文件时自动显示并选择它们。", "enableDragAndDrop": "控制资源管理器是否应该允许通过拖放移动文件和文件夹。", + "confirmDragAndDrop": "控制资源管理器是否应在拖拽移动文件或文件夹时进行确认。", + "confirmDelete": "控制资源管理器是否应在删除文件到回收站时进行确认。", "sortOrder.default": "按名称的字母顺序排列文件和文件夹。文件夹显示在文件前。", "sortOrder.mixed": "按名称的字母顺序排列文件和文件夹。两者穿插显示。", "sortOrder.filesFirst": "按名称的字母顺序排列文件和文件夹。文件显示在文件夹前。", "sortOrder.type": "按扩展名的字母顺序排列文件和文件夹。文件夹显示在文件前。", "sortOrder.modified": "按最后修改日期降序排列文件和文件夹。文件夹显示在文件前。", - "sortOrder": "控制资源管理器文件和文件夹的排列顺序。除了默认排列顺序,你也可以设置为 \"mixed\" (文件和文件夹一起排序)、\"type\" (按文件类型排)、\"modified\" (按最后修改日期排)或是 \"filesFirst\" (将文件排在文件夹前)。" + "sortOrder": "控制资源管理器文件和文件夹的排列顺序。除了默认排列顺序,你也可以设置为 \"mixed\" (文件和文件夹一起排序)、\"type\" (按文件类型排)、\"modified\" (按最后修改日期排)或是 \"filesFirst\" (将文件排在文件夹前)。", + "explorer.decorations.colors": "控制文件修饰是否用颜色。", + "explorer.decorations.badges": "控制文件修饰是否用徽章。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/chs/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 51ca4525bf3..5939052419b 100644 --- a/i18n/chs/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,8 @@ { "noWorkspace": "无打开的文件夹", "explorerSection": "文件资源管理器部分", - "noWorkspaceHelp": "尚未打开文件夹。", + "noWorkspaceHelp": "你还没有在工作区中添加文件夹。", + "addFolder": "添加文件夹", + "noFolderHelp": "尚未打开文件夹。", "openFolder": "打开文件夹" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/chs/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index cd38244eb23..02057ebfda8 100644 --- a/i18n/chs/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "无法解析文件夹 {0}", "fileInputAriaLabel": "键入文件名。按 Enter 以确认或按 Esc 以取消。", "filesExplorerViewerAriaLabel": "{0},文件资源管理器", "dropFolders": "你是否要将文件夹添加到工作区?", "dropFolder": "你是否要将文件夹添加到工作区?", "addFolders": "添加文件夹(&&A)", "addFolder": "添加文件夹(&&A)", + "confirmMove": "是否确实要移动“{0}”?", + "doNotAskAgain": "不再询问", "confirmOverwriteMessage": "目标文件夹中已存在“{0}”。是否要将其替换?", "irreversible": "此操作不可逆!", "replaceButtonLabel": "替换(&&R)" diff --git a/i18n/chs/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..6536d821661 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "问题", + "tooltip.1": "此文件存在 1 个问题", + "tooltip.N": "此文件存在 {0} 个问题", + "markers.showOnFile": "显示关于文件与文件夹的错误与警告。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index c70f6d72be0..123be43ab7b 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "将设置放入此处以覆盖\"默认设置\"。", - "errorInvalidConfiguration": "无法写入设置。请更正文件中的错误/警告,然后重试。", "emptyWorkspaceSettingsHeader": "将设置放入此处以覆盖\"用户设置\"。", "emptyFolderSettingsHeader": "将文件夹设置放入此处以覆盖\"工作区设置\"。", "defaultFolderSettingsTitle": "默认文件夹设置", diff --git a/i18n/chs/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/chs/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index e66ea5624b1..30778096b47 100644 --- a/i18n/chs/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "在当前上下文中没有启用命令“{0}”。", "recentlyUsed": "最近使用", "morecCommands": "其他命令", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "没有匹配的命令" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index c4aae56e0d9..839def0b2a6 100644 --- a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "changes": "第 {0} 个更改 (共 {1} 个)", + "change": "第 {0} 个更改 (共 {1} 个)", + "show previous change": "显示上一个更改", + "show next change": "显示下一个更改", "editorGutterModifiedBackground": "编辑器导航线中被修改行的背景颜色。", "editorGutterAddedBackground": "编辑器导航线中已插入行的背景颜色。", "editorGutterDeletedBackground": "编辑器导航线中被删除行的背景颜色。", diff --git a/i18n/chs/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index ad7c43ade10..3fbefcc2302 100644 --- a/i18n/chs/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,7 @@ "exclude": "配置 glob 模式以在搜索中排除文件和文件夹。从 files.exclude 设置中继承所有 glob 模式。", "exclude.boolean": "匹配文件路径所依据的 glob 模式。设置为 true 或 false 可启用或禁用该模式。", "exclude.when": "对匹配文件的同级文件的其他检查。使用 $(basename) 作为匹配文件名的变量。", - "useRipgrep": "控制是否在文本搜索中使用 ripgrep", + "useRipgrep": "控制是否在文本和文件搜索中使用 ripgrep", "useIgnoreFilesByDefault": "控制在新工作区中搜索时是否默认使用 .gitignore 和 .ignore 文件。", "search.quickOpen.includeSymbols": "配置为在 Quick Open 文件结果中包括全局符号搜索的结果。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 6af8f4d7574..9b159465788 100644 --- a/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "清除搜索结果", "FocusNextSearchResult.label": "聚焦下一搜索结果", "FocusPreviousSearchResult.label": "聚焦上一搜索结果", - "RemoveAction.label": "删除", "file.replaceAll.label": "全部替换", "match.replace.label": "替换" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index d2110b961fc..9da8ac35792 100644 --- a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "添加代码段。", "vscode.extension.contributes.snippets-language": "此代码片段参与的语言标识符。", "vscode.extension.contributes.snippets-path": "代码片段文件的路径。该路径相对于扩展文件夹,通常以 \"./snippets/\" 开头。", - "badFile": "无法读取代码片段文件“{0}”。", "badVariableUse": "“{0}”代码片段很可能混淆了片段变量和片段占位符。有关详细信息,请访问 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax。", + "badFile": "无法读取代码片段文件“{0}”。", "source.snippet": "用户代码片段", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0},{1}" diff --git a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 925312c210a..9e55d0c22e6 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -14,6 +14,7 @@ "runningTasks": "显示运行中的任务", "tasks": "任务", "TaskSystem.noHotSwap": "在有活动任务运行时更换任务执行引擎需要重新加载窗口", + "TaskServer.folderIgnored": "由于使用任务版本 0.1.0,文件夹 {0} 将被忽略", "TaskService.noBuildTask1": "未定义任何生成任务。使用 \"isBuildCommand\" 在 tasks.json 文件中标记任务。", "TaskService.noBuildTask2": "未定义任何生成任务。在 tasks.json 文件中将任务标记为 \"build\" 组。", "TaskService.noTestTask1": "未定义任何测试任务。使用 \"isTestCommand\" 在 tasks.json 文件中标记任务。", @@ -30,6 +31,7 @@ "TaskSystem.activeSame.noBackground": "任务 \"{0}\" 已处于活动状态。若要终止任务,请选择“任务”菜单中的“终止任务...”。", "TaskSystem.active": "当前已有任务正在运行。请先终止它,然后再执行另一项任务。", "TaskSystem.restartFailed": "未能终止并重启任务 {0}", + "TaskService.noConfiguration": "错误: {0} 任务检测没有提供拥有下列配置的任务:\n{1}\n将忽略此任务。", "TaskSystem.configurationErrors": "错误: 提供的任务配置具有验证错误,无法使用。请首先改正错误。", "taskService.ignoreingFolder": "将忽略工作区文件夹 {0} 的任务配置。多文件夹工作区任务支持要求所有文件夹使用任务版本 2.0.0\n", "TaskSystem.invalidTaskJson": "错误: tasks.json 文件的内容具有语法错误。请先更正错误然后再执行任务。\n", diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index ab9987787d1..892b51d9473 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -17,6 +17,7 @@ "terminal.integrated.fontFamily": "控制终端的字体系列,这在编辑器中是默认的。fontFamily 的值。", "terminal.integrated.fontSize": "控制终端的字号(以像素为单位)。", "terminal.integrated.lineHeight": "控制终端的行高,此数字乘以终端字号得到实际行高(以像素表示)。", + "terminal.integrated.enableBold": "是否在终端内启用粗体文本,注意这需要终端命令行的支持。", "terminal.integrated.cursorBlinking": "控制终端光标是否闪烁。", "terminal.integrated.cursorStyle": "控制终端游标的样式。", "terminal.integrated.scrollback": "控制终端保持在缓冲区的最大行数。", diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 61a809c2168..d96d23dca0e 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "新的终端", "workbench.action.terminal.focus": "聚焦于终端", "workbench.action.terminal.focusNext": "聚焦于下一终端", - "workbench.action.terminal.focusAtIndex": "焦点终端 {0}", "workbench.action.terminal.focusPrevious": "聚焦于上一终端", "workbench.action.terminal.paste": "粘贴到活动终端中", "workbench.action.terminal.DefaultShell": "选择默认 Shell", diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json index 204cfda7f73..6c965409e92 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json @@ -6,5 +6,5 @@ { "terminalLinkHandler.followLinkAlt": "Alt + 单击以访问链接", "terminalLinkHandler.followLinkCmd": "Cmd + 单击以跟踪链接", - "terminalLinkHandler.followLinkCtrl": "Ctrl + 单击以跟踪链接" + "terminalLinkHandler.followLinkCtrl": "按住 Ctrl 并单击可访问链接" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index d3e2c12d9a6..837bb66bacc 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "复制", - "createNewTerminal": "新的终端", "paste": "粘贴", "selectAll": "全选", "clear": "清除" diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 27b7ce1e9c3..6b431f37d7f 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "好,永不再显示", "terminal.integrated.chooseWindowsShell": "选择首选的终端 shell,你可稍后在设置中进行更改", "terminalService.terminalCloseConfirmationSingular": "存在一个活动的终端会话,是否要终止此会话?", - "terminalService.terminalCloseConfirmationPlural": "存在 {0} 个活动的终端会话,是否要终止这些会话?", - "yes": "是" + "terminalService.terminalCloseConfirmationPlural": "存在 {0} 个活动的终端会话,是否要终止这些会话?" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..2eb80022de4 --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "设置摘要。此标签将在设置文件中用作分隔注释。", + "vscode.extension.contributes.configuration.properties": "配置属性的描述。", + "scope.window.description": "特定于窗口的配置,可在“用户”或“工作区”设置中配置。", + "scope.resource.description": "特定于资源的配置,可在“用户”、“工作区”或“文件夹”设置中配置。", + "scope.description": "配置适用的范围。可用范围有“窗口”和“资源”。", + "vscode.extension.contributes.configuration": "用于配置字符串。", + "invalid.title": "configuration.title 必须是字符串", + "vscode.extension.contributes.defaultConfiguration": "按语言提供默认编辑器配置设置。", + "invalid.properties": "configuration.properties 必须是对象", + "invalid.allOf": "\"configuration.allOf\" 已被弃用且不应被使用。你可以将多个配置单元作为数组传递给 \"configuration\" 参与点。", + "workspaceConfig.folders.description": "将载入到工作区的文件夹列表。", + "workspaceConfig.path.description": "文件路径。例如 \"/root/folderA\" 或 \"./folderA\"。后者表示根据工作区文件位置进行解析的相对路径。", + "workspaceConfig.name.description": "文件夹的可选名称。", + "workspaceConfig.uri.description": "文件夹的 URI", + "workspaceConfig.settings.description": "工作区设置", + "workspaceConfig.extensions.description": "工作区扩展", + "unknownWorkspaceProperty": "未知的工作区配置属性" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/chs/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/chs/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index 3006c199103..1c27ab2249d 100644 --- a/i18n/chs/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/chs/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -6,6 +6,7 @@ { "schema.token.settings": "标记的颜色和样式。", "schema.token.foreground": "标记的前景色。", + "schema.token.background.warning": "暂不支持标记背景色。", "schema.token.fontStyle": "规则字体样式:“斜体”、“粗体”和“下划线”中的一种或者组合", "schema.fontStyle.error": "字体样式必须为 \"italic\"(斜体)、 \"bold\"(粗体)和 \"underline\"(下划线)的组合。", "schema.properties.name": "规则的描述。", diff --git a/i18n/chs/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/chs/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index 182830f549e..47cfacc0457 100644 --- a/i18n/chs/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/chs/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -33,5 +33,6 @@ "schema.fontSize": "使用某种字体时: 文本字体的字体大小(以百分比表示)。如果未设置,则默认为字体定义中的大小。", "schema.fontId": "使用某种字体时: 字体的 ID。如果未设置,则默认为第一个字体定义。", "schema.light": "浅色主题中文件图标的可选关联。", - "schema.highContrast": "高对比度颜色主题中文件图标的可选关联。" + "schema.highContrast": "高对比度颜色主题中文件图标的可选关联。", + "schema.hidesExplorerArrows": "配置文件资源管理器的箭头是否应在此主题启用时隐藏。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..61d59fe560d --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "请提供 TextMate 颜色主题。", + "vscode.extension.contributes.themes.id": "用户设置中使用的图标主题的 ID。", + "vscode.extension.contributes.themes.label": "显示在 UI 中的颜色主题标签。", + "vscode.extension.contributes.themes.uiTheme": "用于定义编辑器周围颜色的基本主题: \"vs\" 是浅色主题,\"vs-dark\" 是深色主题。\"hc-black\" 是深色高对比度主题。", + "vscode.extension.contributes.themes.path": "tmTheme 文件的路径。该路径相对于扩展文件夹,通常为 \"./themes/themeFile.tmTheme\"。", + "reqarray": "扩展点“{0}”必须是一个数组。", + "reqpath": "“contributes.{0}.path”中应为字符串。提供的值: {1}", + "invalid.path.1": "“contributes.{0}.path”({1})应包含在扩展的文件夹({2})内。这可能会使扩展不可移植。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..0ccb5d7ff4d --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "分析文件图标文件时出现问题: {0}" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..239f4582a9f --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "提供文件图标主题。", + "vscode.extension.contributes.iconThemes.id": "用户设置中使用的图标主题的 ID。", + "vscode.extension.contributes.iconThemes.label": "UI 中显示的图标主题的标签。", + "vscode.extension.contributes.iconThemes.path": "图标主题定义文件的路径。该路径相对于扩展文件夹,通常是 \"./icons/awesome-icon-theme.json\"。", + "reqarray": "扩展点“{0}”必须是一个数组。", + "reqpath": "“contributes.{0}.path”中应为字符串。提供的值: {1}", + "reqid": "contributes.{0}.id\" 中的预期字符串。提供的值: {1}", + "invalid.path.1": "“contributes.{0}.path”({1})应包含在扩展的文件夹({2})内。这可能会使扩展不可移植。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index fae9207b8f3..2a7c7dc77d5 100644 --- a/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "用户设置中使用的图标主题的 ID。", - "vscode.extension.contributes.themes.label": "显示在 UI 中的颜色主题标签。", - "vscode.extension.contributes.themes.uiTheme": "用于定义编辑器周围颜色的基本主题: \"vs\" 是浅色主题,\"vs-dark\" 是深色主题。\"hc-black\" 是深色高对比度主题。", - "vscode.extension.contributes.themes.path": "tmTheme 文件的路径。该路径相对于扩展文件夹,通常为 \"./themes/themeFile.tmTheme\"。", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "用户设置中使用的图标主题的 ID。", - "vscode.extension.contributes.iconThemes.label": "UI 中显示的图标主题的标签。", - "vscode.extension.contributes.iconThemes.path": "图标主题定义文件的路径。该路径相对于扩展文件夹,通常是 \"./icons/awesome-icon-theme.json\"。", "migration.completed": "已向用户设置添加了新的主题设置。{0} 中可备份。", "error.cannotloadtheme": "无法加载 {0}: {1}", - "reqarray": "扩展点“{0}”必须是一个数组。", - "reqpath": "“contributes.{0}.path”中应为字符串。提供的值: {1}", - "invalid.path.1": "“contributes.{0}.path”({1})应包含在扩展的文件夹({2})内。这可能会使扩展不可移植。", - "reqid": "“contributes.{0}.id”中应为字符串。提供的值: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "指定工作台中使用的颜色主题。", "colorThemeError": "主题未知或未安装。", "iconTheme": "指定在工作台中使用的图标主题,或指定 \"null\" 以不显示任何文件图标。", "noIconThemeDesc": "No file icons", "iconThemeError": "文件图标主题未知或未安装。", "workbenchColors": "覆盖当前所选颜色主题的颜色。", - "workbenchColors.deprecated": "该设置不再是实验性设置,并已重命名为“workbench.colorCustomizations”", - "workbenchColors.deprecatedDescription": "改用“workbench.colorCustomizations”", "editorColors": "覆盖当前所选颜色主题中的编辑器颜色和字体样式。", "editorColors.comments": "设置注释的颜色和样式", "editorColors.strings": "设置字符串文本的颜色和样式", diff --git a/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..9db48716791 --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "打开工作区配置文件", + "close": "关闭" +} \ No newline at end of file diff --git a/i18n/cht/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/cht/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 54a0b2aaf23..885fb5847ec 100644 --- a/i18n/cht/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/cht/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "例如 myFile.txt", - "activeEditorMedium": "例如 myFolder/myFile.txt", - "activeEditorLong": "例如 /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "例如 myFolder1, , myFolder2, myFolder3", - "rootPath": "例如 /Users/Development/myProject", - "folderName": "例如 myFolder", - "folderPath": "例如 /Users/Development/myFolder", + "activeEditorShort": "檔案名稱(例如:myFile.txt)", + "activeEditorMedium": "檔案相對於工作區資料夾的相對路徑(例如:myFolder/myFile.txt)", "appName": "例如 VS Code", "dirty": "若使用中的編輯器已變更,即為已變更的指示區", "separator": "條件式分隔符號 (' - '),只會在前後為具有值的變數時顯示", diff --git a/i18n/cht/extensions/emmet/package.i18n.json b/i18n/cht/extensions/emmet/package.i18n.json index 392c4b2278a..84abd814d8a 100644 --- a/i18n/cht/extensions/emmet/package.i18n.json +++ b/i18n/cht/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "依 10 遞增", "command.decrementNumberByTen": "依 10 遞減", "emmetSyntaxProfiles": "為指定的語法定義設定檔,或透過特定規則使用自己的設定檔。", - "emmetExclude": "不應展開 Emmet 縮寫的語言陣列。", - "emmetExtensionsPath": "包含 Emmet 設定檔與程式碼片段的資料夾路徑。」", - "emmetShowExpandedAbbreviation": "顯示建議之展開的 Emmet 縮寫\n\"inMarkupAndStylesheetFilesOnly\" 選項適用於 html、haml、jade、slim、xml、xsl、css、scss、sass、less 和 stylus。\n不論標記/css 為何,該選項「一律」適用於檔案的所有部分。", - "emmetShowAbbreviationSuggestions": "顯示建議之可能的 Emmet 縮寫。但在樣式表內,或若 emmet.showExpandedAbbreviation 設為「永不」,則不適用。", - "emmetIncludeLanguages": "以預設未支援的語言啟用 Emmet 縮寫。在此新增該語言和 Emmet 支援的語言間之對應。例如: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"} ", - "emmetVariables": "要在 Emmet 程式碼片段中使用的變數", - "emmetTriggerExpansionOnTab": "如有啟用,只要按 Tab 鍵就能展開 Emmet 縮寫。", "emmetPreferences": "喜好設定,用以修改某些動作的行為及 Emmet 的解析程式。", "emmetPreferencesIntUnit": "整數值的預設單位", "emmetPreferencesFloatUnit": "浮點值的預設單位", @@ -43,6 +36,5 @@ "emmetPreferencesStylusAfter": "在手寫筆檔案中展開 CSS 縮寫時,要放在 CSS 屬性結尾的符號", "emmetPreferencesCssBetween": "展開 CSS 縮寫時,要放在 CSS 屬性與值之間的符號", "emmetPreferencesSassBetween": "在 SASS 檔案中展開 CSS 縮寫時,要放在 CSS 屬性與值之間的符號", - "emmetPreferencesStylusBetween": "在手寫筆檔案中展開 CSS 縮寫時,要放在 CSS 屬性與值之間的符號", - "emmetShowSuggestionsAsSnippets": "若為 true,則 Emmet 建議會顯示為程式碼片段,可讓您在每個 editor.snippetSuggestions 設定為其排序。" + "emmetPreferencesStylusBetween": "在手寫筆檔案中展開 CSS 縮寫時,要放在 CSS 屬性與值之間的符號" } \ No newline at end of file diff --git a/i18n/cht/extensions/git/out/commands.i18n.json b/i18n/cht/extensions/git/out/commands.i18n.json index d7ef0b15a46..6c7a6f8972a 100644 --- a/i18n/cht/extensions/git/out/commands.i18n.json +++ b/i18n/cht/extensions/git/out/commands.i18n.json @@ -12,8 +12,8 @@ "cloning": "正在複製 Git 儲存庫...", "openrepo": "開啟儲存庫", "proposeopen": "要開啟複製的儲存庫嗎?", - "path to init": "資料夾路徑", - "provide path": "請提供資料夾路徑以初始化 Git 存放庫", + "init repo": "初始化儲存庫", + "create repo": "初始化儲存庫", "HEAD not available": "'{0}' 的 HEAD 版本無法使用。", "confirm stage files with merge conflicts": "確定要暫存 {0} 個有合併衝突的檔案嗎?", "confirm stage file with merge conflicts": "確定要暫存有合併衝突的 {0} 嗎?", diff --git a/i18n/cht/extensions/git/out/repository.i18n.json b/i18n/cht/extensions/git/out/repository.i18n.json index c07485bdb63..9cbc280931f 100644 --- a/i18n/cht/extensions/git/out/repository.i18n.json +++ b/i18n/cht/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "已受到我們刪除", "both added": "皆已新增", "both modified": "皆已修改", + "untracked, short": "U", + "modified, short": "M", "commit": "認可", "merge changes": "合併變更", "staged changes": "已分段的變更", diff --git a/i18n/cht/extensions/typescript/package.i18n.json b/i18n/cht/extensions/typescript/package.i18n.json index e56e400373b..a881af4077d 100644 --- a/i18n/cht/extensions/typescript/package.i18n.json +++ b/i18n/cht/extensions/typescript/package.i18n.json @@ -44,7 +44,6 @@ "typescript.npm": "指定用於自動類型取得的 NPM 可執行檔路徑。TypeScript 必須 >= 2.3.4.", "typescript.check.npmIsInstalled": "檢查是否已安裝NPM用以取得自動類型擷取.", "javascript.nameSuggestions": "從JavaScript推薦表檔案中啟用/停用包含唯一檔名", - "typescript.tsc.autoDetect": "控制 tsc 工作的自動偵測為開啟或關閉。", "typescript.problemMatchers.tsc.label": "TypeScript 問題", "typescript.problemMatchers.tscWatch.label": " TypeScript 問題 (監看模式)" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json index 4cdf779ce91..85ff9ee951e 100644 --- a/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "目前游標位置行的反白顯示背景色彩。", "lineHighlightBorderBox": "目前游標位置行之周圍框線的背景色彩。", - "rangeHighlight": "反白顯示範圍的背景色彩,例如 Quick Open 與尋找功能。", + "rangeHighlight": "反白顯示範圍的背景色彩,例如快速開啟與尋找功能。", "caret": "編輯器游標的色彩。", "editorCursorBackground": "編輯器游標的背景色彩。允許自訂區塊游標重疊的字元色彩。", "editorWhitespaces": "編輯器中空白字元的色彩。", diff --git a/i18n/cht/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/cht/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 32ac75ef725..19132dbfd98 100644 --- a/i18n/cht/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "取代", "label.replaceAllButton": "全部取代", "label.toggleReplaceButton": "切換取代模式", - "title.matchesCountLimit": "只會將前 999 筆結果醒目提示,但所有尋找作業會在完整文字上執行。", "label.matchesLocation": "{0} / {1}", "label.noResults": "沒有結果" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/cht/src/vs/editor/contrib/find/common/findController.i18n.json index c75e923d0b7..cbbf89b710f 100644 --- a/i18n/cht/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "尋找下一個選取項目", "previousSelectionMatchFindAction": "尋找上一個選取項目", "startReplace": "取代", - "addSelectionToNextFindMatch": "將選取項目加入下一個找到的相符項", - "addSelectionToPreviousFindMatch": "將選取項目加入前一個找到的相符項中", - "moveSelectionToNextFindMatch": "將最後一個選擇項目移至下一個找到的相符項", - "moveSelectionToPreviousFindMatch": "將最後一個選擇項目移至前一個找到的相符項", - "selectAllOccurrencesOfFindMatch": "選取所有找到的相符項目", - "changeAll.label": "變更所有發生次數", "showNextFindTermAction": "顯示下一個尋找字詞", "showPreviousFindTermAction": "顯示上一個尋找字詞" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/cht/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 722b3100d2e..381e4cfcb4c 100644 --- a/i18n/cht/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "在上方加入游標", "mutlicursor.insertBelow": "在下方加入游標", - "mutlicursor.insertAtEndOfEachLineSelected": "在行尾新增游標" + "mutlicursor.insertAtEndOfEachLineSelected": "在行尾新增游標", + "addSelectionToNextFindMatch": "將選取項目加入下一個找到的相符項", + "addSelectionToPreviousFindMatch": "將選取項目加入前一個找到的相符項中", + "moveSelectionToNextFindMatch": "將最後一個選擇項目移至下一個找到的相符項", + "moveSelectionToPreviousFindMatch": "將最後一個選擇項目移至前一個找到的相符項", + "selectAllOccurrencesOfFindMatch": "選取所有找到的相符項目", + "changeAll.label": "變更所有發生次數" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json index 5f7d8743b2b..1ec0770a363 100644 --- a/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "色彩格式無效。請使用 #RGB、#RGBA、#RRGGBB 或 #RRGGBBAA", "schema.colors": "工作台中使用的色彩。", "foreground": "整體的前景色彩。僅當未被任何元件覆疊時,才會使用此色彩。", "errorForeground": "整體錯誤訊息的前景色彩。僅當未被任何元件覆蓋時,才會使用此色彩。", diff --git a/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 18a591310bd..604755744c9 100644 --- a/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -13,6 +13,7 @@ "select": "選取(&&S)", "selectWorkspace": "為工作區選取資料夾", "removeFolderFromWorkspace": "將資料夾從工作區移除", + "openFolderSettings": "開啟資料夾設定", "saveWorkspaceAsAction": "另存工作區為...", "save": "儲存(&&S)", "saveWorkspace": "儲存工作區", diff --git a/i18n/cht/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index e2c33864cd6..1ca947dd5de 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "隱藏活動列", - "activityBarAriaLabel": "即時檢視切換器", "globalActions": "全域動作" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..313c717e038 --- /dev/null +++ b/i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "即時檢視切換器" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..0ab2723d455 --- /dev/null +++ b/i18n/cht/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "其他檢視", + "numberBadge": "{0} ({1})", + "manageExtension": "管理延伸模組", + "titleKeybinding": "{0} ({1})", + "hide": "隱藏", + "toggle": "切換釘選的檢視" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 156d3f5bd02..fc25ce13ad0 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "在第二個群組顯示編輯器", "groupThreePicker": "在第三個群組顯示編輯器", "allEditorsPicker": "顯示所有開啟的編輯器", - "view": "檢視" + "view": "檢視", + "file": "檔案" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index d59f4257e4e..05f1e85eb7b 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "命令 '{0}' 目前未啟用,因此無法執行。", "manageExtension": "管理延伸模組" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json index 8b6818a6c02..af13c8df70b 100644 --- a/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,14 @@ "workspaces": "工作區", "developer": "開發人員", "showEditorTabs": "控制已開啟的編輯器是否應顯示在索引標籤中。", - "workbench.editor.labelFormat.default": "顯示檔案的名稱。當啟用索引標籤時,若在一個群組中有兩個檔案使用相同的名稱,就會新增每個檔案路徑具有辨識度的區段。當索引標籤停用時,若編輯器在使用中,則會顯示工作區根目錄的相關路徑。", "workbench.editor.labelFormat.short": "顯示檔案的名稱,並在名稱後接著該檔案的目錄名稱。", - "workbench.editor.labelFormat.medium": "顯示檔案的名稱,並在名稱後接著該檔案與工作區根目錄有關的路徑。", "workbench.editor.labelFormat.long": "顯示檔案的名稱,並在名稱後接著該檔案的絕對路徑。", "tabDescription": "控制編輯器的標籤格式。變更此設定具有多項優點,例如可讓檔案的位置更加清楚:\n-簡短: 'parent'\n-中等: 'workspace/src/parent'\n-完整: '/home/user/workspace/src/parent'\n-預設: '.../parent',當另一個索引標籤共用相同的標題,或若路徑停用,卻共用相關的工作區路徑時", "editorTabCloseButton": "控制編輯器的索引標籤關閉按鈕位置,或在設為 'off' 時將其停用。", "showIcons": "控制開啟的編輯器是否搭配圖示顯示。這需要同時啟用圖示佈景主題。", "enablePreview": "控制已開啟的編輯器是否顯示為預覽。預覽編輯器會重複使用到被保留 (例如按兩下或進行編輯) 並以斜體字型樣式顯示為止。", "enablePreviewFromQuickOpen": "控制透過 Quick Open 所開啟的編輯器是否顯示為預覽。預覽編輯器會重複使用到被保留 (例如按兩下或進行編輯) 為止。", - "editorOpenPositioning": "控制要在何處開啟編輯器。選取 [左] 或 [右] 在目前使用中編輯器的左側或右側開啟編輯器。選取 [先] 或 [後] 從目前使用中編輯器另外開啟編輯器。", "revealIfOpen": "控制編輯器是否要在任何顯示的群組開啟時,在其中顯示。若啟用此選項,已經開啟的編輯器將會繼續顯示,而不會在目前使用中的編輯器群組中再開啟一次。請注意,有一些情況會忽略此設定,例如當強制編輯器在特定群組中開啟,或強制編輯器在目前使用中的群組旁開啟等情況。", - "commandHistory": "控制是否要保留在命令選擇區歷程記錄中最近所使用的命令數目。設定為 0 以停用命令歷程記錄。", "preserveInput": "控制下次開啟命令選擇區時,最後鍵入的輸入是否應該還原。", "closeOnFocusLost": "控制是否在 Quick Open 失去焦點時自動關閉。", "openDefaultSettings": "控制開啟設定時是否也會開啟顯示所有預設設定的編輯器。", @@ -50,7 +46,6 @@ "restoreWindows": "控制重新啟動後視窗重新開啟的方式。選取 [無] 一律以空白工作區開始、選取 [一] 從上一個編輯的視窗重新開啟、選取 [資料夾] 重新開啟所有資料夾曾經開啟的視窗,或選取 [全部] 重新開啟上一個工作階段的所有視窗。", "restoreFullscreen": "控制當視窗在全螢幕模式下結束後,下次是否仍以全螢幕模式開啟。", "zoomLevel": "調整視窗的縮放比例。原始大小為 0,而且每個向上增量 (例如 1) 或向下增量 (例如 -1) 代表放大或縮小 20%。您也可以輸入小數,更細微地調整縮放比例。", - "title": "依據使用中的編輯器控制視窗標題。變數會依據內容替換:\n${activeEditorShort}: 例如 myFile.txt\n${activeEditorMedium}: 例如 myFolder/myFile.txt\n${activeEditorLong}: 例如 /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: 例如 myFolder\n${folderPath}: 例如 /Users/Development/myFolder\n${rootName}: 例如 myFolder1,myFolder2,myFolder3\n${rootPath}: 例如 /Users/Development/myWorkspace\n${appName}: 例如 VS Code\n${dirty}: 用以指出編輯器經過變更的指標\n${separator}: 條件式分隔符號 (' - '),只會在前後為具有值的變數時顯示", "window.newWindowDimensions.default": "在螢幕中央開啟新視窗。", "window.newWindowDimensions.inherit": "以相同於上一個使用中之視窗的維度開啟新視窗。", "window.newWindowDimensions.maximized": "開啟並最大化新視窗。", diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index b6a825d8df7..86768e58c63 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0},偵錯", "debugAriaLabel": "輸入要執行之啟動組態的名稱。", + "addConfigTo": "新增組態 ({0})...", + "addConfiguration": "新增組態...", "noConfigurationsMatching": "沒有任何相符的偵錯組態", "noConfigurationsFound": "找不到任何偵錯組態。請建立'launch.json' 檔案。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..24c491ad8e0 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "偵錯" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index d0e90daa9e8..19f502a82ef 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "組態,用於產生初始 'launch.json'。", "vscode.extension.contributes.debuggers.languages": "可將偵錯延伸模組視為「預設偵錯工具」的語言清單。", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "如有指定,VS Code 會呼叫此命令以決定偵錯配接器的可執行檔路徑及要傳遞的引數。", - "vscode.extension.contributes.debuggers.startSessionCommand": "如有指定,VS Code 會為以此延伸模組為目標的「偵錯」或「執行」動作呼叫此命令。", "vscode.extension.contributes.debuggers.configurationSnippets": "用於在 'launch.json' 中新增組態的程式碼片段。", "vscode.extension.contributes.debuggers.configurationAttributes": "JSON 結構描述組態,用於驗證 'launch.json'。", "vscode.extension.contributes.debuggers.windows": "Windows 特定設定。", diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 4bdc5fb94f2..c949e5dbf8b 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,7 @@ "breakpointRemoved": "已移除中斷點,行 {0},檔案 {1}", "compoundMustHaveConfigurations": "複合必須設有 \"configurations\" 屬性,才能啟動多個組態。", "configMissing": "'launch.json' 中遺漏組態 '{0}'。", - "debugRequestNotSupported": "所選的偵錯組態具有不支援的屬性值 '{0}': '{1}'。", - "debugRequesMissing": "所選的偵錯組態遺漏屬性 '{0}'。", "debugTypeNotSupported": "不支援設定的偵錯類型 '{0}'。", - "debugTypeMissing": "遺漏所選啟動設定的屬性 'type'。", "preLaunchTaskErrors": "執行 preLaunchTask '{0}' 期間偵測到建置錯誤。", "preLaunchTaskError": "執行 preLaunchTask '{0}' 期間偵測到建置錯誤。", "preLaunchTaskExitCode": "preLaunchTask '{0}' 已終止,結束代碼為 {1}。", diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index e7982d93dfd..39f259be4a4 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "第一次評估會擷取物件狀態", "replVariableAriaLabel": "變數 {0} 具有值 {1},「讀取、求值、輸出」迴圈,偵錯", "replExpressionAriaLabel": "運算式 {0} 具有值 {1},「讀取、求值、輸出」迴圈,偵錯", - "replValueOutputAriaLabel": "{0},「讀取、求值、輸出」迴圈,偵錯", - "replKeyValueOutputAriaLabel": "輸出變數 {0} 具有值 {1},「讀取、求值、輸出」迴圈,偵錯" + "replValueOutputAriaLabel": "{0},「讀取、求值、輸出」迴圈,偵錯" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/cht/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 0ce10edb281..141887ab75f 100644 --- a/i18n/cht/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -37,8 +37,6 @@ "openToSide": "開至側邊", "compareSource": "選取用以比較", "globalCompareFile": "使用中檔案的比較對象...", - "pickHistory": "選取先前開啟的檔案以相比較", - "unableToFileToCompare": "選取的檔案無法與 '{0}' 進行比較。", "openFileToCompare": "先開啟檔案以與其他檔案進行比較", "compareWith": "比較 '{0}' 與 '{1}'", "compareFiles": "比較檔案", @@ -47,7 +45,6 @@ "saveAs": "另存新檔...", "saveAll": "全部儲存", "saveAllInGroup": "全部儲存在群組中", - "saveFiles": "儲存已變更的檔案", "revert": "還原檔案", "focusOpenEditors": "聚焦在 [開放式編輯器] 檢視", "focusFilesExplorer": "將焦點設在檔案總管上", diff --git a/i18n/cht/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/cht/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 22aa2fcc887..19ea692c744 100644 --- a/i18n/cht/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,6 @@ { "noWorkspace": "沒有開啟的資料夾", "explorerSection": "檔案總管區段", - "noWorkspaceHelp": "您尚未開啟資料夾。", + "noFolderHelp": "您尚未開啟資料夾。", "openFolder": "開啟資料夾" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..79cb63cbd79 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "問題" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 12df0eb0474..fdeeb3c2a27 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "將您的設定放置在此以覆寫預設設定。", - "errorInvalidConfiguration": "無法寫入設定.請開啟使用者設定並修正檔案中的錯誤/警告後再試一次.", "emptyWorkspaceSettingsHeader": "將您的設定放置在此以覆寫使用者設定。", "emptyFolderSettingsHeader": "將您的資料夾設定放置在此以覆寫工作區設定的資料夾設定。", "defaultFolderSettingsTitle": "預設資料夾設定", diff --git a/i18n/cht/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/cht/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 6b7c584d6f2..510d9ec3ad3 100644 --- a/i18n/cht/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "目前內容中未啟用命令 '{0}'。", "recentlyUsed": "最近使用的", "morecCommands": "其他命令", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "沒有相符的命令" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index 533ad58e7aa..5bd2e68d516 100644 --- a/i18n/cht/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,6 @@ "exclude": "設定 Glob 模式,以排除不要搜尋的檔案及資料夾。請從 file.exclude 設定繼承所有的 Glob 模式。", "exclude.boolean": "要符合檔案路徑的 Glob 模式。設為 True 或 False 可啟用或停用模式。", "exclude.when": "在相符檔案同層級上額外的檢查。請使用 $(basename) 作為相符檔案名稱的變數。", - "useRipgrep": "控制是否要在文字搜尋中使用 ripgrep", "useIgnoreFilesByDefault": "控制在搜尋新的工作區時,是否要根據預設使用 .gitignore 及 .ignore 檔案。", "search.quickOpen.includeSymbols": "設定以將全域符號搜尋的結果納入 Quick Open 的檔案結果中。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 52826c8f8d8..c638d855adf 100644 --- a/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "清除搜尋結果", "FocusNextSearchResult.label": "聚焦於下一個搜尋結果", "FocusPreviousSearchResult.label": "聚焦於上一個搜尋結果", - "RemoveAction.label": "移除", "file.replaceAll.label": "全部取代", "match.replace.label": "取代" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 8f1cdc4c641..a7b095ad28a 100644 --- a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "提供程式碼片段。", "vscode.extension.contributes.snippets-language": "要予以提供此程式碼片段的語言識別碼。", "vscode.extension.contributes.snippets-path": "程式碼片段檔案的路徑。此路徑是擴充功能資料夾的相對路徑,而且一般會以 './snippets/' 開頭。", - "badFile": "無法讀取程式碼片段檔案 \"{0}\"。", "badVariableUse": "程式碼片段 \"{0}\" 很可能會混淆 snippet-variables 及 snippet-placeholders。如需詳細資料,請參閱 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax。", + "badFile": "無法讀取程式碼片段檔案 \"{0}\"。", "source.snippet": "使用者程式碼片段", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0},{1}" diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index db8c0bb2809..40342458179 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "新增終端機", "workbench.action.terminal.focus": "聚焦終端機", "workbench.action.terminal.focusNext": "聚焦下一個終端機", - "workbench.action.terminal.focusAtIndex": "聚焦終端機 {0}", "workbench.action.terminal.focusPrevious": "聚焦上一個終端機", "workbench.action.terminal.paste": "貼入使用中的終端機", "workbench.action.terminal.DefaultShell": "選取預設殼層", diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index f9f8c2b8d9e..4c35ec5d698 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "複製", - "createNewTerminal": "新增終端機", "paste": "貼上", "selectAll": "全選", "clear": "清除" diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 19e71491bf0..fc6b0624a08 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "確定,不要再顯示", "terminal.integrated.chooseWindowsShell": "請選取所需的終端機殼層。您之後可以在設定中變更此選擇", "terminalService.terminalCloseConfirmationSingular": "仍有一個使用中的終端機工作階段。要予以終止嗎?", - "terminalService.terminalCloseConfirmationPlural": "目前共有 {0} 個使用中的終端機工作階段。要予以終止嗎?", - "yes": "是" + "terminalService.terminalCloseConfirmationPlural": "目前共有 {0} 個使用中的終端機工作階段。要予以終止嗎?" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..2bc73e75628 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "設定的摘要。此標籤將會在設定檔中作為分隔註解使用。", + "vscode.extension.contributes.configuration.properties": "組態屬性的描述。", + "scope.window.description": "視窗特定組態,可在使用者或工作區設定中予以設定。", + "scope.resource.description": "資源特定設定,可在使用者、工作區或資料夾設定中予以設定。", + "scope.description": "組態適用的範圍。可用的範圍為「視窗」和「資源」。", + "vscode.extension.contributes.configuration": "提供組態設定。", + "invalid.title": "'configuration.title' 必須是字串", + "vscode.extension.contributes.defaultConfiguration": "依語言貢獻預設編輯器組態設定。", + "invalid.properties": "'configuration.properties' 必須是物件", + "invalid.allOf": "'configuration.allOf' 已取代而不應再使用。請改為將多個組態區段作為陣列,傳遞至「組態」貢獻點。", + "workspaceConfig.folders.description": "要載入工作區之資料夾的清單。", + "workspaceConfig.path.description": "檔案路徑,例如 `/root/folderA` 或 `./folderA` 即為會對工作區檔案位置解析的相關路徑。", + "workspaceConfig.name.description": "資料夾的選用名稱。", + "workspaceConfig.uri.description": "資料夾的 URI", + "workspaceConfig.settings.description": "工作區設定", + "workspaceConfig.extensions.description": "工作區延伸模組", + "unknownWorkspaceProperty": "未知的工作區組態屬性" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/cht/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/cht/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..f1b7981878d --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "提供 Textmate 彩色佈景主題。", + "vscode.extension.contributes.themes.id": "用在使用者設定中的圖示佈景主題識別碼。", + "vscode.extension.contributes.themes.label": "如 UI 中所示的彩色佈景主題標籤。", + "vscode.extension.contributes.themes.uiTheme": "基底佈景主題定義編輯器的色彩: 'vs' 是淺色佈景主題,'vs-dark' 是深色佈景主題。'hc-black' 是深色高對比佈景主題。", + "vscode.extension.contributes.themes.path": "tmTheme 檔案的路徑。此路徑是擴充功能資料夾的相對路徑,通常為 './themes/themeFile.tmTheme'。", + "reqarray": "擴充點 '{0}' 必須是陣列。", + "reqpath": "'contributes.{0}.path' 中應有字串。提供的值: {1}", + "invalid.path.1": "擴充功能資料夾 ({2}) 應包含 'contributes.{0}.path' ({1})。這可能會導致擴充功能無法移植。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..e7493947e49 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "剖析檔案的圖示檔時發生問題: {0}" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..dd6a68fb722 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "貢獻檔案圖示佈景主題。", + "vscode.extension.contributes.iconThemes.id": "用在使用者設定中的圖示佈景主題識別碼。", + "vscode.extension.contributes.iconThemes.label": "以 UI 顯示的圖示佈景主題標籤。", + "vscode.extension.contributes.iconThemes.path": "圖示佈景主題定義檔案。路徑相對於擴充功能資料夾,通常為 './icons/awesome-icon-theme.json'。", + "reqarray": "擴充點 '{0}' 必須是陣列。", + "reqpath": "'contributes.{0}.path' 中應有字串。提供的值: {1}", + "reqid": "`contributes.{0}.id` 中應有字串。提供的值: {1}", + "invalid.path.1": "擴充功能資料夾 ({2}) 應包含 'contributes.{0}.path' ({1})。這可能會導致擴充功能無法移植。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 34021b15c0a..5ab16a62ce2 100644 --- a/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "用在使用者設定中的圖示佈景主題識別碼。", - "vscode.extension.contributes.themes.label": "如 UI 中所示的彩色佈景主題標籤。", - "vscode.extension.contributes.themes.uiTheme": "基底佈景主題定義編輯器的色彩: 'vs' 是淺色佈景主題,'vs-dark' 是深色佈景主題。'hc-black' 是深色高對比佈景主題。", - "vscode.extension.contributes.themes.path": "tmTheme 檔案的路徑。此路徑是擴充功能資料夾的相對路徑,通常為 './themes/themeFile.tmTheme'。", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "用在使用者設定中的圖示佈景主題識別碼。", - "vscode.extension.contributes.iconThemes.label": "以 UI 顯示的圖示佈景主題標籤。", - "vscode.extension.contributes.iconThemes.path": "圖示佈景主題定義檔案。路徑相對於擴充功能資料夾,通常為 './icons/awesome-icon-theme.json'。", "migration.completed": "已將新的佈景主題設定新增到使用者設定。備份位於 {0}。", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "`contributes.{0}.path` 中的預期字串。提供的值: {1}", - "invalid.path.1": "要包含在擴充功能資料夾 ({2}) 中的預期 `contributes.{0}.path` ({1})。這可能會使擴充功能無法移植。", - "reqid": "`contributes.{0}.id` 中的預期字串。提供的值: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "指定在工作台中使用的圖示主題,或設定為 'null' 不顯示任何檔案圖示。", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "依目前選擇的彩色佈景主題覆寫顏色", - "workbenchColors.deprecated": "此設定不再為實驗性,且已被重新命名為 'workbench.colorCustomizations'", - "workbenchColors.deprecatedDescription": "改用'workbench.colorCustomizations'", "editorColors": "依目前選取的色彩佈景主題覆寫編輯器色彩與字型樣式。", "editorColors.comments": "設定註解的色彩與樣式", "editorColors.strings": "設定字串常值的色彩與樣式。", diff --git a/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..e3d8abe8ffe --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "開啟工作區組態檔", + "close": "關閉" +} \ No newline at end of file diff --git a/i18n/deu/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/deu/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 7dc4d240d04..b68dd3a3b2a 100644 --- a/i18n/deu/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/deu/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "z. B. myFile.txt", - "activeEditorMedium": "e.g. myFolder/myFile.txt", - "activeEditorLong": "e.g. /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "z. B. meinOrdner1, meinOrdner2, meinOrdner3", - "rootPath": "z. B. /Users/Development/myProject", - "folderName": "z. B. meinOrdner", - "folderPath": "z. B. /Users/Development/meinOrdner", + "activeEditorShort": "Der Dateiname (z.B. meineDatei.txt)", + "activeEditorLong": "Der vollständige Pfad der Datei (z.B. /Benutzer/Entwicklung/meinProjekt/meinOrdner/meineDatei.txt)", + "rootName": "Name des Arbeitsbereichs (z.B. meinOrdner oder meinArbeitsberech)", + "rootPath": "Dateipfad des Arbeitsbereichs (z.B. /Benutzer/Entwicklung/meinArbeitsbereich)", "appName": "z. B. VS Code", "dirty": "Ein geänderter Indikator, wenn der aktive Editor geändert wurde", "separator": "Ein bedingtes Trennzeichen (' - '), das nur in der Umgebung von Variablen mit Werten angezeigt wird", diff --git a/i18n/deu/extensions/emmet/package.i18n.json b/i18n/deu/extensions/emmet/package.i18n.json index aef483c7df2..7c71a6c1109 100644 --- a/i18n/deu/extensions/emmet/package.i18n.json +++ b/i18n/deu/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Um 10 erhöhen", "command.decrementNumberByTen": "Um 10 verringern", "emmetSyntaxProfiles": "Definieren Sie das Profil für die angegebene Syntax, oder verwenden Sie Ihr eigenes Profil mit bestimmten Regeln.", - "emmetExclude": "Ein Array von Sprachen, in dem Emmet-Abkürzungen nicht erweitert werden sollen.", - "emmetExtensionsPath": "Pfad zu einem Ordner mit Emmet-Profilen und Ausschnitten.", - "emmetShowExpandedAbbreviation": "Zeigt erweiterte Emmet-Abkürzungen als Vorschläge an.\nDie Option inMarkupAndStylesheetFilesOnly gilt für HTML, HAML, Jade, Slim, XML, XSL, CSS, SCSS, Sass, Less und Stylus.\nDie Option \"always\" gilt unabhängig vom Markup/CSS für alle Teile der Datei.", - "emmetShowAbbreviationSuggestions": "Zeigt mögliche Emmet-Abkürzungen als Vorschläge an. Diese Option gilt nicht in Stylesheets oder wenn emmet.showExpandedAbbreviation auf \"never\" festgelegt ist.", - "emmetIncludeLanguages": "Aktivieren Sie Emmet-Abkürzungen in Sprachen, die nicht standardmäßig unterstützt werden. Fügen Sie hier ein Mapping zwischen der Sprache und der von Emmet unterstützten Sprache hinzu.\nBeispiel: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "In Emmet-Ausschnitten zu verwendende Variablen", - "emmetTriggerExpansionOnTab": "Wenn aktiviert, werden Emmet-Abkürzungen beim Drücken der TAB-TASTE erweitert.", "emmetPreferences": "Einstellungen, die zum Ändern des Verhaltens einiger Aktionen und Konfliktlöser von Emmet verwendet werden.", "emmetPreferencesIntUnit": "Standardeinheit für Integerwerte", "emmetPreferencesFloatUnit": "Standardeinheit für Floatwerte", @@ -43,6 +36,5 @@ "emmetPreferencesStylusAfter": "Symbol, das beim Erweitern von CSS-Abkürzungen in Stylus-Dateien am Ende der CSS-Eigenschaft eingefügt werden soll", "emmetPreferencesCssBetween": "Symbol, das beim Erweitern von CSS-Abkürzungen zwischen der CSS-Eigenschaft und dem Wert eingefügt werden soll", "emmetPreferencesSassBetween": "Symbol, das beim Erweitern von CSS-Abkürzungen in Sass-Dateien zwischen der CSS-Eigenschaft und dem Wert eingefügt werden soll", - "emmetPreferencesStylusBetween": "Symbol, das beim Erweitern von CSS-Abkürzungen in Stylus-Dateien zwischen der CSS-Eigenschaft und dem Wert eingefügt werden soll", - "emmetShowSuggestionsAsSnippets": "Bei TRUE werden die Emmet-Vorschläge als Ausschnitte angezeigt, mit denen Sie sie der editor.snippetSuggestions-Einstellung entsprechend anordnen können." + "emmetPreferencesStylusBetween": "Symbol, das beim Erweitern von CSS-Abkürzungen in Stylus-Dateien zwischen der CSS-Eigenschaft und dem Wert eingefügt werden soll" } \ No newline at end of file diff --git a/i18n/deu/extensions/git/out/commands.i18n.json b/i18n/deu/extensions/git/out/commands.i18n.json index c3d3a5519b7..3f2fcad2989 100644 --- a/i18n/deu/extensions/git/out/commands.i18n.json +++ b/i18n/deu/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Git-Repository wird geklont...", "openrepo": "Repository öffnen", "proposeopen": "Möchten Sie das geklonte Repository öffnen?", - "path to init": "Ordnerpfad", - "provide path": "Geben Sie einen Ordnerpfad zum Initialisieren eines Git-Repositorys an.", + "init repo": "Repository initialisieren", + "create repo": "Repository initialisieren", + "are you sure": "Erstellt ein Git-Repository unter '{0}'. Sind Sie sicher das Sie weiterfahren möchten?", "HEAD not available": "Es ist keine HEAD-Version von \"{0}\" verfügbar.", "confirm stage files with merge conflicts": "Möchten Sie {0} Dateien mit Mergingkonflikten bereitstellen?", "confirm stage file with merge conflicts": "Möchten Sie {0} mit Mergingkonflikten bereitstellen?", diff --git a/i18n/deu/extensions/git/out/repository.i18n.json b/i18n/deu/extensions/git/out/repository.i18n.json index eeff60b713c..aa81d1a2b07 100644 --- a/i18n/deu/extensions/git/out/repository.i18n.json +++ b/i18n/deu/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Gelöscht von uns", "both added": "Beide hinzugefügt", "both modified": "Beide geändert", + "untracked, short": "U", + "modified, short": "M", "commit": "Commit", "merge changes": "Änderungen zusammenführen", "staged changes": "Bereitgestellte Änderungen", diff --git a/i18n/deu/extensions/git/package.i18n.json b/i18n/deu/extensions/git/package.i18n.json index 4b4b197df1a..42eb8374ef1 100644 --- a/i18n/deu/extensions/git/package.i18n.json +++ b/i18n/deu/extensions/git/package.i18n.json @@ -15,6 +15,8 @@ "command.stageAll": "Alle Änderungen bereitstellen", "command.stageSelectedRanges": "Gewählte Bereiche bereitstellen", "command.revertSelectedRanges": "Ausgewählte Bereiche zurücksetzen", + "command.stageChange": "Änderung bereitstellen", + "command.revertChange": "Änderung zurücksetzen", "command.unstage": "Bereitstellung der Änderungen aufheben", "command.unstageAll": "Bereitstellung aller Änderungen aufheben", "command.unstageSelectedRanges": "Bereitstellung gewählter Bereiche aufheben", diff --git a/i18n/deu/extensions/typescript/package.i18n.json b/i18n/deu/extensions/typescript/package.i18n.json index 227e220881d..3725f9400c0 100644 --- a/i18n/deu/extensions/typescript/package.i18n.json +++ b/i18n/deu/extensions/typescript/package.i18n.json @@ -44,7 +44,6 @@ "typescript.npm": "Gibt den Pfad zur ausführbaren NPM-Datei an, die für die automatische Typerfassung verwendet wird. Hierfür ist TypeScript 2.3.4 oder höher erforderlich.", "typescript.check.npmIsInstalled": "Überprüfen Sie, ob NPM für die automatische Typerfassung installiert ist.", "javascript.nameSuggestions": "Das Einbeziehen eindeutiger Namen von der Datei in der JavaScript-Vorschlagsliste aktivieren/deaktivieren.", - "typescript.tsc.autoDetect": "Steuert, ob die automatische Erkennung von tsc-Tasks aktiviert oder deaktiviert ist.\n", "typescript.problemMatchers.tsc.label": "TypeScript-Probleme", "typescript.problemMatchers.tscWatch.label": "TypeScript-Probleme (Überwachungsmodus)" } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/deu/src/vs/editor/contrib/find/browser/findWidget.i18n.json index bbffc013c9e..1a791fe2241 100644 --- a/i18n/deu/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Ersetzen", "label.replaceAllButton": "Alle ersetzen", "label.toggleReplaceButton": "Ersetzen-Modus wechseln", - "title.matchesCountLimit": "Nur die ersten 999 Ergebnisse werden hervorgehoben, alle Suchvorgänge beziehen sich aber auf den gesamten Text.", "label.matchesLocation": "{0} von {1}", "label.noResults": "Keine Ergebnisse" } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/deu/src/vs/editor/contrib/find/common/findController.i18n.json index a704a485374..966c9eafe93 100644 --- a/i18n/deu/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Nächste Auswahl suchen", "previousSelectionMatchFindAction": "Vorherige Auswahl suchen", "startReplace": "Ersetzen", - "addSelectionToNextFindMatch": "Auswahl zur nächsten Übereinstimmungssuche hinzufügen", - "addSelectionToPreviousFindMatch": "Letzte Auswahl zu vorheriger Übereinstimmungssuche hinzufügen", - "moveSelectionToNextFindMatch": "Letzte Auswahl in nächste Übereinstimmungssuche verschieben", - "moveSelectionToPreviousFindMatch": "Letzte Auswahl in vorherige Übereinstimmungssuche verschieben", - "selectAllOccurrencesOfFindMatch": "Alle Vorkommen auswählen und Übereinstimmung suchen", - "changeAll.label": "Alle Vorkommen ändern", "showNextFindTermAction": "Nächsten Suchbegriff anzeigen", "showPreviousFindTermAction": "Vorherigen Suchbegriff anzeigen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/deu/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 58edd06f8f7..66385866668 100644 --- a/i18n/deu/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Cursor oberhalb hinzufügen", "mutlicursor.insertBelow": "Cursor unterhalb hinzufügen", - "mutlicursor.insertAtEndOfEachLineSelected": "Cursor an Zeilenenden hinzufügen" + "mutlicursor.insertAtEndOfEachLineSelected": "Cursor an Zeilenenden hinzufügen", + "addSelectionToNextFindMatch": "Auswahl zur nächsten Übereinstimmungssuche hinzufügen", + "addSelectionToPreviousFindMatch": "Letzte Auswahl zu vorheriger Übereinstimmungssuche hinzufügen", + "moveSelectionToNextFindMatch": "Letzte Auswahl in nächste Übereinstimmungssuche verschieben", + "moveSelectionToPreviousFindMatch": "Letzte Auswahl in vorherige Übereinstimmungssuche verschieben", + "selectAllOccurrencesOfFindMatch": "Alle Vorkommen auswählen und Übereinstimmung suchen", + "changeAll.label": "Alle Vorkommen ändern" } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json index a26d1d4b935..b1b17e724eb 100644 --- a/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Ungültiges Farbformat. Verwenden Sie #RGB, #RGBA, #RRGGBB oder #RRGGBBAA.", "schema.colors": "In der Workbench verwendete Farben.", "foreground": "Allgemeine Vordergrundfarbe. Diese Farbe wird nur verwendet, wenn sie nicht durch eine Komponente überschrieben wird.", "errorForeground": "Allgemeine Vordergrundfarbe. Diese Farbe wird nur verwendet, wenn sie nicht durch eine Komponente überschrieben wird.", diff --git a/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json index d630b8be8f2..fd7afc2d998 100644 --- a/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "Ordner zum Arbeitsbereich hinzufügen...", "add": "&&Hinzufügen", "addFolderToWorkspaceTitle": "Ordner zum Arbeitsbereich hinzufügen", + "globalRemoveFolderFromWorkspace": "Ordner aus dem Arbeitsbereich entfernen...", "newWorkspace": "Neuer Arbeitsbereich...", "select": "Au&&swählen", "selectWorkspace": "Ordner für den Arbeitsbereich auswählen", "removeFolderFromWorkspace": "Ordner aus dem Arbeitsbereich entfernen", + "openFolderSettings": "Ordnereinstellungen öffnen", "saveWorkspaceAsAction": "Arbeitsbereich speichern unter...", "save": "&&Speichern", "saveWorkspace": "Arbeitsbereich speichern", "openWorkspaceAction": "Arbeitsbereich öffnen...", "openWorkspaceConfigFile": "Konfigurationsdatei des Arbeitsbereichs öffnen", + "openFolderAsWorkspaceInNewWindow": "Ordner als Arbeitsbereich in neuem Fenster öffnen", "workspaceFolderPickerPlaceholder": "Arbeitsbereichsordner auswählen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index 419bdb09927..4bf40f11e3b 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Aktivitätsleiste ausblenden", - "activityBarAriaLabel": "Umschaltung der aktiven Ansicht", "globalActions": "Globale Aktionen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..a2d382d743c --- /dev/null +++ b/i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Umschaltung der aktiven Ansicht" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..3e71b2d6ba4 --- /dev/null +++ b/i18n/deu/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "Zusätzliche Ansichten", + "numberBadge": "{0} ({1})", + "manageExtension": "Erweiterung verwalten", + "titleKeybinding": "{0} ({1})", + "toggle": "Ansichtsfixierung umschalten" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 7ce49db8855..0812b9299a4 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "Editoren in zweiter Gruppe anzeigen", "groupThreePicker": "Editoren in dritter Gruppe anzeigen", "allEditorsPicker": "Alle geöffneten Editoren anzeigen", - "view": "Anzeigen" + "view": "Anzeigen", + "file": "Datei" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index f86613230bf..cda94be8348 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "Der Befehl \"{0}\" ist zurzeit nicht aktiviert und kann nicht ausgeführt werden.", "manageExtension": "Erweiterung verwalten" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json index ac447a68175..3cc4c47add8 100644 --- a/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,14 @@ "workspaces": "Arbeitsbereiche", "developer": "Entwickler", "showEditorTabs": "Steuert, ob geöffnete Editoren auf Registerkarten angezeigt werden sollen.", - "workbench.editor.labelFormat.default": "Zeigt den Namen der Datei an. Wenn Registerkarten aktiviert sind und zwei Dateien den gleichen Namen in einer Gruppe haben, werden die besonderen Abschnitte des Pfads jeder Datei hinzugefügt. Wenn Registerkarten deaktiviert sind, wird der Pfad zum Arbeitsbereich-Stammverzeichnis angezeigt, wenn der Editor aktiv ist.", "workbench.editor.labelFormat.short": "Den Namen der Datei anzeigen, gefolgt von dessen Verzeichnisnamen.", - "workbench.editor.labelFormat.medium": "Zeigt den Namen der Datei an, gefolgt vom Pfad zum Arbeitsbereich-Stammverzeichnis.", "workbench.editor.labelFormat.long": "Zeigt den Namen der Datei an, gefolgt von ihrem absoluten Pfad.", "tabDescription": "Steuert das Format der Beschriftung für einen Editor. Wenn Sie diese Einstellung ändern, ist beispielsweise der Speicherort einer Datei besser ersichtlich:\n- kurz: \"parent\"\n- mittel: \"workspace/src/parent\"\n- lang: \"/home/user/workspace/src/parent\"\n- Standard: \".../parent\", wenn eine andere Registerkarte denselben Titel hat, oder den relativen Arbeitsbereichspfad, wenn Registerkarten deaktiviert sind.", "editorTabCloseButton": "Steuert die Position der Schließen-Schaltflächen der Editor-Registerkarten oder deaktiviert sie bei der Einstellung \"off\".", "showIcons": "Steuert, ob geöffnete Editoren mit einem Symbol angezeigt werden sollen. Hierzu muss auch ein Symboldesign aktiviert werden.", "enablePreview": "Steuert, ob geöffnete Editoren als Vorschau angezeigt werden. Vorschau-Editoren werden wiederverwendet, bis sie gespeichert werden (z. B. über Doppelklicken oder Bearbeiten), und sie werden mit kursivem Schriftschnitt angezeigt.", "enablePreviewFromQuickOpen": "Steuert, ob geöffnete Editoren aus Quick Open als Vorschau angezeigt werden. Vorschau-Editoren werden wiederverwendet, bis sie gespeichert werden (z. B. über Doppelklicken oder Bearbeiten).", - "editorOpenPositioning": "Steuert, wo Editoren geöffnet werden. Wählen Sie \"Links\" oder \"Rechts\" aus, um Editoren links oder rechts vom aktuellen aktiven Editor zu öffnen. Wählen Sie \"Erster\" oder \"Letzter\" aus, um Editoren unabhängig vom aktuell aktiven Editor zu öffnen.", "revealIfOpen": "Steuert, ob ein geöffneter Editor in einer der sichtbaren Gruppen angezeigt wird. Ist diese Option deaktiviert, wird ein Editor vorzugsweise in der aktuell aktiven Editorgruppe geöffnet. Ist diese Option aktiviert, wird ein bereits geöffneter Editor angezeigt und nicht in der aktuell aktiven Editorgruppe erneut geöffnet. In einigen Fällen wird diese Einstellung ignoriert, z. B. wenn das Öffnen eines Editors in einer bestimmten Gruppe oder neben der aktuell aktiven Gruppe erzwungen wird.", - "commandHistory": "Steuert, ob die Anzahl zuletzt verwendeter Befehle im Verlauf für die Befehlspalette gespeichert wird. Legen Sie diese Option auf 0 fest, um den Befehlsverlauf zu deaktivieren.", "preserveInput": "Steuert, ob die letzte typisierte Eingabe in die Befehlspalette beim nächsten Öffnen wiederhergestellt wird.", "closeOnFocusLost": "Steuert, ob Quick Open automatisch geschlossen werden soll, sobald das Feature den Fokus verliert.", "openDefaultSettings": "Steuert, ob beim Öffnen der Einstellungen auch ein Editor geöffnet wird, der alle Standardeinstellungen anzeigt.", @@ -50,7 +46,6 @@ "restoreWindows": "Steuert, wie Fenster nach einem Neustart erneut geöffnet werden. Wählen Sie \"none\", um immer mit einem leeren Arbeitsbereich zu beginnen, \"one\", um das zuletzt verwendete Fenster erneut zu öffnen, \"folders\", um alle Fenster, in denen Ordner geöffnet waren, erneut zu öffnen, oder \"all\", um alle Fenster der letzten Sitzung erneut zu öffnen.", "restoreFullscreen": "Steuert, ob ein Fenster im Vollbildmodus wiederhergestellt wird, wenn es im Vollbildmodus beendet wurde.", "zoomLevel": "Passen Sie den Zoomfaktor des Fensters an. Die ursprüngliche Größe ist 0. Jede Inkrementierung nach oben (z. B. 1) oder unten (z. B. -1) stellt eine Vergrößerung bzw. Verkleinerung um 20 % dar. Sie können auch Dezimalwerte eingeben, um den Zoomfaktor genauer anzupassen.", - "title": "Steuert den Fenstertitel basierend auf dem aktiven Editor. Variablen werden abhängig vom Kontext ersetzt:\n${activeEditorShort}: z. B. meineDatei.txt\n${activeEditorMedium}: z. B. meinOrdner/meineDatei.txt\n${activeEditorLong}: z. B. /Users/Development/meinProjekt/meinOrdner/meineDatei.txt\n${folderName}: z. B. \nmeinOrdner${folderPath}: z. B. /Users/Development/meinOrdner\n${rootName}: z. B. meinOrdner1, meinOrdner2, meinOrdner3\n${rootPath}: z. B. /Users/Development/meinArbeitsbereich\n${appName}: z. B. VS Code\n${dirty}: ein Änderungsindikator, wenn der aktive Editor geändert wurde\n${separator}: ein bedingtes Trennzeichen (\" - \"), das nur angezeigt wird, wenn es zwischen Variablen mit Werten steht", "window.newWindowDimensions.default": "Öffnet neue Fenster in der Mitte des Bildschirms.", "window.newWindowDimensions.inherit": "Öffnet neue Fenster mit den gleichen Abmessungen wie das letzte aktive Fenster.", "window.newWindowDimensions.maximized": "Öffnet neue Fenster maximiert.", diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index be338b43ea2..b06443ae9ef 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, Debugging", "debugAriaLabel": "Geben Sie den Namen einer auszuführenden Startkonfiguration ein.", + "addConfigTo": "Konfiguration hinzufügen ({0})...", + "addConfiguration": "Konfiguration hinzufügen...", "noConfigurationsMatching": "Keine übereinstimmenden Debugkonfigurationen", "noConfigurationsFound": "Keine Debugkonfiguration gefunden. Erstellen Sie die Datei \"launch.json\"." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..5345ba65476 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Debuggen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 427b79c92de..1c098b69622 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Konfigurationen zum Generieren der anfänglichen Datei \"launch.json\".", "vscode.extension.contributes.debuggers.languages": "Liste der Sprachen, für die die Debugerweiterung als \"Standarddebugger\" angesehen werden kann", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Wenn dies festgelegt ist, ruft der VS Code diesen Befehl auf, um den ausführbaren Pfad des Debugadapters und die zu übergebenden Argumente zu bestimmen.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Wenn dies festgelegt ist, ruft der VS Code diesen Befehl für die Debug- oder Ausführungsaktionen aus, die für diese Erweiterung bestimmt sind.", "vscode.extension.contributes.debuggers.configurationSnippets": "Snippets zum Hinzufügen neuer Konfigurationen in \"launch.json\".", "vscode.extension.contributes.debuggers.configurationAttributes": "JSON-Schemakonfigurationen zum Überprüfen von \"launch.json\".", "vscode.extension.contributes.debuggers.windows": "Windows-spezifische Einstellungen.", diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 85809743b85..2cbcf3ae529 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,7 @@ "breakpointRemoved": "Der Haltepunkt wurde entfernt. Zeile {0}, Datei \"{1}\".", "compoundMustHaveConfigurations": "Für den Verbund muss das Attribut \"configurations\" festgelegt werden, damit mehrere Konfigurationen gestartet werden können.", "configMissing": "Konfiguration \"{0}\" fehlt in \"launch.json\".", - "debugRequestNotSupported": "Die ausgewählte Debugkonfiguration verfügt über einen nicht unterstützten Attributwert \"{0}\": \"{1}\".", - "debugRequesMissing": "Das Attribut \"{0}\" fehlt in der ausgewählten Debugkonfiguration.", "debugTypeNotSupported": "Der konfigurierte Debugtyp \"{0}\" wird nicht unterstützt.", - "debugTypeMissing": "Fehlende Eigenschaft \"type\" für die ausgewählte Startkonfiguration.", "preLaunchTaskErrors": "Buildfehler während preLaunchTask \"{0}\".", "preLaunchTaskError": "Buildfehler während preLaunchTask \"{0}\".", "preLaunchTaskExitCode": "Der preLaunchTask \"{0}\" wurde mit dem Exitcode {1} beendet.", diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index dded802b64c..fc3e3434fee 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "Der Objektstatus wird aus der ersten Auswertung erfasst.", "replVariableAriaLabel": "Variable {0} besitzt den Wert {1}, Read Eval Print-Loop, Debuggen", "replExpressionAriaLabel": "Ausdruck {0} besitzt den Wert {1}, Read Eval Print-Loop, Debuggen", - "replValueOutputAriaLabel": "{0}, Read Eval Print-Loop, Debuggen", - "replKeyValueOutputAriaLabel": "Ausgabevariable {0} besitzt den Wert {1}, Read Eval Print-Loop, Debuggen" + "replValueOutputAriaLabel": "{0}, Read Eval Print-Loop, Debuggen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index bc53701d4ae..46de1e8541a 100644 --- a/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Dateien", + "filesCategory": "Datei", "revealInSideBar": "In Seitenleiste anzeigen", "acceptLocalChanges": "Änderungen verwenden und Datenträgerinhalte überschreiben", "revertLocalChanges": "Änderungen verwerfen und Datenträgerinhalte wiederherstellen" diff --git a/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 9bbadf5a16f..241386f0b5c 100644 --- a/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "Möchten Sie \"{0}\" wirklich löschen?", "undoBin": "Die Wiederherstellung kann aus dem Papierkorb erfolgen.", "undoTrash": "Die Wiederherstellung kann aus dem Papierkorb erfolgen.", + "doNotAskAgain": "Nicht erneut fragen", "confirmDeleteMessageFolder": "Möchten Sie \"{0}\" samt Inhalt wirklich endgültig löschen?", "confirmDeleteMessageFile": "Möchten Sie \"{0}\" wirklich endgültig löschen?", "irreversible": "Diese Aktion kann nicht rückgängig gemacht werden.", @@ -37,8 +38,6 @@ "openToSide": "Zur Seite öffnen", "compareSource": "Für Vergleich auswählen", "globalCompareFile": "Aktive Datei vergleichen mit...", - "pickHistory": "Zuvor geöffnete Datei für den Vergleich auswählen", - "unableToFileToCompare": "Die ausgewählte Datei kann nicht mit \"{0}\" verglichen werden.", "openFileToCompare": "Zuerst eine Datei öffnen, um diese mit einer anderen Datei zu vergleichen", "compareWith": "'{0}' mit '{1}' vergleichen", "compareFiles": "Dateien vergleichen", @@ -47,7 +46,7 @@ "saveAs": "Speichern unter...", "saveAll": "Alle speichern", "saveAllInGroup": "Alle in der Gruppe speichern", - "saveFiles": "Geänderte Dateien speichern", + "saveFiles": "Alle Dateien speichern", "revert": "Datei wiederherstellen", "focusOpenEditors": "Fokus auf Ansicht \"Geöffnete Editoren\"", "focusFilesExplorer": "Fokus auf Datei-Explorer", diff --git a/i18n/deu/src/vs/workbench/parts/files/browser/files.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/files/browser/files.contribution.i18n.json index 93f045f545a..e396ef8d753 100644 --- a/i18n/deu/src/vs/workbench/parts/files/browser/files.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/browser/files.contribution.i18n.json @@ -40,6 +40,8 @@ "dynamicHeight": "Steuert, ob sich die Höhe des Abschnitts \"Geöffnete Editoren\" dynamisch an die Anzahl der Elemente anpassen soll.", "autoReveal": "Steuert, ob der Explorer Dateien beim Öffnen automatisch anzeigen und auswählen soll.", "enableDragAndDrop": "Steuert, ob der Explorer das Verschieben von Dateien und Ordnern mithilfe von Drag Drop zulassen soll.", + "confirmDragAndDrop": "Steuert, ob der Explorer um Bestätigung bitten soll, beim Verschieben von Dateien oder Ordnern per Ziehen und Ablegen.", + "confirmDelete": "Steuert, ob der Explorer um Bestätigung bitten soll, wenn Sie eine Datei über den Papierkorb löschen.", "sortOrder.default": "Dateien und Ordner werden nach ihren Namen in alphabetischer Reihenfolge sortiert. Ordner werden vor Dateien angezeigt. ", "sortOrder.mixed": "Dateien und Ordner werden nach ihren Namen in alphabetischer Reihenfolge sortiert. Dateien und Ordner werden vermischt angezeigt.", "sortOrder.filesFirst": "Dateien und Ordner werden nach ihren Namen in alphabetischer Reihenfolge sortiert. Dateien werden vor Ordnern angezeigt.", diff --git a/i18n/deu/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/deu/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index e04313a8208..e3de54fe532 100644 --- a/i18n/deu/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,8 @@ { "noWorkspace": "Es ist kein Ordner geöffnet.", "explorerSection": "Datei-Explorer-Abschnitt", - "noWorkspaceHelp": "Sie haben noch keinen Ordner geöffnet.", + "noWorkspaceHelp": "Sie haben noch keinen Ordner zum Arbeitsbereich hinzugefügt.", + "addFolder": "Ordner hinzufügen", + "noFolderHelp": "Sie haben noch keinen Ordner geöffnet.", "openFolder": "Ordner öffnen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/deu/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index 31a534a16fa..972dbbe86f2 100644 --- a/i18n/deu/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "Ordner {0} kann nicht aufgelöst werden.", "fileInputAriaLabel": "Geben Sie den Dateinamen ein. Drücken Sie zur Bestätigung die EINGABETASTE oder ESC, um den Vorgang abzubrechen.", "filesExplorerViewerAriaLabel": "{0}, Datei-Explorer", "dropFolders": "Möchten Sie die Ordner zum Arbeitsbereich hinzufügen?", "dropFolder": "Möchten Sie den Ordner zum Arbeitsbereich hinzufügen?", "addFolders": "&&Ordner hinzufügen", "addFolder": "&&Ordner hinzufügen", + "confirmMove": "Sind Sie sicher, dass Sie \"{0}\" verschieben möchten?", + "doNotAskAgain": "Nicht erneut fragen", "confirmOverwriteMessage": "{0} ist im Zielordner bereits vorhanden. Möchten Sie das Element ersetzen?", "irreversible": "Diese Aktion kann nicht rückgängig gemacht werden.", "replaceButtonLabel": "&&Ersetzen" diff --git a/i18n/deu/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..cf58a240413 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Probleme", + "tooltip.1": "1 Problem in dieser Datei", + "tooltip.N": "{0} Probleme in dieser Datei", + "markers.showOnFile": "Fehler & Warnungen auf Dateien und Ordnern anzeigen." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index c7f0245455c..b100f612513 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Platzieren Sie Ihre Einstellungen hier, um die Standardeinstellungen zu überschreiben.", - "errorInvalidConfiguration": "Einstellungen können nicht geschrieben werden. Öffnen Sie die Datei, um Fehler/Warnungen in der Datei zu korrigieren. Versuchen Sie es anschließend noch mal.", "emptyWorkspaceSettingsHeader": "Platzieren Sie Ihre Einstellungen hier, um die Benutzereinstellungen zu überschreiben.", "emptyFolderSettingsHeader": "Platzieren Sie Ihre Ordnereinstellungen hier, um die Einstellungen in den Arbeitsbereichseinstellungen zu überschreiben.", "defaultFolderSettingsTitle": "Standardordnereinstellungen", diff --git a/i18n/deu/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/deu/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 321ccab5284..77769778060 100644 --- a/i18n/deu/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "Der Befehl \"{0}\" ist im aktuellen Kontext nicht aktiviert.", "recentlyUsed": "zuletzt verwendet", "morecCommands": "andere Befehle", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "Keine übereinstimmenden Befehle." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index 96756d61e40..bd63f3fb9cd 100644 --- a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "changes": "{0} von {1} Änderungen", + "change": "{0} von {1} Änderung", + "show previous change": "Vorherige Änderung anzeigen", + "show next change": "Nächste Änderung anzeigen", "editorGutterModifiedBackground": "Hintergrundfarbe für die Editor-Leiste für Zeilen, die geändert wurden.", "editorGutterAddedBackground": "Hintergrundfarbe für die Editor-Leiste für Zeilen, die hinzugefügt wurden.", "editorGutterDeletedBackground": "Hintergrundfarbe für die Editor-Leiste für Zeilen, die gelöscht wurden.", diff --git a/i18n/deu/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index 44f81eb9c7f..b36930b05c6 100644 --- a/i18n/deu/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,6 @@ "exclude": "Konfigurieren Sie Globmuster zum Ausschließen von Dateien und Ordnern in Suchvorgängen. Alle Globmuster werden von der files.exclude-Einstellung geerbt.", "exclude.boolean": "Das Globmuster, mit dem Dateipfade verglichen werden sollen. Legen Sie diesen Wert auf \"true\" oder \"false\" fest, um das Muster zu aktivieren bzw. zu deaktivieren.", "exclude.when": "Zusätzliche Überprüfung der gleichgeordneten Elemente einer entsprechenden Datei. Verwenden Sie \"$(basename)\" als Variable für den entsprechenden Dateinamen.", - "useRipgrep": "Steuert, ob \"ripgrep\" in der Textsuche verwendet wird", "useIgnoreFilesByDefault": "Steuert, ob bei der Suche in einem neuen Arbeitsbereich standardmäßig GITIGNORE- und IGNORE-Dateien verwendet werden sollen.", "search.quickOpen.includeSymbols": "Konfigurieren Sie diese Option, um Ergebnisse aus einer globalen Symbolsuche in die Dateiergebnisse für Quick Open einzuschließen." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json index b16c9eacc2a..94d13d8f553 100644 --- a/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Suchergebnisse löschen", "FocusNextSearchResult.label": "Fokus auf nächstes Suchergebnis", "FocusPreviousSearchResult.label": "Fokus auf vorheriges Suchergebnis", - "RemoveAction.label": "Entfernen", "file.replaceAll.label": "Alle ersetzen", "match.replace.label": "Ersetzen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 016b1854df2..1d0d27e52b0 100644 --- a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Trägt Codeausschnitte bei.", "vscode.extension.contributes.snippets-language": "Der Sprachbezeichner, für den dieser Codeausschnitt beigetragen wird.", "vscode.extension.contributes.snippets-path": "Der Pfad der Codeausschnittdatei. Der Pfad ist relativ zum Erweiterungsordner und beginnt normalerweise mit \". /snippets/\".", - "badFile": "Die Ausschnittsdatei \"{0}\" konnte nicht gelesen werden.", "badVariableUse": "Das \"{0}\"-Snippet verwirrt wahrscheinlich Snippet-Variablen und Snippet-Paltzhalter. Schaue https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax für weitere Informationen.", + "badFile": "Die Ausschnittsdatei \"{0}\" konnte nicht gelesen werden.", "source.snippet": "Benutzercodeausschnitt", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 5f9f1928ae6..09fd787097a 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -14,6 +14,7 @@ "runningTasks": "Aktive Aufgaben anzeigen", "tasks": "Aufgaben", "TaskSystem.noHotSwap": "Zum Ändern des Aufgabenausführungsmoduls mit einem aktiven Task muss das Fenster erneut geladen werden.", + "TaskServer.folderIgnored": "Der Ordner {0} wird ignoriert, da er Aufgabenversion 0.1.0 verwendet", "TaskService.noBuildTask1": "Keine Buildaufgabe definiert. Markieren Sie eine Aufgabe mit 'isBuildCommand' in der tasks.json-Datei.", "TaskService.noBuildTask2": "Es ist keine Buildaufgabe definiert. Markieren Sie eine Aufgabe in der Datei \"tasks.json\" als \"Buildgruppe\". ", "TaskService.noTestTask1": "Keine Testaufgabe definiert. Markieren Sie eine Aufgabe mit 'isTestCommand' in der tasks.json-Datei.", diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 7d62688f024..93a8b04286a 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Neues Terminal", "workbench.action.terminal.focus": "Fokus im Terminal", "workbench.action.terminal.focusNext": "Fokus im nächsten Terminal", - "workbench.action.terminal.focusAtIndex": "Terminal {0} im Fokus", "workbench.action.terminal.focusPrevious": "Fokus im vorherigen Terminal", "workbench.action.terminal.paste": "In aktives Terminal einfügen", "workbench.action.terminal.DefaultShell": "Standardshell auswählen", diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 558f228c1f1..cf9ef31e248 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Kopieren", - "createNewTerminal": "Neues Terminal", "paste": "Einfügen", "selectAll": "Alles auswählen", "clear": "Löschen" diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index e01f30f61a5..ac6f1dfc78c 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "OK, nicht mehr anzeigen", "terminal.integrated.chooseWindowsShell": "Wählen Sie Ihre bevorzugte Terminalshell. Sie können diese später in Ihren Einstellungen ändern.", "terminalService.terminalCloseConfirmationSingular": "Eine aktive Terminalsitzung ist vorhanden. Möchten Sie sie beenden?", - "terminalService.terminalCloseConfirmationPlural": "{0} aktive Terminalsitzungen sind vorhanden. Möchten Sie sie beenden?", - "yes": "Ja" + "terminalService.terminalCloseConfirmationPlural": "{0} aktive Terminalsitzungen sind vorhanden. Möchten Sie sie beenden?" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..ce08826d007 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Eine Zusammenfassung der Einstellungen. Diese Bezeichnung wird in der Einstellungsdatei als trennender Kommentar verwendet.", + "vscode.extension.contributes.configuration.properties": "Die Beschreibung der Konfigurationseigenschaften.", + "scope.window.description": "Fensterspezifische Konfiguration, die in den Benutzer- oder Arbeitsbereichseinstellungen konfiguriert werden kann.", + "scope.resource.description": "Ressourcenspezifische Konfiguration, die in den Benutzer-, Arbeitsbereichs- oder Ordnereinstellungen konfiguriert werden kann.", + "scope.description": "Bereich, in dem die Konfiguration gültig ist. Verfügbare Gültigkeitsbereiche sind \"window\" und \"resource\".", + "vscode.extension.contributes.configuration": "Trägt Konfigurationseigenschaften bei.", + "invalid.title": "configuration.title muss eine Zeichenfolge sein.", + "vscode.extension.contributes.defaultConfiguration": "Trägt zu Konfigurationeinstellungen des Standard-Editors für die jeweilige Sprache bei.", + "invalid.properties": "\"configuration.properties\" muss ein Objekt sein.", + "invalid.allOf": "\"configuration.allOf\" ist veraltet und sollte nicht mehr verwendet werden. Übergeben Sie stattdessen mehrere Konfigurationsabschnitte als Array an den Beitragspunkt \"configuration\".", + "workspaceConfig.folders.description": "Liste von Ordnern, die in den Arbeitsbereich geladen werden.", + "workspaceConfig.path.description": "Ein Dateipfad, z. B. \" /root/folderA\" oder \"./folderA\" bei einem relativen Pfad, der in Bezug auf den Speicherort der Arbeitsbereichsdatei aufgelöst wird.", + "workspaceConfig.name.description": "Ein optionaler Name für den Ordner.", + "workspaceConfig.extensions.description": "Arbeitsbereichserweiterungen", + "unknownWorkspaceProperty": "Unbekannte Arbeitsbereichs-Konfigurationseigenschaft" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/deu/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/deu/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index 3628bed2f06..d13ca944626 100644 --- a/i18n/deu/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/deu/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -6,6 +6,7 @@ { "schema.token.settings": "Farben und Stile für das Token.", "schema.token.foreground": "Vordergrundfarbe für das Token.", + "schema.token.background.warning": "Token Hintergrundfarben werden derzeit nicht unterstützt.", "schema.token.fontStyle": "Schriftschnitt der Regel: kursiv, fett und unterstrichen (einzeln oder in Kombination)", "schema.fontStyle.error": "Der Schriftschnitt muss eine Kombination aus \"kursiv\", \"fett\" und \"unterstrichen\" sein.", "schema.properties.name": "Beschreibung der Regel.", diff --git a/i18n/deu/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/deu/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index 86353589189..cce0737bd42 100644 --- a/i18n/deu/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/deu/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -33,5 +33,6 @@ "schema.fontSize": "Wenn eine Schriftart verwendet wird: der Schriftgrad als Prozentsatz der Textschriftart. Wenn diese Angabe nicht festgelegt wird, wird standardmäßig die Größe in der Schriftartdefinition verwendet.", "schema.fontId": "Bei Verwendung einer Schriftart: die ID der Schriftart. Wenn diese Angabe nicht festgelegt wird, wird standardmäßig die erste Schriftartdefinition verwendet.", "schema.light": "Optionale Zuordnungen für Dateisymbole in hellen Farbdesigns.", - "schema.highContrast": "Optionale Zuordnungen für Dateisymbole in Farbdesigns mit hohem Kontrast." + "schema.highContrast": "Optionale Zuordnungen für Dateisymbole in Farbdesigns mit hohem Kontrast.", + "schema.hidesExplorerArrows": "Konfiguriert, ob die Datei-Explorer Pfeile ausgeblendet werden sollen, wenn dieses Motiv aktiv ist." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/deu/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..667f131a465 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contributes textmate color themes.", + "vscode.extension.contributes.themes.id": "Die ID des Symboldesigns wie in den Benutzereinstellungen verwendet.", + "vscode.extension.contributes.themes.label": "Die Bezeichnung des Farbdesigns wie in der Benutzeroberfläche angezeigt.", + "vscode.extension.contributes.themes.uiTheme": "Das Basisdesign, das die Farben um den Editor definiert: \"vs\" ist das helle Farbdesign, \"vs-dark\" das dunkle Farbdesign. \"hc-black\" ist das dunkle Design mit hohem Kontrast.", + "vscode.extension.contributes.themes.path": "Der Pfad der TMTHEME-Datei. Der Pfad ist relativ zum Erweiterungsordner und lautet normalerweise \"./themes/themeFile.tmTheme\".", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "Expected string in `contributes.{0}.path`. Provided value: {1}", + "invalid.path.1": "Es wurde erwartet, dass \"contributes.{0}.path\" ({1}) im Ordner ({2}) der Erweiterung enthalten ist. Dies führt ggf. dazu, dass die Erweiterung nicht portierbar ist." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..b0f9faf6b52 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problems parsing file icons file: {0}" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..65109048ac5 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "Die ID des Symboldesigns wie in den Benutzereinstellungen verwendet.", + "vscode.extension.contributes.iconThemes.label": "Die Bezeichnung des Symboldesigns wie in der Benutzeroberfläche angezeigt.", + "vscode.extension.contributes.iconThemes.path": "Der Pfad der Symboldesign-Definitionsdatei. Der Pfad ist relativ zum Erweiterungsordner und lautet normalerweise \"./icons/awesome-icon-theme.json\".", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "Expected string in `contributes.{0}.path`. Provided value: {1}", + "reqid": "In \"contributes.{0}.id\" wurde eine Zeichenfolge erwartet. Bereitgestellter Wert: {1}", + "invalid.path.1": "Es wurde erwartet, dass \"contributes.{0}.path\" ({1}) im Ordner ({2}) der Erweiterung enthalten ist. Dies führt ggf. dazu, dass die Erweiterung nicht portierbar ist." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index a3137e30eb6..d551e506d69 100644 --- a/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "Die ID des Symboldesigns wie in den Benutzereinstellungen verwendet.", - "vscode.extension.contributes.themes.label": "Die Bezeichnung des Farbdesigns wie in der Benutzeroberfläche angezeigt.", - "vscode.extension.contributes.themes.uiTheme": "Das Basisdesign, das die Farben um den Editor definiert: \"vs\" ist das helle Farbdesign, \"vs-dark\" das dunkle Farbdesign. \"hc-black\" ist das dunkle Design mit hohem Kontrast.", - "vscode.extension.contributes.themes.path": "Der Pfad der TMTHEME-Datei. Der Pfad ist relativ zum Erweiterungsordner und lautet normalerweise \"./themes/themeFile.tmTheme\".", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "Die ID des Symboldesigns wie in den Benutzereinstellungen verwendet.", - "vscode.extension.contributes.iconThemes.label": "Die Bezeichnung des Symboldesigns wie in der Benutzeroberfläche angezeigt.", - "vscode.extension.contributes.iconThemes.path": "Der Pfad der Symboldesign-Definitionsdatei. Der Pfad ist relativ zum Erweiterungsordner und lautet normalerweise \"./icons/awesome-icon-theme.json\".", "migration.completed": "Den Benutzereinstellungen wurden neue Designeinstellungen hinzugefügt. Sicherung verfügbar unter {0}.", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "In \"contributes.{0}.path\" wurde eine Zeichenfolge erwartet. Bereitgestellter Wert: {1}", - "invalid.path.1": "Es wurde erwartet, dass \"contributes.{0}.path\" ({1}) im Ordner ({2}) der Erweiterung enthalten ist. Dies führt ggf. dazu, dass die Erweiterung nicht portierbar ist.", - "reqid": "In \"contributes.{0}.id\" wurde eine Zeichenfolge erwartet. Bereitgestellter Wert: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "Gibt das in der Workbench verwendete Symboldesign oder \"null\", um keine Dateisymbole anzuzeigen, an.", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Überschreibt Farben aus dem derzeit ausgewählte Farbdesign.", - "workbenchColors.deprecated": "Diese Einstellung ist nicht mehr experimentell und wurde in \"workbench.colorCustomizations\" umbenannt.", - "workbenchColors.deprecatedDescription": "Verwenden Sie stattdessen \"workbench.colorCustomizations\".", "editorColors": "Überschreibt Editorfarben und den Schriftschnitt aus dem momentan ausgewählten Farbdesign.", "editorColors.comments": "Legt die Farben und Stile für Kommentare fest.", "editorColors.strings": "Legt die Farben und Stile für Zeichenfolgenliterale fest.", diff --git a/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..9bb276f44ac --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Konfigurationsdatei des Arbeitsbereichs öffnen", + "close": "Schließen" +} \ No newline at end of file diff --git a/i18n/esn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/esn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 6f2a10e46de..0fea08772ca 100644 --- a/i18n/esn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/esn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "p. ej. myFile.txt", - "activeEditorMedium": "e.g. myFolder/myFile.txt", - "activeEditorLong": "e.g. /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "p. ej. myFolder1, myFolder2, myFolder3", - "rootPath": "p. ej. /Users/Development/myProject", - "folderName": "p. ej. myFolder", - "folderPath": "p. ej. /Users/Development/myFolder", + "activeEditorShort": "el nombre del archivo (por ejemplo miarchivo.txt)", + "activeEditorMedium": "la ruta de acceso del archivo relativa a la carpeta del espacio de trabajo (p. ej. miCarpeta/miArchivo.txt)", + "activeEditorLong": "la ruta de acceso completa del archivo (por ejemplo, /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "nombre del área de trabajo (p. ej. myFolder o myWorkspace)", + "rootPath": "ruta del archivo del área de trabajo (p. ej. /Users/Development/myWorkspace)", + "folderName": "nombre de la carpeta del área de trabajo en la que el archivo está contenido (p. ej. myFolder)", + "folderPath": "ruta de acceso de archivo de la carpeta del área de trabajo en la que el archivo está contenido (p. ej. /Users/Development/myFolder)", "appName": "p. ej. VS Code", "dirty": "un indicador con modificaciones si el editor activo tiene modificaciones", "separator": "un separador condicional (\"-\") que aparece solo cuando está rodeado de variables con valores", diff --git a/i18n/esn/extensions/emmet/package.i18n.json b/i18n/esn/extensions/emmet/package.i18n.json index 07653dd9567..863e98a95bb 100644 --- a/i18n/esn/extensions/emmet/package.i18n.json +++ b/i18n/esn/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Aumentar por 10", "command.decrementNumberByTen": "Disminuir por 10", "emmetSyntaxProfiles": "Defina el perfil de la sintaxis especificada o use su propio perfil con reglas específicas.", - "emmetExclude": "Matriz de lenguajes donde no deben expandirse la abreviación Emmet.", - "emmetExtensionsPath": "Ruta de acceso a una carpeta que contiene los perfiles de emmet y fragmentos.»", - "emmetShowExpandedAbbreviation": "\nMuestra abreviaciones Emmet expandidas como sugerencias. La opción \"inMarkupAndStylesheetFilesOnly\" se aplica a HTML, HAML, Jade, Slim, XML, XSL, CSS, SCSS, SASS, LESS y Stylus. La opción \"always\" se aplica a todas las partes del archivo, independientemente de que sea de marcado o CSS.", - "emmetShowAbbreviationSuggestions": "Muestra posibles abreviaciones Emmet como sugerencias. No se aplica a hojas de estilos ni cuando emmet.showExpandedAbbreviation está establecido en \"never\".", - "emmetIncludeLanguages": "Habilita abreviaciones Emmet en lenguajes que no se admiten de forma predeterminada. Agregue una asignación aquí entre el lenguaje y el lenguaje que admite Emmet.\n Ejemplo: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Variables para usar en fragmentos de código Emmet", - "emmetTriggerExpansionOnTab": "Cuando se habilita, se expande la abreviación Emmet al presionar la tecla TAB.", "emmetPreferences": "Preferencias usadas para modificar el comportamiento de algunas acciones y resoluciones de Emmet.", "emmetPreferencesIntUnit": "Unidad predeterminada para valores enteros", "emmetPreferencesFloatUnit": "Unidad predeterminada para valores float", @@ -43,6 +36,5 @@ "emmetPreferencesStylusAfter": "Símbolo que debe colocarse al final de una propiedad CSS cuando se expanden abreviaturas CSS en archivos Stylus", "emmetPreferencesCssBetween": "Símbolo que debe colocarse entre una propiedad CSS y un valor cuando se expanden abreviaturas CSS", "emmetPreferencesSassBetween": "Símbolo que debe colocarse entre una propiedad CSS y un valor cuando se expanden abreviaturas CSS en archivos SASS", - "emmetPreferencesStylusBetween": "Símbolo que debe colocarse entre una propiedad CSS y un valor cuando se expanden abreviaturas CSS en archivos Stylus", - "emmetShowSuggestionsAsSnippets": "Si es true, las sugerencias Emmet se muestran como fragmentos de código, de modo que puede ordenarlas por el valor editor.snippetSuggestions." + "emmetPreferencesStylusBetween": "Símbolo que debe colocarse entre una propiedad CSS y un valor cuando se expanden abreviaturas CSS en archivos Stylus" } \ No newline at end of file diff --git a/i18n/esn/extensions/git/out/commands.i18n.json b/i18n/esn/extensions/git/out/commands.i18n.json index 0376ca94cc1..69862736c9d 100644 --- a/i18n/esn/extensions/git/out/commands.i18n.json +++ b/i18n/esn/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Clonando el repositorio GIT...", "openrepo": "Abrir repositorio", "proposeopen": "¿Desea abrir el repositorio clonado?", - "path to init": "Ruta de acceso de la carpeta", - "provide path": "Proporcione una ruta de acceso de carpeta para inicializar un repositorio GIT", + "init repo": "Inicializar el repositorio", + "create repo": "Inicializar el repositorio", + "are you sure": "Esto creará un repositorio Git en '{0}'. ¿Está seguro de que desea continuar?", "HEAD not available": "La versión HEAD de '{0}' no está disponible.", "confirm stage files with merge conflicts": "¿Está seguro de que quiere hacer una copia intermedia de {0} archivos con conflictos de fusión mediante combinación?", "confirm stage file with merge conflicts": "¿Está seguro de que quiere hacer una copia intermedia de {0} con conflictos de fusión mediante combinación? ", diff --git a/i18n/esn/extensions/git/out/repository.i18n.json b/i18n/esn/extensions/git/out/repository.i18n.json index fc557b451ea..b6063166fd7 100644 --- a/i18n/esn/extensions/git/out/repository.i18n.json +++ b/i18n/esn/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Borrado por nosotros", "both added": "Ambos añadidos", "both modified": "Ambos modificados", + "untracked, short": "U", + "modified, short": "M", "commit": "Confirmar", "merge changes": "Fusionar cambios mediante combinación", "staged changes": "Cambios almacenados provisionalmente", diff --git a/i18n/esn/extensions/typescript/package.i18n.json b/i18n/esn/extensions/typescript/package.i18n.json index 2aeb36b7218..61e69211e91 100644 --- a/i18n/esn/extensions/typescript/package.i18n.json +++ b/i18n/esn/extensions/typescript/package.i18n.json @@ -44,7 +44,6 @@ "typescript.npm": "Especifica la ruta de acceso al archivo ejecutable de NPM usada para la adquisición automática de tipos. Requiere TypeScript >= 2.3.4.", "typescript.check.npmIsInstalled": "Compruebe si NPM está instalado para la adquisición automática de tipos.", "javascript.nameSuggestions": "Habilitar/deshabilitar nombres únicos de la lista de sugerencias en los archivos de JavaScript. ", - "typescript.tsc.autoDetect": "Controla si la detección automática de tareas TSC está activada o desactivada.", "typescript.problemMatchers.tsc.label": "Problemas de TypeScript", "typescript.problemMatchers.tscWatch.label": "Problemas de TypeScript (modo de inspección)" } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/esn/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 6ffe5c01c29..5b52fbf2852 100644 --- a/i18n/esn/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Reemplazar", "label.replaceAllButton": "Reemplazar todo", "label.toggleReplaceButton": "Alternar modo de reemplazar", - "title.matchesCountLimit": "Solo se resaltan los primeros 999 resultados, pero todas las operaciones de búsqueda trabajan en todo el texto.", "label.matchesLocation": "{0} de {1}", "label.noResults": "Sin resultados" } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/esn/src/vs/editor/contrib/find/common/findController.i18n.json index 2928bececec..27d384a1b68 100644 --- a/i18n/esn/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Buscar selección siguiente", "previousSelectionMatchFindAction": "Buscar selección anterior", "startReplace": "Reemplazar", - "addSelectionToNextFindMatch": "Agregar selección hasta la siguiente coincidencia de búsqueda", - "addSelectionToPreviousFindMatch": "Agregar selección hasta la anterior coincidencia de búsqueda", - "moveSelectionToNextFindMatch": "Mover última selección hasta la siguiente coincidencia de búsqueda", - "moveSelectionToPreviousFindMatch": "Mover última selección hasta la anterior coincidencia de búsqueda", - "selectAllOccurrencesOfFindMatch": "Seleccionar todas las repeticiones de coincidencia de búsqueda", - "changeAll.label": "Cambiar todas las ocurrencias", "showNextFindTermAction": "Mostrar el siguiente término de búsqueda", "showPreviousFindTermAction": "Mostrar término de búsqueda anterior" } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/esn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 13f4bac636a..d5994146753 100644 --- a/i18n/esn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Agregar cursor arriba", "mutlicursor.insertBelow": "Agregar cursor debajo", - "mutlicursor.insertAtEndOfEachLineSelected": "Añadir cursores a finales de línea" + "mutlicursor.insertAtEndOfEachLineSelected": "Añadir cursores a finales de línea", + "addSelectionToNextFindMatch": "Agregar selección hasta la siguiente coincidencia de búsqueda", + "addSelectionToPreviousFindMatch": "Agregar selección hasta la anterior coincidencia de búsqueda", + "moveSelectionToNextFindMatch": "Mover última selección hasta la siguiente coincidencia de búsqueda", + "moveSelectionToPreviousFindMatch": "Mover última selección hasta la anterior coincidencia de búsqueda", + "selectAllOccurrencesOfFindMatch": "Seleccionar todas las repeticiones de coincidencia de búsqueda", + "changeAll.label": "Cambiar todas las ocurrencias" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json index 91ed718d0ad..354ba1a82a9 100644 --- a/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Formato de color no válido. Use #TGB, #RBGA, #RRGGBB o #RRGGBBAA", "schema.colors": "Colores usados en el área de trabajo.", "foreground": "Color de primer plano general. Este color solo se usa si un componente no lo invalida.", "errorForeground": "Color de primer plano general para los mensajes de erroe. Este color solo se usa si un componente no lo invalida.", diff --git a/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 81bfd015f9e..fc9101aee18 100644 --- a/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "Agregar carpeta al área de trabajo...", "add": "&& Agregar", "addFolderToWorkspaceTitle": "Agregar carpeta al área de trabajo", + "globalRemoveFolderFromWorkspace": "Quitar carpeta del Área de trabajo...", "newWorkspace": "Nueva área de trabajo...", "select": "&&Seleccionar", "selectWorkspace": "Seleccionar carpetas para el área de trabajo", "removeFolderFromWorkspace": "Quitar carpeta del área de trabajo", + "openFolderSettings": "Abrir Configuración de carpeta", "saveWorkspaceAsAction": "Guardar área de trabajo como...", "save": "&&Guardar", "saveWorkspace": "Guardar área de trabajo", "openWorkspaceAction": "Abrir área de trabajo...", "openWorkspaceConfigFile": "Abrir archivo de configuración del área de trabajo", + "openFolderAsWorkspaceInNewWindow": "Abrir carpeta como Área de trabajo en una Nueva Ventana", "workspaceFolderPickerPlaceholder": "Seleccionar la carpeta del área de trabajo" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index bfe695f895b..66f040cada4 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Ocultar barra de actividades", - "activityBarAriaLabel": "Modificador de vista activa", "globalActions": "Acciones globales" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..bbaa4095de7 --- /dev/null +++ b/i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Modificador de vista activa" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..b8bb426ec85 --- /dev/null +++ b/i18n/esn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1} ", + "additionalViews": "Vistas adicionales", + "numberBadge": "{0} ({1})", + "manageExtension": "Administrar extensión", + "titleKeybinding": "{0} ({1})", + "toggle": "Alternar vista fijada" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index c5c13f08096..ae6d0079e4c 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "Mostrar editores del segundo grupo", "groupThreePicker": "Mostrar editores del tercer grupo", "allEditorsPicker": "Mostrar todos los editores abiertos", - "view": "Ver" + "view": "Ver", + "file": "Archivo" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 7dd9c672cbe..4f9bdabe15e 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "El comando \"{0}\" no está habilitado actualmente y no se puede ejecutar.", "manageExtension": "Administrar extensión" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json index 4655a5812be..20663bc3124 100644 --- a/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,15 @@ "workspaces": "Áreas de trabajo", "developer": "Desarrollador", "showEditorTabs": "Controla si los editores abiertos se deben mostrar o no en pestañas.", - "workbench.editor.labelFormat.default": "Mostrar el nombre del archivo. Cuando las pestañas están habilitadas y dos archivos tienen el mismo nombre en un grupo, se agregan las secciones distintivas de la ruta de acceso de cada archivo. Cuando las pestañas están deshabilitadas, se muestra la ruta de acceso relativa a la raíz del área de trabajo si el editor está activo.", "workbench.editor.labelFormat.short": "Mostrar el nombre del archivo seguido de su nombre de directorio.", - "workbench.editor.labelFormat.medium": "Mostrar el nombre del archivo seguido de la ruta de acceso relativo a la raíz del espacio de trabajo.", "workbench.editor.labelFormat.long": "Mostrar el nombre del archivo seguido de la ruta de acceso absoluta.", "tabDescription": "Controla el formato de la etiqueta para un editor. Modificar este ajuste puede hacer, por ejemplo, que sea más fácil entender la ubicación de un archivo: - corta: 'parent' - media: 'workspace/src/parent' - larga: '/home/user/workspace/src/parect' - por defecto: '.../parent', cuando otra pestaña comparte el mismo título, o la ruta de acceso relativa del espacio de trabajo si las pestañas están deshabilitadas", "editorTabCloseButton": "Controla la posición de los botones de cierre de pestañas del editor o los deshabilita si se establece en \"off\".", "showIcons": "Controla si los editores abiertos deben mostrarse o no con un icono. Requiere que también se habilite un tema de icono.", "enablePreview": "Controla si los editores abiertos se muestran en vista previa. Los editores en vista previa se reutilizan hasta que se guardan (por ejemplo, mediante doble clic o editándolos) y se muestran en cursiva.", "enablePreviewFromQuickOpen": "Controla si los editores abiertos mediante Quick Open se muestran en modo de vista previa. Los editores en modo de vista previa se reutilizan hasta que se conservan (por ejemplo, mediante doble clic o editándolos).", - "editorOpenPositioning": "Controla dónde se abren los editores. Seleccione 'izquierda' o 'derecha' para abrir los editores situados a la izquierda o la derecha del que está actualmente activo. Seleccione 'primero' o 'último' para abrir los editores con independencia del que esté actualmente activo.", "revealIfOpen": "Controla si un editor se muestra en alguno de los grupos visibles cuando se abre. Si se deshabilita esta opción, un editor preferirá abrirse en el grupo de editores activo en ese momento. Si se habilita, un editor ya abierto se mostrará en lugar de volver a abrirse en el grupo de editores activo. Tenga en cuenta que hay casos en los que esta opción se omite; por ejemplo, cuando se fuerza la apertura de un editor en un grupo específico o junto al grupo activo actual.", - "commandHistory": "Controla el número de comandos usados recientemente a almacenar en el historial para la paleta de comandos. Establezca a 0 para deshabilitar el historial de comandos.", + "commandHistory": "Controla el número de comandos utilizados recientemente que se mantendrán en el historial de la paleta de comandos. Establezca el valor a 0 para desactivar el historial de comandos.", "preserveInput": "Controla si la última entrada introducida en la paleta de comandos debería ser restaurada cuando sea abierta la próxima vez.", "closeOnFocusLost": "Controla si Quick Open debe cerrarse automáticamente cuando pierde el foco.", "openDefaultSettings": "Controla si la configuración de apertura también abre un editor que muestra todos los valores predeterminados.", @@ -50,7 +47,6 @@ "restoreWindows": "Controla cómo se vuelven a abrir las ventanas tras un reinicio. Seleccione \"none\" para comenzar siempre con un área de trabajo vacía, \"one\" para volver a abrir la última ventana en la que trabajó, \"folders\" para volver a abrir todas las ventanas que tenían carpetas abiertas o \"all\" para volver a abrir todas las ventanas de la última sesión.", "restoreFullscreen": "Controla si una ventana se debe restaurar al modo de pantalla completa si se salió de ella en dicho modo.", "zoomLevel": "Ajuste el nivel de zoom de la ventana. El tamaño original es 0 y cada incremento (por ejemplo, 1) o disminución (por ejemplo, -1) representa una aplicación de zoom un 20 % más grande o más pequeño. También puede especificar decimales para ajustar el nivel de zoom con una granularidad más precisa.", - "title": "Controla el título de la ventana según el editor activo. Las variables se sustituyen según el contexto:\n${activeEditorShort}: e.g. myFile.txt\n${activeEditorMedium}: e.g. myFolder/myFile.txt\n${activeEditorLong}: por ejemplo, /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: por ejemplo, myFolder\n${folderPath}: por ejemplo, /Users/Development/myFolder\n${rootName}: por ejemplo, myFolder1, myFolder2, myFolder3\n${rootPath}: por ejemplo, /Users/Development/myWorkspace\n${appName}: por ejemplo, VS Code\n${dirty}: un indicador con modificaciones si el editor activo está desfasado\n${separator}: separador condicional (\" - \") que solo se muestra cuando está rodeado de variables con valores", "window.newWindowDimensions.default": "Abrir las nuevas ventanas en el centro de la pantalla.", "window.newWindowDimensions.inherit": "Abrir las nuevas ventanas con la misma dimensión que la última activa.", "window.newWindowDimensions.maximized": "Abrir las nuevas ventanas maximizadas.", diff --git a/i18n/esn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index be6974deb6b..e9a982317e2 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, depurar", "debugAriaLabel": "Escriba un nombre de una configuración de inicio para ejecutar.", + "addConfigTo": "Agregar configuración ({0})...", + "addConfiguration": "Agregar configuración...", "noConfigurationsMatching": "No hay ninguna configuración de depuración coincidente", "noConfigurationsFound": "No se encontró ninguna configuración de inicio. Cree un archivo \"launch.json\"." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..7a6db36a29e --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Depurar" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index f4d25015e28..28c7690312b 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Configuraciones para generar el archivo \"launch.json\" inicial.", "vscode.extension.contributes.debuggers.languages": "Lista de lenguajes para los que la extensión de depuración podría considerarse el \"depurador predeterminado\".", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Si se especifica, VS Code llamará a este comando para determinar la ruta de acceso ejecutable del adaptador de depuración y los argumentos que se deben pasar.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Si se especifica, VS Code llamará a este comando para las acciones de \"depuración\" o \"ejecución\" destinadas para esta extensión.", "vscode.extension.contributes.debuggers.configurationSnippets": "Fragmentos de código para agregar nuevas configuraciones a \"launch.json\".", "vscode.extension.contributes.debuggers.configurationAttributes": "Configuraciones de esquema JSON para validar \"launch.json\".", "vscode.extension.contributes.debuggers.windows": "Configuración específica de Windows.", diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 39eca78322f..01b6c98e302 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,7 @@ "breakpointRemoved": "Punto de interrupción quitado, línea {0}, archivo {1}", "compoundMustHaveConfigurations": "El compuesto debe tener configurado el atributo \"configurations\" a fin de iniciar varias configuraciones.", "configMissing": "La configuración \"{0}\" falta en \"launch.json\".", - "debugRequestNotSupported": "La configuración de depuración seleccionada tiene un valor de atributo '{0}': '{1}' no compatible.", - "debugRequesMissing": "El atributo '{0}' está ausente en la configuración de depuración elegida.", "debugTypeNotSupported": "El tipo de depuración '{0}' configurado no es compatible.", - "debugTypeMissing": "Falta la propiedad \"type\" en la configuración de inicio seleccionada.", "preLaunchTaskErrors": "Errores de compilación durante la tarea preLaunchTask '{0}'.", "preLaunchTaskError": "Error de compilación durante la tarea preLaunchTask '{0}'.", "preLaunchTaskExitCode": "La tarea preLaunchTask '{0}' finalizó con el código de salida {1}.", diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index c71edc9f51f..29384cb26e7 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "El estado del objeto se captura desde la primera evaluación", "replVariableAriaLabel": "La variable {0} tiene el valor {1}, read–eval–print loop, depuración", "replExpressionAriaLabel": "La expresión {0} tiene el valor {1}, read–eval–print loop, depuración", - "replValueOutputAriaLabel": "{0}, read–eval–print loop, depuración", - "replKeyValueOutputAriaLabel": "La variable de salida {0} tiene el valor {1}, read–eval–print loop, depuración" + "replValueOutputAriaLabel": "{0}, read–eval–print loop, depuración" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index 9b4c0a6fb45..5b4f1d9a867 100644 --- a/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Archivos", + "filesCategory": "Archivo", "revealInSideBar": "Mostrar en barra lateral", "acceptLocalChanges": "Usar los cambios y sobrescribir el contenido del disco", "revertLocalChanges": "Descartar los cambios y volver al contenido del disco" diff --git a/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 836362af71e..5d9def6792e 100644 --- a/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "¿Está seguro de que desea eliminar '{0}'?", "undoBin": "Puede restaurar desde la papelera de reciclaje.", "undoTrash": "Puede restaurar desde la papelera.", + "doNotAskAgain": "No volver a preguntarme", "confirmDeleteMessageFolder": "¿Está seguro de que desea eliminar '{0}' y su contenido de forma permanente?", "confirmDeleteMessageFile": "¿Está seguro de que desea eliminar '{0}' de forma permanente?", "irreversible": "Esta acción es irreversible.", @@ -37,8 +38,6 @@ "openToSide": "Abrir en el lateral", "compareSource": "Seleccionar para comparar", "globalCompareFile": "Comparar archivo activo con...", - "pickHistory": "Seleccione un archivo abierto anteriormente para comparar", - "unableToFileToCompare": "El archivo seleccionado no se puede comparar con '{0}'.", "openFileToCompare": "Abrir un archivo antes para compararlo con otro archivo.", "compareWith": "Comparar \"{0}\" con \"{1}\"", "compareFiles": "Comparar archivos", @@ -47,7 +46,7 @@ "saveAs": "Guardar como...", "saveAll": "Guardar todos", "saveAllInGroup": "Guardar todo en el grupo", - "saveFiles": "Guardar archivos con modificaciones", + "saveFiles": "Guardar todos los archivos", "revert": "Revertir archivo", "focusOpenEditors": "Foco sobre la vista de editores abiertos", "focusFilesExplorer": "Enfocar Explorador de archivos", diff --git a/i18n/esn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/esn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index ed00449cce3..8857fa7d07b 100644 --- a/i18n/esn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,7 @@ { "noWorkspace": "No hay ninguna carpeta abierta", "explorerSection": "Sección del Explorador de archivos", - "noWorkspaceHelp": "Todavía no ha abierto ninguna carpeta.", + "noWorkspaceHelp": "Todavía no ha agregado una carpeta al espacio de trabajo.", + "noFolderHelp": "Todavía no ha abierto ninguna carpeta.", "openFolder": "Abrir carpeta" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/esn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index 7903df9c11b..40f9fcc3277 100644 --- a/i18n/esn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "No se puede resolver la carpeta {0}", "fileInputAriaLabel": "Escriba el nombre de archivo. Presione ENTRAR para confirmar o Esc para cancelar", "filesExplorerViewerAriaLabel": "{0}, Explorador de archivos", "dropFolders": "¿Quiere agregar las carpetas al área de trabajo?", "dropFolder": "¿Quiere agregar la carpeta al área de trabajo?", "addFolders": "&&Agregar carpetas", "addFolder": "&&Agregar carpeta", + "confirmMove": "¿Está seguro de que desea mover '{0}'?", "confirmOverwriteMessage": "'{0}' ya existe en la carpeta de destino. ¿Desea reemplazarlo?", "irreversible": "Esta acción es irreversible.", "replaceButtonLabel": "Reemplazar" diff --git a/i18n/esn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..710f5b027a0 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Problemas", + "tooltip.1": "1 problema en este fichero", + "tooltip.N": "{0} problemas en este fichero", + "markers.showOnFile": "Mostrar Errores y Advertencias en la carpeta y ficheros." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index ed5419507d3..da443e5daba 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Coloque aquí su configuración para sobrescribir la configuración predeterminada.", - "errorInvalidConfiguration": "No se puede escribir la configuración. Corrija los errores o advertencias del archivo y vuelva a intentarlo.", "emptyWorkspaceSettingsHeader": "Coloque aquí su configuración para sobrescribir la configuración de usuario.", "emptyFolderSettingsHeader": "Coloque aquí su configuración de carpeta para sobrescribir la que se especifica en la configuración de área de trabajo.", "defaultFolderSettingsTitle": "Configuración de carpeta predeterminada", diff --git a/i18n/esn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/esn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 5b11b46879d..e0012dd14f7 100644 --- a/i18n/esn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "El comando '{0}' no está habilitado en el contexto actual.", "recentlyUsed": "usado recientemente", "morecCommands": "otros comandos", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "No hay comandos coincidentes" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index c0de845ea64..4c8491b6c87 100644 --- a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "show previous change": "Mostrar el cambio anterior", + "show next change": "Mostrar el cambio siguiente", "editorGutterModifiedBackground": "Color de fondo del medianil del editor para las líneas modificadas.", "editorGutterAddedBackground": "Color de fondo del medianil del editor para las líneas agregadas.", "editorGutterDeletedBackground": "Color de fondo del medianil del editor para las líneas eliminadas.", diff --git a/i18n/esn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index a77598c77bc..d0eef49247f 100644 --- a/i18n/esn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,7 @@ "exclude": "Configure patrones globales para excluir archivos y carpetas de las búsquedas. Hereda todos los patrones globales de la configuración files.exclude.", "exclude.boolean": "El patrón global con el que se harán coincidir las rutas de acceso de los archivos. Establézcalo en true o false para habilitarlo o deshabilitarlo.", "exclude.when": "Comprobación adicional de los elementos del mismo nivel de un archivo coincidente. Use $(nombreBase) como variable para el nombre de archivo que coincide.", - "useRipgrep": "Controla si debe utilizarse ripgrep en la búsqueda de texto", + "useRipgrep": "Controla si se utiliza ripgrep en la búsqueda de texto y ficheros", "useIgnoreFilesByDefault": "Controla si usar los archivos .gitignore y .ignore de forma predeterminada al buscar en una nueva área de trabajo.", "search.quickOpen.includeSymbols": "Configurar para incluir los resultados de una búsqueda global de símbolos en los resultados de archivos de Quick Open." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 314acd5b6dd..572f519b892 100644 --- a/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Borrar resultados de la búsqueda", "FocusNextSearchResult.label": "Centrarse en el siguiente resultado de la búsqueda", "FocusPreviousSearchResult.label": "Centrarse en el anterior resultado de la búsqueda", - "RemoveAction.label": "Quitar", "file.replaceAll.label": "Reemplazar todo", "match.replace.label": "Reemplazar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 3353f89b68d..bc5073a75cf 100644 --- a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Aporta fragmentos de código.", "vscode.extension.contributes.snippets-language": "Identificador del lenguaje al que se aporta este fragmento de código.", "vscode.extension.contributes.snippets-path": "Ruta de acceso del archivo de fragmentos de código. La ruta es relativa a la carpeta de extensión y normalmente empieza por \"./snippets/\".", - "badFile": "No se pudo leer el archivo del fragmento \"{0}\".", "badVariableUse": "Es muy probable que el fragmento de código \"{0}\" confunda las variables de fragmento de código y los marcadores de posición de fragmento de código. Consulte https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax para más informacion.", + "badFile": "No se pudo leer el archivo del fragmento \"{0}\".", "source.snippet": "Fragmento de código del usuario", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index ad64a450cf5..50d2ca8b4b1 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -30,6 +30,7 @@ "TaskSystem.activeSame.noBackground": "La tarea \"{0}\" ya está activa. Para terminarla, use la opción \"Terminar tarea\" del menú Tareas.", "TaskSystem.active": "Ya hay una tarea en ejecución. Finalícela antes de ejecutar otra tarea.", "TaskSystem.restartFailed": "No se pudo terminar y reiniciar la tarea {0}", + "TaskService.noConfiguration": "Error: La detección de tarea {0} no encontró una tarea para la siguiente configuración:\n{1}\nLa tarea será omitida.\n", "TaskSystem.configurationErrors": "Error: La configuración de la tarea proporcionada tiene errores de validación y no se puede usar. Corrija los errores primero.", "taskService.ignoreingFolder": "Ignorando las configuraciones de tarea para la carpeta del area de trabajo {0}. El soporte de tarea de area de trabajo multi carpeta requiere que todas las carpetas usen la versión de tarea 2.0.0 ", "TaskSystem.invalidTaskJson": "Error: El contenido del archivo tasks.json tiene errores de sintaxis. Corríjalos antes de ejecutar una tarea.", diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 2fb25c70d99..c3d0cfd1e37 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Nuevo terminal", "workbench.action.terminal.focus": "Enfocar terminal", "workbench.action.terminal.focusNext": "Enfocar terminal siguiente", - "workbench.action.terminal.focusAtIndex": "Enfocar terminal {0}", "workbench.action.terminal.focusPrevious": "Enfocar terminal anterior", "workbench.action.terminal.paste": "Pegar en el terminal activo", "workbench.action.terminal.DefaultShell": "Seleccionar el shell predeterminado", diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 1b04639ccd5..a2ea49d47f1 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Copiar", - "createNewTerminal": "Nuevo terminal", "paste": "Pegar", "selectAll": "Seleccionar todo", "clear": "Borrar" diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 6b1dbc4c66a..1a5374df014 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "De acuerdo, no volver a mostrar este mensaje", "terminal.integrated.chooseWindowsShell": "Seleccione el shell de terminal que desee, puede cambiarlo más adelante en la configuración", "terminalService.terminalCloseConfirmationSingular": "Hay una sesión de terminal activa, ¿quiere terminarla?", - "terminalService.terminalCloseConfirmationPlural": "Hay {0} sesiones de terminal activas, ¿quiere terminarlas?", - "yes": "Sí" + "terminalService.terminalCloseConfirmationPlural": "Hay {0} sesiones de terminal activas, ¿quiere terminarlas?" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..38c0dd3726b --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Resumen de la configuración. Esta etiqueta se usará en el archivo de configuración como comentario divisor.", + "vscode.extension.contributes.configuration.properties": "Descripción de las propiedades de configuración.", + "scope.window.description": "Configuración específica para ventanas, que se puede definir en la configuración de usuario o de área de trabajo.", + "scope.resource.description": "Configuración específica para recursos, que se puede definir en la configuración de usuario, de área de trabajo o de carpeta.", + "scope.description": "Ámbito donde es aplicable la configuración. Los ámbitos disponibles son \"window\" y \"resource\".", + "vscode.extension.contributes.configuration": "Aporta opciones de configuración.", + "invalid.title": "configuration.title debe ser una cadena", + "vscode.extension.contributes.defaultConfiguration": "Contribuye a la configuración de los parámetros del editor predeterminados por lenguaje.", + "invalid.properties": "configuration.properties debe ser un objeto", + "workspaceConfig.folders.description": "Lista de carpetas para cargar en el área de trabajo. ", + "workspaceConfig.path.description": "Ruta de acceso de archivo; por ejemplo, \"/raíz/carpetaA\" o \"./carpetaA\" para una ruta de acceso de archivo que se resolverá respecto a la ubicación del archivo del área de trabajo.", + "workspaceConfig.settings.description": "Configuración de área de trabajo", + "workspaceConfig.extensions.description": "Extensiones del área de trabajo", + "unknownWorkspaceProperty": "Propiedad de configuración de espacio de trabajo desconocida" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/esn/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/esn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..5be27841f5b --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contributes textmate color themes.", + "vscode.extension.contributes.themes.id": "Identificador del tema de icono como se usa en la configuración de usuario.", + "vscode.extension.contributes.themes.label": "Etiqueta del tema de color tal como se muestra en la interfaz de usuario.", + "vscode.extension.contributes.themes.uiTheme": "Tema base que define los colores que se usan en el editor: 'vs' es el tema de color claro, 'vs-dark' es el tema de color oscuro, 'hc-black' es el tema oscuro de alto contraste.", + "vscode.extension.contributes.themes.path": "Ruta de acceso del archivo tmTheme. La ruta de acceso es relativa a la carpeta de extensión y suele ser './themes/themeFile.tmTheme'.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "Se esperaba una cadena en \"contributes.{0}.path\". Valor proporcionado: {1}", + "invalid.path.1": "Se esperaba que \"contributes.{0}.path\" ({1}) se incluyera en la carpeta de la extensión ({2}). Esto puede hacer que la extensión no sea portátil." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..b0f9faf6b52 --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problems parsing file icons file: {0}" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..541e0ac3d8b --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "Identificador del tema de icono como se usa en la configuración de usuario.", + "vscode.extension.contributes.iconThemes.label": "Etiqueta del tema de icono como se muestra en la interfaz de usuario.", + "vscode.extension.contributes.iconThemes.path": "Ruta de acceso del archivo de definición de temas de icono. La ruta de acceso es relativa a la carpeta de extensión y suele ser './icons/awesome-icon-theme.json'.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "Se esperaba una cadena en \"contributes.{0}.path\". Valor proporcionado: {1}", + "reqid": "Se esperaba una cadena en `contributes.{0}.id`. Valor proporcionado: {1}", + "invalid.path.1": "Se esperaba que \"contributes.{0}.path\" ({1}) se incluyera en la carpeta de la extensión ({2}). Esto puede hacer que la extensión no sea portátil." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 7c308f9717e..cb85af9d3cd 100644 --- a/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "Identificador del tema de icono como se usa en la configuración de usuario.", - "vscode.extension.contributes.themes.label": "Etiqueta del tema de color tal como se muestra en la interfaz de usuario.", - "vscode.extension.contributes.themes.uiTheme": "Tema base que define los colores que se usan en el editor: 'vs' es el tema de color claro, 'vs-dark' es el tema de color oscuro, 'hc-black' es el tema oscuro de alto contraste.", - "vscode.extension.contributes.themes.path": "Ruta de acceso del archivo tmTheme. La ruta de acceso es relativa a la carpeta de extensión y suele ser './themes/themeFile.tmTheme'.", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "Identificador del tema de icono como se usa en la configuración de usuario.", - "vscode.extension.contributes.iconThemes.label": "Etiqueta del tema de icono como se muestra en la interfaz de usuario.", - "vscode.extension.contributes.iconThemes.path": "Ruta de acceso del archivo de definición de temas de icono. La ruta de acceso es relativa a la carpeta de extensión y suele ser './icons/awesome-icon-theme.json'.", "migration.completed": "Se han agregado nuevos valores de tema a la configuración de usuario. Hay una copia de seguridad disponible en {0}.", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "Se esperaba una cadena en \"contributes.{0}.path\". Valor proporcionado: {1}", - "invalid.path.1": "Se esperaba que \"contributes.{0}.path\" ({1}) se incluyera en la carpeta de la extensión ({2}). Esto puede hacer que la extensión no sea portátil.", - "reqid": "Se esperaba una cadena en `contributes.{0}.id`. Valor proporcionado: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "Especifica el tema de icono utilizado en el área de trabajo o \"null\" para no mostrar ningún icono de archivo.", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Reemplaza los colores del tema de color actual", - "workbenchColors.deprecated": "Esta configuracion no es experimental y se ha cambiado de nombre a 'workbench.colorCustomizations'", - "workbenchColors.deprecatedDescription": "Utilice 'workbench.colorCustomizations' en su lugar", "editorColors": "Reemplaza los colores y el estilo de fuente del editor del tema de color seleccionado.", "editorColors.comments": "Establece los colores y estilos para los comentarios", "editorColors.strings": "Establece los colores y estilos para los literales de cadena.", diff --git a/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..17798aeb3c8 --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Abrir archivo de configuración del área de trabajo", + "close": "Cerrar" +} \ No newline at end of file diff --git a/i18n/fra/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/fra/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index fcedce53b3c..c8334701a65 100644 --- a/i18n/fra/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/fra/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "exemple : myFile.txt", - "activeEditorMedium": "exemple : myFolder/myFile.txt", - "activeEditorLong": "exemple : /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "par ex., myFolder1, myFolder2, myFolder3", - "rootPath": "exemple : /Users/Development/myProject", - "folderName": "par ex., myFolder", - "folderPath": "par ex., /Users/Development/myFolder", + "activeEditorShort": "le nom du fichier (ex: monfichier.txt)", + "activeEditorMedium": "le chemin d’accès du fichier relatif au dossier de l’espace de travail (ex: myFolder/myFile.txt)", + "activeEditorLong": "le chemin d’accès complet du fichier (ex: /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "nom de l’espace de travail (ex: monDossier ou monEspaceDeTravail)", + "rootPath": "chemin d’accès de l’espace de travail (ex: /Users/Development/myWorkspace)", + "folderName": "nom du dossier de l'espace de travail auquel le fichier appartient (ex: monDossier)", + "folderPath": "chemin d’accès du dossier de l'espace de travail auquel le fichier appartient (ex: /Users/Development/myFolder)", "appName": "exemple : VS Code", "dirty": "indicateur d'intégrité si l'intégrité de l'éditeur actif est compromise", "separator": "séparateur conditionnel (' - ') qui s'affiche uniquement quand il est entouré de variables avec des valeurs", diff --git a/i18n/fra/extensions/emmet/package.i18n.json b/i18n/fra/extensions/emmet/package.i18n.json index d9a0b979e40..3136f6135aa 100644 --- a/i18n/fra/extensions/emmet/package.i18n.json +++ b/i18n/fra/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Incrémenter de 10", "command.decrementNumberByTen": "Décrémenter de 10", "emmetSyntaxProfiles": "Définissez le profil pour la syntaxe spécifiée ou utilisez votre propre profil avec des règles spécifiques.", - "emmetExclude": "Ensemble de langages où les abréviations emmet ne doivent pas être développées.", - "emmetExtensionsPath": "Chemin d'un dossier contenant les profils et les extraits Emmet.", - "emmetShowExpandedAbbreviation": "Affiche les abréviations Emmet développées sous forme de suggestions.\nL’option \"inMarkupAndStylesheetFilesOnly\" s’applique à html, haml, jade, slim, xml, xsl, css, scss, sass, less et un stylet.\nL’option \"toujours\" s’applique à toutes les parties du fichier indépendamment du balisage/css.", - "emmetShowAbbreviationSuggestions": "Affiche les abréviations Emmet possibles sous forme de suggestions. Non applicable dans les feuilles de style ou quand emmet.showExpandedAbbreviation est défini sur \"jamais\".", - "emmetIncludeLanguages": "Active les abréviations Emmet dans les langages qui ne sont pas pris en charge par défaut. Ajoute un mappage ici entre le langage et le langage Emmet pris en charge .\n Par exemple : {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Variables à utiliser dans les extraits Emmet", - "emmetTriggerExpansionOnTab": "Une fois les abréviations Emmet activées, elles se développent quand vous appuyez sur la touche Tab.", "emmetPreferences": "Préférences utilisées pour modifier le comportement de certaines actions et résolveurs d'Emmet.", "emmetPreferencesIntUnit": "Unité par défaut pour les valeurs entières", "emmetPreferencesFloatUnit": "Unité par défaut pour les valeurs float", @@ -44,5 +37,7 @@ "emmetPreferencesCssBetween": "Symbole à placer entre la propriété CSS et la valeur pendant le développement des abréviations CSS", "emmetPreferencesSassBetween": "Symbole à placer entre la propriété CSS et la valeur pendant le développement des abréviations CSS dans les fichiers Sass", "emmetPreferencesStylusBetween": "Symbole à placer entre la propriété CSS et la valeur pendant le développement des abréviations CSS dans les fichiers Stylus", - "emmetShowSuggestionsAsSnippets": "Si la valeur est True, les suggestions Emmet s'affichent sous forme d'extraits, ce qui vous permet de les ordonner conformément au paramètre editor.snippetSuggestions." + "emmetPreferencesFilterCommentBefore": "Une définition de commentaire qui doit être placée avant l’élément correspondant quand le filtre de commentaire est appliqué.", + "emmetPreferencesFilterCommentAfter": "Une définition de commentaire qui doit être placée après l’élément correspondant quand un filtre de commentaire est appliqué.", + "emmetPreferencesFilterCommentTrigger": "Une liste séparée par des virgules de noms d’attributs qui devraient exister en abrégé pour que le filtre de commentaire soit appliqué" } \ No newline at end of file diff --git a/i18n/fra/extensions/git/out/commands.i18n.json b/i18n/fra/extensions/git/out/commands.i18n.json index 72e09a4dac2..e0dab3e5a12 100644 --- a/i18n/fra/extensions/git/out/commands.i18n.json +++ b/i18n/fra/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Clonage du dépôt git...", "openrepo": "Ouvrir le dépôt", "proposeopen": "Voulez-vous ouvrir le dépôt cloné ?", - "path to init": "Chemin du dossier", - "provide path": "Veuillez fournir un chemin de dossier pour initialiser un dépôt Git", + "init repo": "Initialiser le dépôt", + "create repo": "Initialiser le dépôt", + "are you sure": "Ceci va créer un dépôt Git dans '{0}'. Êtes-vous sûr de vouloir continuer ?", "HEAD not available": "La version HEAD de '{0}' n'est pas disponible.", "confirm stage files with merge conflicts": "Voulez-vous vraiment créer {0} fichiers avec des conflits de fusion ?", "confirm stage file with merge conflicts": "Voulez-vous vraiment créer {0} avec des conflits de fusion ?", diff --git a/i18n/fra/extensions/git/out/repository.i18n.json b/i18n/fra/extensions/git/out/repository.i18n.json index 75b81935d06..9f5e062bdb0 100644 --- a/i18n/fra/extensions/git/out/repository.i18n.json +++ b/i18n/fra/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Supprimé par nos soins", "both added": "Tous deux ajoutés", "both modified": "Tous deux modifiés", + "untracked, short": "U", + "modified, short": "M", "commit": "Commit", "merge changes": "Fusionner les modifications", "staged changes": "Modifications en zone de transit", diff --git a/i18n/fra/extensions/git/package.i18n.json b/i18n/fra/extensions/git/package.i18n.json index 6253e6cf5fe..e5008fa48da 100644 --- a/i18n/fra/extensions/git/package.i18n.json +++ b/i18n/fra/extensions/git/package.i18n.json @@ -15,6 +15,8 @@ "command.stageAll": "Mettre en attente toutes les modifications", "command.stageSelectedRanges": "Mettre en attente les plages sélectionnées", "command.revertSelectedRanges": "Restaurer les portées sélectionnées", + "command.stageChange": "Mettre en attente la modification", + "command.revertChange": "Restaurer la modification", "command.unstage": "Annuler la mise en attente des modifications", "command.unstageAll": "Annuler la mise en attente de toutes les modifications", "command.unstageSelectedRanges": "Annuler la mise en attente des plages sélectionnées", diff --git a/i18n/fra/extensions/typescript/package.i18n.json b/i18n/fra/extensions/typescript/package.i18n.json index 8762fa61f04..848e776f0d6 100644 --- a/i18n/fra/extensions/typescript/package.i18n.json +++ b/i18n/fra/extensions/typescript/package.i18n.json @@ -44,7 +44,8 @@ "typescript.npm": "Spécifie le chemin de l'exécutable NPM utilisé pour l'acquisition de type automatique. Nécessite TypeScript >= 2.3.4.", "typescript.check.npmIsInstalled": "Vérifie si NPM est installé pour l'acquisition de type automatique.", "javascript.nameSuggestions": "Activez/désactivez l'inclusion de noms uniques à partir du fichier dans les listes de suggestions JavaScript.", - "typescript.tsc.autoDetect": "Contrôle si la détection automatique des tâches tsc est activée ou désactivée.", + "typescript.tsc.autoDetect": "Contrôle la détection automatique des tâches tsc. 'off' désactive cette fonctionnalité. 'build' crée uniquement des tâches de compilation à exécution unique. 'watch' crée uniquement des tâches de compilation et de watch. 'on' crée les deux les tâches build et watch. La valeur par défaut est 'on'.", "typescript.problemMatchers.tsc.label": "Problèmes liés à TypeScript", - "typescript.problemMatchers.tscWatch.label": "Problèmes liés à TypeScript (mode espion)" + "typescript.problemMatchers.tscWatch.label": "Problèmes liés à TypeScript (mode espion)", + "typescript.quickSuggestionsForPaths": "Activer/désactiver les suggestions rapides lorsque vous saisissez un chemin d’import." } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/fra/src/vs/editor/contrib/find/browser/findWidget.i18n.json index e6ecb5ce261..35e6cb71d88 100644 --- a/i18n/fra/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Remplacer", "label.replaceAllButton": "Tout remplacer", "label.toggleReplaceButton": "Changer le mode de remplacement", - "title.matchesCountLimit": "Seuls les 999 premiers résultats sont mis en surbrillance. Cependant, toutes les opérations de recherche sont appliquées à l'ensemble du texte.", "label.matchesLocation": "{0} sur {1}", "label.noResults": "Aucun résultat" } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/fra/src/vs/editor/contrib/find/common/findController.i18n.json index 2176cea208c..21889b4123e 100644 --- a/i18n/fra/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Sélection suivante", "previousSelectionMatchFindAction": "Sélection précédente", "startReplace": "Remplacer", - "addSelectionToNextFindMatch": "Ajouter la sélection à la correspondance de recherche suivante", - "addSelectionToPreviousFindMatch": "Ajouter la sélection à la correspondance de recherche précédente", - "moveSelectionToNextFindMatch": "Déplacer la dernière sélection vers la correspondance de recherche suivante", - "moveSelectionToPreviousFindMatch": "Déplacer la dernière sélection à la correspondance de recherche précédente", - "selectAllOccurrencesOfFindMatch": "Sélectionner toutes les occurrences des correspondances de la recherche", - "changeAll.label": "Modifier toutes les occurrences", "showNextFindTermAction": "Afficher le terme de recherche suivant", "showPreviousFindTermAction": "Afficher le terme de recherche précédent" } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/fra/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 081fbcf0bec..04e943155da 100644 --- a/i18n/fra/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Ajouter un curseur au-dessus", "mutlicursor.insertBelow": "Ajouter un curseur en dessous", - "mutlicursor.insertAtEndOfEachLineSelected": "Ajouter des curseurs à la fin des lignes" + "mutlicursor.insertAtEndOfEachLineSelected": "Ajouter des curseurs à la fin des lignes", + "addSelectionToNextFindMatch": "Ajouter la sélection à la correspondance de recherche suivante", + "addSelectionToPreviousFindMatch": "Ajouter la sélection à la correspondance de recherche précédente", + "moveSelectionToNextFindMatch": "Déplacer la dernière sélection vers la correspondance de recherche suivante", + "moveSelectionToPreviousFindMatch": "Déplacer la dernière sélection à la correspondance de recherche précédente", + "selectAllOccurrencesOfFindMatch": "Sélectionner toutes les occurrences des correspondances de la recherche", + "changeAll.label": "Modifier toutes les occurrences" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json index 1c47e156e38..2cfa0fbeab4 100644 --- a/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Format de couleur non valide. Utilisez #RGB, #RGBA, #RRGGBB ou #RRGGBBAA", "schema.colors": "Couleurs utilisées dans le banc d'essai.", "foreground": "Couleur de premier plan globale. Cette couleur est utilisée si elle n'est pas remplacée par un composant.", "errorForeground": "Couleur principale de premier plan pour les messages d'erreur. Cette couleur est utilisée uniquement si elle n'est pas redéfinie par un composant.", diff --git a/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 857489eaa8f..778330402d3 100644 --- a/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "Ajouter un dossier à l'espace de travail...", "add": "&&Ajouter", "addFolderToWorkspaceTitle": "Ajouter un dossier à l'espace de travail", + "globalRemoveFolderFromWorkspace": "Supprimer le dossier d’espace de travail...", "newWorkspace": "Nouvel espace de travail...", "select": "&&Sélectionner", "selectWorkspace": "Sélectionner les dossiers pour l’espace de travail", "removeFolderFromWorkspace": "Supprimer le dossier de l'espace de travail", + "openFolderSettings": "Ouvrir le dossier Paramètres", "saveWorkspaceAsAction": "Enregistrer l’espace de travail sous...", "save": "&&Enregistrer", "saveWorkspace": "Enregistrer l’espace de travail", "openWorkspaceAction": "Ouvrir un espace de travail...", "openWorkspaceConfigFile": "Ouvrir le Fichier de Configuration d’espace de travail", + "openFolderAsWorkspaceInNewWindow": "Ouvrir le dossier en tant qu'espace de travail dans une nouvelle fenêtre", "workspaceFolderPickerPlaceholder": "Sélectionner le dossier de l’espace de travail" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index a04b897abfe..affef8547e2 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Masquer la barre d'activités", - "activityBarAriaLabel": "Sélecteur d'affichage actif", "globalActions": "Actions globales" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..ed052dd9d9c --- /dev/null +++ b/i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Sélecteur d'affichage actif" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..0935a1bd196 --- /dev/null +++ b/i18n/fra/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "Vues supplémentaires", + "numberBadge": "{0} ({1})", + "manageExtension": "Gérer l'extension", + "titleKeybinding": "{0} ({1})", + "toggle": "Afficher/masquer la vue épinglée" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index dc32ce2159e..4326e29e9e4 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "Afficher les éditeurs du deuxième groupe", "groupThreePicker": "Afficher les éditeurs du troisième groupe", "allEditorsPicker": "Afficher tous les éditeurs ouverts", - "view": "Affichage" + "view": "Affichage", + "file": "Fichier" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 6e9f1b4185b..d4a3eda558a 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "La commande '{0}' n'est pas activée et ne peut pas être exécutée.", "manageExtension": "Gérer l'extension" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json index de18c2da7d0..32259e528e6 100644 --- a/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,15 @@ "workspaces": "Espaces de travail", "developer": "Développeur", "showEditorTabs": "Contrôle si les éditeurs ouverts doivent s'afficher ou non sous des onglets.", - "workbench.editor.labelFormat.default": "Affiche le nom du fichier. Lorsque les onglets sont activés et deux fichiers portent le même nom dans un groupe les sections distinctes du chemin de chaque fichier sont ajoutées. Lorsque les onglets sont désactivées, le chemin relatif à la racine d’espace de travail est affiché si l’éditeur est actif.", "workbench.editor.labelFormat.short": "Indiquer le nom du fichier suivi de son nom de répertoire.", - "workbench.editor.labelFormat.medium": "Indiquer le nom du fichier suivi de son chemin d’accès relatif à la racine de l’espace de travail.", "workbench.editor.labelFormat.long": "Indiquer le nom du fichier suivi de son chemin d’accès absolu.", "tabDescription": "Contrôle le format de l’étiquette d’un éditeur. La modification de ce paramètre peut par exemple rendre plus facile la compréhension de l’emplacement d’un fichier :\n- short: 'parent'\n- medium: 'workspace/src/parent'\n- long: '/home/user/workspace/src/parent'\n- default: '.../parent', quand un autre onglet partage le même titre, ou la chemin d’accès relatif à l'espace de travail si les onglets sont désactivés", "editorTabCloseButton": "Contrôle la position des boutons de fermeture des onglets de l'éditeur, ou les désactive quand le paramètre a la valeur 'off'.", "showIcons": "Contrôle si les éditeurs ouverts doivent s'afficher ou non avec une icône. Cela implique notamment l'activation d'un thème d'icône.", "enablePreview": "Contrôle si les éditeurs ouverts s'affichent en mode aperçu. Les éditeurs en mode aperçu sont réutilisés jusqu'à ce qu'ils soient conservés (par exemple, après un double-clic ou une modification) et apparaissent avec un style de police en italique.", "enablePreviewFromQuickOpen": "Contrôle si les éditeurs de Quick Open s'affichent en mode aperçu. Les éditeurs en mode aperçu sont réutilisés jusqu'à ce qu'ils soient conservés (par exemple, après un double-clic ou une modification).", - "editorOpenPositioning": "Contrôle l'emplacement de l'ouverture des éditeurs. Sélectionnez 'left' ou 'right' pour ouvrir les éditeurs à gauche ou à droite de l'éditeur actuellement actif. Sélectionnez 'first' ou 'last' pour ouvrir les éditeurs indépendamment de l'éditeur actuellement actif.", "revealIfOpen": "Contrôle si un éditeur est affiché dans l'un des groupes visibles, s'il est ouvert. Si cette option est désactivée, l'éditeur s'ouvre de préférence dans le groupe d'éditeurs actif. Si cette option est activée, tout éditeur déjà ouvert est affiché au lieu d'être rouvert dans le groupe d'éditeurs actif. Notez que dans certains cas, ce paramètre est ignoré, par exemple quand vous forcez un éditeur à s'ouvrir dans un groupe spécifique ou à côté du groupe actif.", - "commandHistory": "Contrôle le nombre de commandes récemment utilisées à conserver dans l'historique de la palette de commandes. Définissez cette valeur sur 0 pour désactiver l'historique de commandes.", + "commandHistory": "Contrôle le nombre de commandes récemment utilisées à retenir dans l’historique de la palette de commande. Spécifier la valeur 0 pour désactiver l’historique des commandes.", "preserveInput": "Contrôle si la dernière entrée tapée dans la palette de commandes doit être restaurée à la prochaine ouverture.", "closeOnFocusLost": "Contrôle si Quick Open doit se fermer automatiquement, une fois qu'il a perdu le focus.", "openDefaultSettings": "Contrôle si l'ouverture des paramètres entraîne également l'ouverture d'un éditeur qui affiche tous les paramètres par défaut.", @@ -50,7 +47,7 @@ "restoreWindows": "Contrôle comment les fenêtres seront rouvertes après un redémarrage. Sélectionner 'none' pour toujours démarrer avec un espace de travail vide, 'one' pour rouvrir la dernière fenêtre avec laquelle vous avez travaillé, 'folders' pour rouvrir toutes les fenêtres qui avaient des dossiers ouverts ou 'all' pour rouvrir toutes les fenêtres de votre dernière session.", "restoreFullscreen": "Contrôle si une fenêtre doit être restaurée en mode plein écran si elle a été fermée dans ce mode.", "zoomLevel": "Modifiez le niveau de zoom de la fenêtre. La taille d'origine est 0. Chaque incrément supérieur (exemple : 1) ou inférieur (exemple : -1) représente un zoom 20 % plus gros ou plus petit. Vous pouvez également entrer des décimales pour changer le niveau de zoom avec une granularité plus fine.", - "title": "Contrôle le titre de la fenêtre en fonction de l'éditeur actif. Les variables sont remplacées selon le contexte :\n${activeEditorShort} : par ex., myFile.txt\n${activeEditorMedium} : par ex., myFolder/myFile.txt\n${activeEditorLong} : par ex., /Users/Development/myProject/myFolder/myFile.txt\n${folderName} : par ex., myFolder\n${folderPath} : par ex., /Users/Development/myFolder\n${rootName} : par ex., myFolder1, myFolder2, myFolder3\n${rootPath} : par ex., /Users/Development/myWorkspace\n${appName} : par ex., VS Code\n${dirty} : indicateur d'intégrité si l'intégrité de l'éditeur actif est compromise\n${separator} : séparateur conditionnel (\" - \") qui s'affiche uniquement quand il est entouré de variables avec des valeurs", + "title": "Contrôle le titre de la fenêtre en fonction sur l’éditeur actif. Les variables sont remplacés selon le contexte : ${activeEditorShort} : le nom du fichier (ex: monFichier.txt) ${activeEditorMedium} : le chemin d’accès au fichier par rapport au dossier de l’espace de travail (ex: monDossier/monFichier.txt) ${activeEditorLong} : le chemin d’accès complet du fichier (par exemple / Users/Developpement/monDossier/monFichier.txt) ${folderName} : nom du dossier de l’espace de travail auquel le fichier appartient (ex: mondossier) ${folderPath} : chemin d’accès du dossier de l'espace de travail auquel le fichier appartient (ex: /Users/Developpement/monDossier) {$ rootName} : nom de l’espace de travail (:. monDossier ou monEspaceDeTravail) ${rootPath} : chemin d’accès de l’espace de travail (ex: /Users/Developpement/monEspaceDeTravail) ${appName} : ex. VS Code ${dirty} : un indicateur si l’éditeur actif est modifié ${separator} : un séparateur conditionnel (\" - \") qui ne s'affiche que quand ils sont entourés par des variables avec des valeurs", "window.newWindowDimensions.default": "Permet d'ouvrir les nouvelles fenêtres au centre de l'écran.", "window.newWindowDimensions.inherit": "Permet d'ouvrir les nouvelles fenêtres avec la même dimension que la dernière fenêtre active.", "window.newWindowDimensions.maximized": "Permet d'ouvrir les nouvelles fenêtres de manière agrandie.", diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 30c636b7769..914334d0401 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, débogage", "debugAriaLabel": "Tapez le nom d'une configuration de lancement à exécuter.", + "addConfigTo": "Ajouter une configuration ({0})...", + "addConfiguration": "Ajouter une configuration...", "noConfigurationsMatching": "Aucune configuration de débogage correspondante", "noConfigurationsFound": "Configurations de débogage introuvables. Créez un fichier 'launch.json'." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..449ccd606fe --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Déboguer" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..9782a892c46 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debugFocusVariablesView": "Focus sur les Variables", + "debugFocusWatchView": "Focus sur Watch", + "debugFocusCallStackView": "Focus sur CallStack", + "debugFocusBreakpointsView": "Focus sur les points d'arrêts" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 8a1e2b50d5f..5a3987eaa76 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Configurations pour la génération du fichier 'launch.json' initial.", "vscode.extension.contributes.debuggers.languages": "Liste de langages pour lesquels l'extension de débogage peut être considérée comme \"débogueur par défaut\".", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Si l'extension VS Code spécifiée appelle cette commande pour déterminer le chemin de l'exécutable de l'adaptateur de débogage et les arguments à passer.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Si l'extension VS Code spécifiée appelle cette commande pour les actions \"debug\" ou \"run\" ciblées pour cette extension.", "vscode.extension.contributes.debuggers.configurationSnippets": "Extraits pour l'ajout de nouvelles configurations à 'launch.json'.", "vscode.extension.contributes.debuggers.configurationAttributes": "Configurations de schéma JSON pour la validation de 'launch.json'.", "vscode.extension.contributes.debuggers.windows": "Paramètres spécifiques à Windows.", diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index d8dbd301b65..a5a92077a68 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,10 @@ "breakpointRemoved": "Point d'arrêt supprimé, ligne {0}, fichier {1}", "compoundMustHaveConfigurations": "L'attribut \"configurations\" du composé doit être défini pour permettre le démarrage de plusieurs configurations.", "configMissing": "Il manque la configuration '{0}' dans 'launch.json'.", - "debugRequestNotSupported": "La configuration de débogage choisie a une valeur d’attribut non prise en charge `{0}` : `{1}`.", - "debugRequesMissing": "L’attribut `{0}` est introuvable dans la configuration de débogage choisie.", + "debugRequestNotSupported": "L’attribut '{0}' a une valeur '{1}' non prise en charge dans la configuration de débogage sélectionnée.", + "debugRequesMissing": "L’attribut '{0}' est introuvable dans la configuration de débogage sélectionnée.", "debugTypeNotSupported": "Le type de débogage '{0}' configuré n'est pas pris en charge.", - "debugTypeMissing": "Propriété 'type' manquante pour la configuration de lancement choisie.", + "debugTypeMissing": "La propriété 'type' est manquante pour la configuration de lancement sélectionnée.", "preLaunchTaskErrors": "Des erreurs de build ont été détectées durant le preLaunchTask '{0}'.", "preLaunchTaskError": "Une erreur de build a été détectée durant le preLaunchTask '{0}'.", "preLaunchTaskExitCode": "Le preLaunchTask '{0}' s'est terminé avec le code de sortie {1}.", diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 9fa5e84fe4a..93c9076aca7 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -8,5 +8,5 @@ "replVariableAriaLabel": "La variable {0} a la valeur {1}, boucle REPL (Read Eval Print Loop), débogage", "replExpressionAriaLabel": "L'expression {0} a la valeur {1}, boucle REPL (Read Eval Print Loop), débogage", "replValueOutputAriaLabel": "{0}, boucle REPL (Read Eval Print Loop), débogage", - "replKeyValueOutputAriaLabel": "La variable de sortie {0} a la valeur {1}, boucle REPL (Read Eval Print Loop), débogage" + "replRawObjectAriaLabel": "La variable Repl {0} a la valeur {1}, read eval print loop, débogage" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index 2a8a3d2e72c..c0057e5215c 100644 --- a/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Fichiers", + "filesCategory": "Fichier", "revealInSideBar": "Afficher dans la barre latérale", "acceptLocalChanges": "Utiliser vos modifications et écraser les contenus du disque", "revertLocalChanges": "Ignorer les modifications et revenir au contenu sur le disque" diff --git a/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 78b61033acc..05c3150dcf4 100644 --- a/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "Voulez-vous vraiment supprimer '{0}' ?", "undoBin": "Vous pouvez effectuer une restauration à partir de la Corbeille.", "undoTrash": "Vous pouvez effectuer une restauration à partir de la Poubelle.", + "doNotAskAgain": "Ne plus me demander", "confirmDeleteMessageFolder": "Voulez-vous vraiment supprimer définitivement '{0}' et son contenu ?", "confirmDeleteMessageFile": "Voulez-vous vraiment supprimer définitivement '{0}' ?", "irreversible": "Cette action est irréversible !", @@ -37,8 +38,6 @@ "openToSide": "Ouvrir sur le côté", "compareSource": "Sélectionner pour comparer", "globalCompareFile": "Comparer le fichier actif à...", - "pickHistory": "Sélectionnez un fichier ouvert à comparer", - "unableToFileToCompare": "Impossible de comparer le fichier sélectionné à '{0}'.", "openFileToCompare": "Ouvrez d'abord un fichier pour le comparer à un autre fichier.", "compareWith": "Comparer '{0}' à '{1}'", "compareFiles": "Comparer des fichiers", @@ -47,7 +46,7 @@ "saveAs": "Enregistrer sous...", "saveAll": "Enregistrer tout", "saveAllInGroup": "Enregistrer tout dans le groupe", - "saveFiles": "Enregistrer les fichiers à l'intégrité compromise", + "saveFiles": "Enregistrer tous les fichiers", "revert": "Rétablir le fichier", "focusOpenEditors": "Mettre le focus sur la vue des éditeurs ouverts", "focusFilesExplorer": "Focus sur l'Explorateur de fichiers", diff --git a/i18n/fra/src/vs/workbench/parts/files/browser/files.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/files/browser/files.contribution.i18n.json index 066934ce4c8..9693ca31c50 100644 --- a/i18n/fra/src/vs/workbench/parts/files/browser/files.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/browser/files.contribution.i18n.json @@ -40,10 +40,14 @@ "dynamicHeight": "Contrôle si la hauteur de la section des éditeurs ouverts doit s'adapter dynamiquement ou non au nombre d'éléments.", "autoReveal": "Contrôle si l'Explorateur doit automatiquement afficher et sélectionner les fichiers à l'ouverture.", "enableDragAndDrop": "Contrôle si l'explorateur doit autoriser le déplacement de fichiers et de dossiers par glisser-déplacer.", + "confirmDragAndDrop": "Contrôle si l’Explorateur doit demander confirmation lors du déplacement de fichiers ou de dossiers via glisser-déposer.", + "confirmDelete": "Contrôle si l’explorateur doit demander confirmation lorsque vous supprimez un fichier via la corbeille.", "sortOrder.default": "Les fichiers et dossiers sont triés par nom, dans l’ordre alphabétique. Les dossiers sont affichés avant les fichiers.", "sortOrder.mixed": "Les fichiers et dossiers sont triés par nom, dans l’ordre alphabétique. Les fichiers sont imbriqués dans les dossiers.", "sortOrder.filesFirst": "Les fichiers et dossiers sont triés par nom, dans l’ordre alphabétique. Les fichiers sont affichés avant les dossiers.", "sortOrder.type": "Les fichiers et dossiers sont triés par extension, dans l’ordre alphabétique. Les dossiers sont affichés avant les fichiers.", "sortOrder.modified": "Les fichiers et dossiers sont triés par date de dernière modification, dans l’ordre décroissant. Les dossiers sont affichés avant les fichiers.", - "sortOrder": "Contrôle l'ordre de tri des fichiers et dossiers dans l'explorateur. En plus du tri par défaut, vous pouvez définir l'ordre sur 'mixed' (fichiers et dossiers triés combinés), 'type' (par type de fichier), 'modified' (par date de dernière modification) ou 'fileFirst' (trier les fichiers avant les dossiers)." + "sortOrder": "Contrôle l'ordre de tri des fichiers et dossiers dans l'explorateur. En plus du tri par défaut, vous pouvez définir l'ordre sur 'mixed' (fichiers et dossiers triés combinés), 'type' (par type de fichier), 'modified' (par date de dernière modification) ou 'fileFirst' (trier les fichiers avant les dossiers).", + "explorer.decorations.colors": "Contrôle si les décorations de fichier doivent utiliser des couleurs.", + "explorer.decorations.badges": "Contrôle si les décorations de fichier doivent utiliser des badges." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/fra/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 8d920cf85ed..a44dd00649c 100644 --- a/i18n/fra/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,8 @@ { "noWorkspace": "Aucun dossier ouvert", "explorerSection": "Section de l'Explorateur de fichiers", - "noWorkspaceHelp": "Vous n'avez pas encore ouvert de dossier.", + "noWorkspaceHelp": "Vous n’avez pas encore ajouté un dossier à l’espace de travail.", + "addFolder": "Ajouter un dossier", + "noFolderHelp": "Vous n'avez pas encore ouvert de dossier.", "openFolder": "Ouvrir le dossier" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/fra/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index b4031885489..c30df4ecd5b 100644 --- a/i18n/fra/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "Impossible de résoudre le dossier {0}", "fileInputAriaLabel": "Tapez le nom du fichier. Appuyez sur Entrée pour confirmer ou sur Échap pour annuler.", "filesExplorerViewerAriaLabel": "{0}, Explorateur de fichiers", "dropFolders": "Voulez-vous ajouter les dossiers à l’espace de travail ?", "dropFolder": "Voulez-vous ajouter le dossier à l’espace de travail ?", "addFolders": "&&Ajouter les dossiers", "addFolder": "&&Ajouter le dossier", + "confirmMove": "Êtes-vous certain de vouloir déplacer '{0}' ?", + "doNotAskAgain": "Ne plus me demander", "confirmOverwriteMessage": "{0}' existe déjà dans le dossier de destination. Voulez-vous le remplacer ?", "irreversible": "Cette action est irréversible !", "replaceButtonLabel": "&&Remplacer" diff --git a/i18n/fra/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..72ea24da7b8 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Problèmes", + "tooltip.1": "1 problème dans ce fichier", + "tooltip.N": "{0} problèmes dans ce fichier", + "markers.showOnFile": "Afficher les erreurs & les avertissements sur les fichiers et dossiers." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 3684b913ba7..2c9bee3d6c2 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Placer vos paramètres ici pour remplacer les paramètres par défaut.", - "errorInvalidConfiguration": "Impossible d'écrire les paramètres. Corrigez les erreurs/avertissements présents dans le fichier, puis réessayez.", "emptyWorkspaceSettingsHeader": "Placer vos paramètres ici pour remplacer les paramètres utilisateur.", "emptyFolderSettingsHeader": "Placer les paramètres de votre dossier ici pour remplacer ceux des paramètres de l’espace de travail.", "defaultFolderSettingsTitle": "Paramètres de dossier par défaut", diff --git a/i18n/fra/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/fra/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 1c20cdc1e83..9806bbb1795 100644 --- a/i18n/fra/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "La commande '{0}' n'est pas activée dans le contexte actuel.", "recentlyUsed": "récemment utilisées", "morecCommands": "autres commandes", - "commandLabel": "{0} : {1}", "cat.title": "{0} : {1}", "noCommandsMatching": "Aucune commande correspondante" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index e9c5ba38792..9e292a57bbd 100644 --- a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "changes": "{0} sur {1} modifications", + "change": "{0} sur {1} modification", + "show previous change": "Voir la modification précédente", + "show next change": "Voir la modification suivante", "editorGutterModifiedBackground": "Couleur d'arrière-plan de la reliure de l'éditeur pour les lignes modifiées.", "editorGutterAddedBackground": "Couleur d'arrière-plan de la reliure de l'éditeur pour les lignes ajoutées.", "editorGutterDeletedBackground": "Couleur d'arrière-plan de la reliure de l'éditeur pour les lignes supprimées.", diff --git a/i18n/fra/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index a2647c9191c..079ee64e791 100644 --- a/i18n/fra/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,7 @@ "exclude": "Configurez les modèles Glob pour exclure les fichiers et les dossiers des recherches. Hérite de tous les modèles Glob à partir du paramètre files.exclude.", "exclude.boolean": "Modèle Glob auquel les chemins de fichiers doivent correspondre. Affectez la valeur true ou false pour activer ou désactiver le modèle.", "exclude.when": "Vérification supplémentaire des frères d'un fichier correspondant. Utilisez $(basename) comme variable pour le nom de fichier correspondant.", - "useRipgrep": "Contrôle si ripgrep doit être utilisé dans la recherche de texte", + "useRipgrep": "Contrôle si ripgrep doit être utilisé dans la recherche de texte et de fichier", "useIgnoreFilesByDefault": "Indique s'il faut utiliser les fichiers .gitignore et .ignore par défaut en cas de recherche dans un nouvel espace de travail.", "search.quickOpen.includeSymbols": "Configurez l'ajout des résultats d'une recherche de symboles globale dans le fichier de résultats pour Quick Open." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 2478230b806..e43ec2a86c7 100644 --- a/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Effacer les résultats de la recherche", "FocusNextSearchResult.label": "Focus sur le résultat de la recherche suivant", "FocusPreviousSearchResult.label": "Focus sur le résultat de la recherche précédent", - "RemoveAction.label": "Supprimer", "file.replaceAll.label": "Tout remplacer", "match.replace.label": "Remplacer" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index b340098147f..344eb79e2cd 100644 --- a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Ajoute des extraits de code.", "vscode.extension.contributes.snippets-language": "Identificateur de langage pour lequel cet extrait de code est ajouté.", "vscode.extension.contributes.snippets-path": "Chemin du fichier d'extraits de code. Le chemin est relatif au dossier d'extensions et commence généralement par './snippets/'.", - "badFile": "Le fichier d’extrait \"{0}\" n’a pas pu être lu.", "badVariableUse": "L'extrait de code \"{0}\" confond très probablement les variables et les espaces réservés d'extrait de code. Consultez https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax pour plus d'informations.", + "badFile": "Le fichier d’extrait \"{0}\" n’a pas pu être lu.", "source.snippet": "Extrait de code utilisateur", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 0f3f74aef8d..abe24c7ec4d 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -14,6 +14,7 @@ "runningTasks": "Afficher les tâches en cours d'exécution", "tasks": "Tâches", "TaskSystem.noHotSwap": "Changer le moteur d’exécution de tâches avec une tâche active en cours d’exécution nécessite de recharger la fenêtre", + "TaskServer.folderIgnored": "Le dossier {0} est ignoré car il utilise la version 0.1.0 de task", "TaskService.noBuildTask1": "Aucune tâche de build définie. Marquez une tâche avec 'isBuildCommand' dans le fichier tasks.json.", "TaskService.noBuildTask2": "Aucune tâche de génération définie. Marquez une tâche comme groupe 'build' dans le fichier tasks.json.", "TaskService.noTestTask1": "Aucune tâche de test définie. Marquez une tâche avec 'isTestCommand' dans le fichier tasks.json.", @@ -30,6 +31,7 @@ "TaskSystem.activeSame.noBackground": "La tâche '{0}' est déjà active. Pour la terminer, il utilise `Terminer la Tâche...` dans le menu Tâches.", "TaskSystem.active": "Une tâche est déjà en cours d'exécution. Terminez-la avant d'exécuter une autre tâche.", "TaskSystem.restartFailed": "Échec de la fin de l'exécution de la tâche {0}", + "TaskService.noConfiguration": "Erreur : La détection de la tâche {0} n’a pas contribué à une tâche pour la configuration suivante : {1}, la tâche sera ignorée.\n", "TaskSystem.configurationErrors": "Erreur : la configuration de tâche fournie comporte des erreurs de validation et ne peut pas être utilisée. Corrigez d'abord les erreurs.", "taskService.ignoreingFolder": "Les configurations de tâche seront ignorées pour le dossier de l’espace de travail {0}. Le support de la tâche d'espace de travail multi-dossier requiert que tous les dossiers utilisent task version 2.0.0\n", "TaskSystem.invalidTaskJson": "Erreur : le fichier tasks.json contient des erreurs de syntaxe. Corrigez-les avant d'exécuter une tâche.\n", diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 8a455dbd3c0..8e54d84198f 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -17,6 +17,7 @@ "terminal.integrated.fontFamily": "Contrôle la famille de polices du terminal. La valeur par défaut est la valeur associée à editor.fontFamily.", "terminal.integrated.fontSize": "Contrôle la taille de police en pixels du terminal.", "terminal.integrated.lineHeight": "Contrôle la hauteur de ligne du terminal. La multiplication de ce nombre par la taille de police du terminal permet d'obtenir la hauteur de ligne réelle en pixels.", + "terminal.integrated.enableBold": "Indique s'il faut activer le texte en gras dans le terminal, notez que cela nécessite la prise en charge du terminal Shell.", "terminal.integrated.cursorBlinking": "Contrôle si le curseur du terminal clignote.", "terminal.integrated.cursorStyle": "Contrôle le style du curseur du terminal.", "terminal.integrated.scrollback": "Contrôle la quantité maximale de lignes que le terminal conserve dans sa mémoire tampon.", diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index c06b522fc53..b1d65f3e2d3 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Nouveau terminal", "workbench.action.terminal.focus": "Focus sur le terminal", "workbench.action.terminal.focusNext": "Focus sur le terminal suivant", - "workbench.action.terminal.focusAtIndex": "Focus sur le terminal {0}", "workbench.action.terminal.focusPrevious": "Focus sur le terminal précédent", "workbench.action.terminal.paste": "Coller dans le terminal actif", "workbench.action.terminal.DefaultShell": "Sélectionner l'interpréteur de commandes par défaut", diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 7aeb29b6337..aa7d60b35db 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Copier", - "createNewTerminal": "Nouveau terminal", "paste": "Coller", "selectAll": "Tout Sélectionner", "clear": "Effacer" diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 4692e6dfcd1..d636f6886f8 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "OK, ne plus afficher", "terminal.integrated.chooseWindowsShell": "Sélectionnez votre interpréteur de commandes de terminal favori. Vous pouvez le changer plus tard dans vos paramètres", "terminalService.terminalCloseConfirmationSingular": "Il existe une session de terminal active. Voulez-vous la tuer ?", - "terminalService.terminalCloseConfirmationPlural": "Il existe {0} sessions de terminal actives. Voulez-vous les tuer ?", - "yes": "Oui" + "terminalService.terminalCloseConfirmationPlural": "Il existe {0} sessions de terminal actives. Voulez-vous les tuer ?" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..c93a0aa18c9 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -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. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Résumé des paramètres. Cette étiquette va être utilisée dans le fichier de paramètres en tant que commentaire de séparation.", + "vscode.extension.contributes.configuration.properties": "Description des propriétés de configuration.", + "scope.window.description": "Configuration spécifique de la fenêtre, qui peut être configurée dans les paramètres utilisateur ou de l'espace de travail.", + "scope.resource.description": "Configuration spécifique de la ressource, qui peut être configurée dans les paramètres utilisateur, de l'espace de travail ou du dossier.", + "scope.description": "Portée dans laquelle la configuration s’applique. Les portées disponibles sont `window` et `resource`.", + "vscode.extension.contributes.configuration": "Ajoute des paramètres de configuration.", + "invalid.title": "'configuration.title' doit être une chaîne", + "vscode.extension.contributes.defaultConfiguration": "Contribue aux paramètres de configuration d'éditeur par défaut en fonction du langage.", + "invalid.properties": "'configuration.properties' doit être un objet", + "invalid.allOf": "'configuration.allOf' est obsolète et ne doit plus être utilisé. Au lieu de cela, passez plusieurs sections de configuration sous forme de tableau au point de contribution 'configuration'.", + "workspaceConfig.folders.description": "Liste des dossiers à être chargés dans l’espace de travail.", + "workspaceConfig.path.description": "Un chemin de fichier, par exemple, '/root/folderA' ou './folderA' pour un chemin relatif résolu selon l’emplacement du fichier d’espace de travail.", + "unknownWorkspaceProperty": "Propriété de configuration d’espace de travail inconnue" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/fra/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/fra/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index d9200a0b879..72ed7866243 100644 --- a/i18n/fra/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/fra/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -6,6 +6,7 @@ { "schema.token.settings": "Couleurs et styles du jeton.", "schema.token.foreground": "Couleur de premier plan du jeton.", + "schema.token.background.warning": "Les couleurs d’arrière-plan des tokens ne sont actuellement pas pris en charge.", "schema.token.fontStyle": "Style de police de la règle : 'italique', 'gras' ou 'souligné', ou une combinaison de ces styles", "schema.fontStyle.error": "Le style de police doit être une combinaison de 'italic', 'bold' et 'underline'", "schema.properties.name": "Description de la règle.", diff --git a/i18n/fra/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/fra/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index 47c337cef4b..d920cb0bcb8 100644 --- a/i18n/fra/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/fra/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -33,5 +33,6 @@ "schema.fontSize": "Quand une police est utilisée : taille de police en pourcentage par rapport à la police du texte. En l'absence de définition, la taille de la définition de police est utilisée par défaut.", "schema.fontId": "Quand une police est employée : ID de la police. En l'absence de définition, la première définition de police est utilisée par défaut.", "schema.light": "Associations facultatives des icônes de fichiers dans les thèmes de couleur claire.", - "schema.highContrast": "Associations facultatives des icônes de fichiers dans les thèmes de couleur à contraste élevé." + "schema.highContrast": "Associations facultatives des icônes de fichiers dans les thèmes de couleur à contraste élevé.", + "schema.hidesExplorerArrows": "Détermine si les flèches de l’Explorateur de fichier doivent être masquées lorsque ce thème est actif." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/fra/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..63c65b5f2e0 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contributes textmate color themes.", + "vscode.extension.contributes.themes.id": "ID du thème d'icône utilisé dans les paramètres utilisateur.", + "vscode.extension.contributes.themes.label": "Étiquette du thème de couleur comme indiqué dans l'interface utilisateur (IU).", + "vscode.extension.contributes.themes.uiTheme": "Thème de base définissant les couleurs autour de l'éditeur : 'vs' est le thème de couleur clair, 'vs-dark' est le thème de couleur sombre. 'hc-black' est le thème sombre à contraste élevé.", + "vscode.extension.contributes.themes.path": "Chemin du fichier tmTheme. Le chemin est relatif au dossier d'extensions et correspond généralement à './themes/themeFile.tmTheme'.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "Chaîne attendue dans 'contributes.{0}.path'. Valeur fournie : {1}", + "invalid.path.1": "'contributes.{0}.path' ({1}) est censé être inclus dans le dossier ({2}) de l'extension. Cela risque de rendre l'extension non portable." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..b0f9faf6b52 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problems parsing file icons file: {0}" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..0c251843630 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "ID du thème d'icône utilisé dans les paramètres utilisateur.", + "vscode.extension.contributes.iconThemes.label": "Étiquette du thème d'icône indiqué dans l'IU (interface utilisateur).", + "vscode.extension.contributes.iconThemes.path": "Chemin du fichier de définitions de thèmes d'icônes. Le chemin est relatif au dossier d'extensions et correspond généralement à './icons/awesome-icon-theme.json'.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "Chaîne attendue dans 'contributes.{0}.path'. Valeur fournie : {1}", + "reqid": "Chaîne attendue dans 'contributes.{0}.id'. Valeur fournie : {1}", + "invalid.path.1": "'contributes.{0}.path' ({1}) est censé être inclus dans le dossier ({2}) de l'extension. Cela risque de rendre l'extension non portable." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 8ca3299b2ba..234d5fb5a0e 100644 --- a/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "ID du thème d'icône utilisé dans les paramètres utilisateur.", - "vscode.extension.contributes.themes.label": "Étiquette du thème de couleur comme indiqué dans l'interface utilisateur (IU).", - "vscode.extension.contributes.themes.uiTheme": "Thème de base définissant les couleurs autour de l'éditeur : 'vs' est le thème de couleur clair, 'vs-dark' est le thème de couleur sombre. 'hc-black' est le thème sombre à contraste élevé.", - "vscode.extension.contributes.themes.path": "Chemin du fichier tmTheme. Le chemin est relatif au dossier d'extensions et correspond généralement à './themes/themeFile.tmTheme'.", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "ID du thème d'icône utilisé dans les paramètres utilisateur.", - "vscode.extension.contributes.iconThemes.label": "Étiquette du thème d'icône indiqué dans l'IU (interface utilisateur).", - "vscode.extension.contributes.iconThemes.path": "Chemin du fichier de définitions de thèmes d'icônes. Le chemin est relatif au dossier d'extensions et correspond généralement à './icons/awesome-icon-theme.json'.", "migration.completed": "De nouveaux paramètres de thème ont été ajoutés aux paramètres utilisateur. Sauvegarde disponible sur {0}.", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "Chaîne attendue dans 'contributes.{0}.path'. Valeur fournie : {1}", - "invalid.path.1": "'contributes.{0}.path' ({1}) est censé être inclus dans le dossier ({2}) de l'extension. Cela risque de rendre l'extension non portable.", - "reqid": "Chaîne attendue dans 'contributes.{0}.id'. Valeur fournie : {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "Spécifie le thème d'icône utilisé dans le banc d'essai ou 'null' pour n'afficher aucune icône de fichier.", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Remplace les couleurs du thème de couleur sélectionné.", - "workbenchColors.deprecated": "Le paramètre n'est plus expérimental et a été renommé 'workbench.colorCustomizations'", - "workbenchColors.deprecatedDescription": "Utiliser 'workbench.colorCustomizations' à la place", "editorColors": "Remplace les couleurs et le style de la police de l’éditeur du thème par la couleur actuellement sélectionnée.", "editorColors.comments": "Définit les couleurs et les styles des commentaires", "editorColors.strings": "Définit les couleurs et les styles des littéraux de chaînes.", diff --git a/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..e6f04379725 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Ouvrir le Fichier de Configuration d’espace de travail", + "close": "Fermer" +} \ No newline at end of file diff --git a/i18n/hun/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/hun/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 73e2b227f47..b0baf1f7552 100644 --- a/i18n/hun/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/hun/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "pl.: myFile.txt", - "activeEditorMedium": "pl.: myFolder/myFile.txt", - "activeEditorLong": "pl.: /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "pl.: myFolder1, myFolder2, myFolder3", - "rootPath": "pl.: /Users/Development/myProject", - "folderName": "pl.: myFolder", - "folderPath": "pl.: /Users/Development/myProject", + "activeEditorShort": "a fájl neve (pl. myFile.txt)", + "activeEditorMedium": "a fájl relatív elérési útja a munkaterület mappájához képest (pl. myFolder/myFile.txt)", + "activeEditorLong": "a fájl teljes elérési útja (pl. /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "a munkaterület neve (pl. myFolder vagy myWorkspace)", + "rootPath": "a munkaterület elérési útja (pl. /Users/Development/myWorkspace)", + "folderName": "azon munkaterületi mappa a neve, amelyben a fájl található (pl. myFolder)", + "folderPath": "azon munkaterületi mappa elérési útja, amelyben a fájl található (pl. /Users/Development/myFolder)", "appName": "pl.: VS Code", "dirty": "módosításjelző, ami akkor jelenik meg, ha az aktív szerkesztőablak tartalma módosítva lett", "separator": "egy feltételes elválasztó (' - '), ami akkor jelenik meg, ha olyan változókkal van körülvéve, amelyeknek van értéke", diff --git a/i18n/hun/extensions/emmet/package.i18n.json b/i18n/hun/extensions/emmet/package.i18n.json index 576657ed646..e8dd71aabaa 100644 --- a/i18n/hun/extensions/emmet/package.i18n.json +++ b/i18n/hun/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Növelés 10-zel", "command.decrementNumberByTen": "Csökkentés 10-zel", "emmetSyntaxProfiles": "Konkrét szintaktika profiljának meghatározása vagy saját profil használata adott szabályokkal.", - "emmetExclude": "Azon nyelvek listája, ahol az Emmet-rövidítések ne legyenek kibontva.", - "emmetExtensionsPath": "Egy Emmet-profilokat és -kódtöredékeket tartalmazó mappa elérési útja.", - "emmetShowExpandedAbbreviation": "Kibontott emmet-rövidítések megjelenítése javaslatként. Az \"inMarkupAndStylesheetFilesOnly\" beállítás csak a html, haml, jade, slim, xml, xsl, css, scss, sass, less és stylus típusú tartalmat jelenti. Az \"always\" beállítás a fájl összes részére vonatkozik a jelölőnyelvtől/css-től függetlenül.", - "emmetShowAbbreviationSuggestions": "A lehetséges emmet-rövidítések megjelenítése javaslatként. Nem használható a stíluslapokon vagy ha az emmet.showExpandedAbbreviation értéke \"never\".", - "emmetIncludeLanguages": "Emmet-rövidítések engedélyezése olyan nyelvek esetében, amelyek alapértelmezés szerint nem támogatottak. Egy megfeleltetést kell felvenni a nyelv és egy emmet által támogatott nyelv között.\nPl.: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Az emmet-kódrészletekben használt változók", - "emmetTriggerExpansionOnTab": "Ha engedélyezve van, akkor az Emmet-rövidítések a Tab billentyű lenyomásával bonthatók ki.", "emmetPreferences": "Beállítások, melyek módosítják az Emmet műveleteinek és feloldó algoritmusainak viselkedését.", "emmetPreferencesIntUnit": "Az egész számok alapértelmezett mértékegysége", "emmetPreferencesFloatUnit": "A lebegőpontos számok alapértelmezett mértékegysége", @@ -44,5 +37,7 @@ "emmetPreferencesCssBetween": "A CSS-tulajdonság és az érték közé helyezett szimbólum CSS-rövidítések kibontásánál", "emmetPreferencesSassBetween": "A CSS-tulajdonság és az érték közé helyezett szimbólum CSS-rövidítések kibontásánál Sass-fájlokban", "emmetPreferencesStylusBetween": "A CSS-tulajdonság és az érték közé helyezett szimbólum CSS-rövidítések kibontásánál Stylus-fájlokban", - "emmetShowSuggestionsAsSnippets": "Ha az értéke igaz, akkor az emmetes javaslatok kódrészletekként jelennek meg, ami lehetővé teszi az editor.snippetSuggestions beállítás alapján történő rendezésüket." + "emmetPreferencesFilterCommentBefore": "Annak a megjegyzésnek a definíciója, ami az illeszkedő elem elé kerül a megjegyzésszűrő alkalmazása esetén.", + "emmetPreferencesFilterCommentAfter": "Annak a megjegyzésnek a definíciója, ami az illeszkedő elem mögé kerül a megjegyzésszűrő alkalmazása esetén.", + "emmetPreferencesFilterCommentTrigger": "Attribútumnevek vesszővel elválasztott listája, amelyeknek léteznie kell a megjegyzésszűrő alkalmazásához." } \ No newline at end of file diff --git a/i18n/hun/extensions/git/out/commands.i18n.json b/i18n/hun/extensions/git/out/commands.i18n.json index e3a35609258..ed82f751b7f 100644 --- a/i18n/hun/extensions/git/out/commands.i18n.json +++ b/i18n/hun/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Git-forráskódtár klónozása...", "openrepo": "Forráskódtár megnyitása", "proposeopen": "Szeretné megnyitni a klónozott forráskódtárat?", - "path to init": "Mappa elérési útja", - "provide path": "Git-forráskódtár inicializálásához adjon meg egy elérési utat!", + "init repo": "Forráskódtár előkészítése", + "create repo": "Forráskódtár előkészítése", + "are you sure": "A művelet egy Git forráskódtárat hoz létre a következő helyen: '{0}. Biztosan szeretné folytatni?", "HEAD not available": "A(z) '{0}' HEAD-verziója nem elérhető.", "confirm stage files with merge conflicts": "Biztosan elő szeretne jegyezni {0} ütközési konfliktussal rendelkező fájlt?", "confirm stage file with merge conflicts": "Biztosan elő szeretne jegyezni a következő, ütközési konfliktussal rendelkező fájlt: {0}?", diff --git a/i18n/hun/extensions/git/out/repository.i18n.json b/i18n/hun/extensions/git/out/repository.i18n.json index 360a4435ac6..386f0a265df 100644 --- a/i18n/hun/extensions/git/out/repository.i18n.json +++ b/i18n/hun/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Általunk törölt", "both added": "Mindkettő hozzáadta", "both modified": "Mindkettő módosította", + "untracked, short": "N", + "modified, short": "M", "commit": "Commit", "merge changes": "Módosítások összeolvasztása", "staged changes": "Beadásra előjegyzett módosítások", diff --git a/i18n/hun/extensions/git/package.i18n.json b/i18n/hun/extensions/git/package.i18n.json index 3aff31e4cd7..81661105b4d 100644 --- a/i18n/hun/extensions/git/package.i18n.json +++ b/i18n/hun/extensions/git/package.i18n.json @@ -15,6 +15,8 @@ "command.stageAll": "Összes módosítás előjegyzése beadásra", "command.stageSelectedRanges": "Kijelölt területek előjegyzése beadásra", "command.revertSelectedRanges": "Kijelölt területek visszaállítása", + "command.stageChange": "Változás előjegyzése beadásra", + "command.revertChange": "Változtatás visszavonása", "command.unstage": "Módosítások előjegyzésének törlése", "command.unstageAll": "Minden módosítás előjegyzésének törlése", "command.unstageSelectedRanges": "Kijelölt területek előjegyzésének törlése", diff --git a/i18n/hun/extensions/typescript/package.i18n.json b/i18n/hun/extensions/typescript/package.i18n.json index 031efbd3fe4..3b45505e009 100644 --- a/i18n/hun/extensions/typescript/package.i18n.json +++ b/i18n/hun/extensions/typescript/package.i18n.json @@ -44,7 +44,8 @@ "typescript.npm": "Az automatikus típusdefiníció-letöltéshez használt NPM végrehajtható fájl elérési útja. TypeScript 2.3.4-et igényel.", "typescript.check.npmIsInstalled": "Ellenőrizze, hogy az NPM telepítve van-e az automatikus típusdefiníció-letöltéshez.", "javascript.nameSuggestions": "Egyedi nevek listázásának engedélyezése a javascriptes javaslati listákban.", - "typescript.tsc.autoDetect": "Meghatározza, hogy a tsc-feladatok automatikus felderítése be van-e kapcsolva.", + "typescript.tsc.autoDetect": "Meghatározza a tsc-s feladatok automatikus felderítésének működését. 'off' érték esetén a funkció ki van kapcsolva. 'build' esetén egyszer lefutó, fordítást végző feladatok jönnek létre. 'watch' esetén csak fordítást és figyelést végző feladatok jönnek létre. 'on' esetén buildelési és figyelési feladatok is keletkeznek. Az alapértelmezett érték: 'on'.", "typescript.problemMatchers.tsc.label": "TypeScript-problémák", - "typescript.problemMatchers.tscWatch.label": "TypeScript-problémák (figyelő módban)" + "typescript.problemMatchers.tscWatch.label": "TypeScript-problémák (figyelő módban)", + "typescript.quickSuggestionsForPaths": "Kiegészítési javaslatok engedélyezése importált elérési utak beírásakor." } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/hun/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 2e445d0ec2e..43d34e8aacc 100644 --- a/i18n/hun/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Csere", "label.replaceAllButton": "Az összes előfordulás cseréje", "label.toggleReplaceButton": "Váltás csere módra", - "title.matchesCountLimit": "Csak az első 999 találat van kiemelve, de minden keresési művelet a teljes szöveggel dolgozik.", "label.matchesLocation": "{0} (összesen {1})", "label.noResults": "Nincs eredmény" } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/hun/src/vs/editor/contrib/find/common/findController.i18n.json index b502771aa98..6e1f33bceda 100644 --- a/i18n/hun/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Következő kijelölés", "previousSelectionMatchFindAction": "Előző kijelölés", "startReplace": "Csere", - "addSelectionToNextFindMatch": "Kijelölés hozzáadása a következő keresési találathoz", - "addSelectionToPreviousFindMatch": "Kijelölés hozzáadása az előző keresési találathoz", - "moveSelectionToNextFindMatch": "Utolsó kijelölés áthelyezése a következő keresési találatra", - "moveSelectionToPreviousFindMatch": "Utolsó kijelölés áthelyezése az előző keresési találatra", - "selectAllOccurrencesOfFindMatch": "Az összes keresési találat kijelölése", - "changeAll.label": "Minden előfordulás módosítása", "showNextFindTermAction": "Következő keresési kifejezés megjelenítése", "showPreviousFindTermAction": "Előző keresési kifejezés megjelenítése" } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/hun/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 8aa3dbca9ff..f50dc975843 100644 --- a/i18n/hun/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Kurzor beszúrása egy sorral feljebb", "mutlicursor.insertBelow": "Kurzor beszúrása egy sorral lejjebb", - "mutlicursor.insertAtEndOfEachLineSelected": "Kurzor beszúrása a sorok végére" + "mutlicursor.insertAtEndOfEachLineSelected": "Kurzor beszúrása a sorok végére", + "addSelectionToNextFindMatch": "Kijelölés hozzáadása a következő keresési találathoz", + "addSelectionToPreviousFindMatch": "Kijelölés hozzáadása az előző keresési találathoz", + "moveSelectionToNextFindMatch": "Utolsó kijelölés áthelyezése a következő keresési találatra", + "moveSelectionToPreviousFindMatch": "Utolsó kijelölés áthelyezése az előző keresési találatra", + "selectAllOccurrencesOfFindMatch": "Az összes keresési találat kijelölése", + "changeAll.label": "Minden előfordulás módosítása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json index 8cfb21c1837..1d88bef987d 100644 --- a/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Érvénytelen színformátum. Az #RGB, #RGBA, #RRGGBB vagy #RRGGBBAA formátum használható.", "schema.colors": "A munkaterületen használt színek.", "foreground": "Általános előtérszín. Csak akkor van használva, ha nem írja felül az adott komponens.", "errorForeground": "A hibaüzenetek általános előtérszíne. Csak akkor van használva, ha nem írja felül az adott komponens.", diff --git a/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 64c1ec455b3..854d2bb1a23 100644 --- a/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "Mappa hozzáadása a munkaterülethez...", "add": "&&Hozzáadás", "addFolderToWorkspaceTitle": "Mappa hozzáadása a munkaterülethez", + "globalRemoveFolderFromWorkspace": "Mappa eltávolítása a munkaterületről...", "newWorkspace": "Új munkaterület...", "select": "&&Kiválasztás", "selectWorkspace": "Válassza ki a munkaterület mappáit!", "removeFolderFromWorkspace": "Mappa eltávolítása a munkaterületről", + "openFolderSettings": "Mappa beállításainak megnyitása", "saveWorkspaceAsAction": "Munkaterület mentése másként...", "save": "Menté&&s", "saveWorkspace": "Munkaterület mentése", "openWorkspaceAction": "Munkaterület megnyitása...", "openWorkspaceConfigFile": "Munkaterület konfigurációs fájljának megnyitása", + "openFolderAsWorkspaceInNewWindow": "Mappa megnyitása munkaterületként egy új ablakban", "workspaceFolderPickerPlaceholder": "Válasszon munkaterület-mappát!" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index 266ac56433e..3c81d54bd07 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Tevékenységsáv elrejtése", - "activityBarAriaLabel": "Az aktív nézet váltása", "globalActions": "Globális műveletek" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..4fe5826df65 --- /dev/null +++ b/i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Az aktív nézet váltása" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..af96f733ba7 --- /dev/null +++ b/i18n/hun/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} – {1}", + "additionalViews": "További nézetek", + "numberBadge": "{0} ({1})", + "manageExtension": "Kiegészítő kezelése", + "titleKeybinding": "{0} ({1})", + "hide": "Elrejtés", + "toggle": "Nézet rögzítésének be- és kikapcsolása" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 186c2e66b64..05a3be82161 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "A második csoportban található szerkesztőablakok megjelenítése", "groupThreePicker": "A harmadik csoportban található szerkesztőablakok megjelenítése", "allEditorsPicker": "Összes megnyitott szerkesztőablak megjelenítése", - "view": "Nézet" + "view": "Nézet", + "file": "Fájl" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 3cc19480b62..dfd63a785b3 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "A(z) '{0}' parancs jelenleg nem engedélyezett és nem futtatható.", "manageExtension": "Kiegészítő kezelése" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json index 730c270e5d5..53babca5f63 100644 --- a/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,15 @@ "workspaces": "Munkaterületek", "developer": "Fejlesztői", "showEditorTabs": "Meghatározza, hogy a megnyitott szerkesztőablakok telején megjelenjenek-e a fülek", - "workbench.editor.labelFormat.default": "Fájl nevének megjelenítése. Ha a fülek engedélyezve vannak, és két egyező nevű fájl van egy csoportban, az elérési útjuk eltérő része lesz hozzáfűzve a névhez. Ha a fülek le vannak tiltva, a fájl munkaterület gyökérkönyvtárához képest relatív elérési útja jelenik meg, ha a szerkesztőablak aktív.", "workbench.editor.labelFormat.short": "A fájl nevének megjelenítése a könyvtár nevével együtt.", - "workbench.editor.labelFormat.medium": "Fájl nevének megjelenítése a fájl munkaterület gyökérkönyvtárához képest relatív elérési útjával együtt.", "workbench.editor.labelFormat.long": "Fájl nevének megjelenítése a fájl abszolút elérési útjával együtt.", "tabDescription": "Meghatározza a szerkesztőablakok címkéje formáját. A beállítás módosítása könnyebbé teheti a fájl helyének kiderítését:\n- short: 'parent'\n- medium: 'workspace/src/parent'\n- long: '/home/user/workspace/src/parent'\n- default: '.../parent', ha egy másik fülnek ugyanaz a címe, vagy a relatív elérési út, ha a fülek le vannak tiltva", "editorTabCloseButton": "Meghatározza a szerkesztőablakok fülein található bezárógomb pozícióját vagy eltávolítja őket, ha a beállítás értéke 'off'.", "showIcons": "Meghatározza, hogy a megnyitott szerkesztőablakok ikonnal együtt jelenjenek-e meg. A működéshez szükséges egy ikontéma engedélyezése is.", "enablePreview": "Meghatározza, hogy a megnyitott szerkesztőablakok előnézetként jelenjenek-e meg. Az előnézetként használt szerkesztőablakok újra vannak hasznosítva, amíg meg nem tartja őket a felhasználó (pl. dupla kattintás vagy szerkesztés esetén), és dőlt betűvel jelenik meg a címsoruk.", "enablePreviewFromQuickOpen": "Meghatározza, hogy a gyors megnyitás során megnyitott szerkesztőablakok előnézetként jelenjenek-e meg. Az előnézetként használt szerkesztőablakok újra vannak hasznosítva, amíg meg nem tartja őket a felhasználó (pl. dupla kattintás vagy szerkesztés esetén).", - "editorOpenPositioning": "Meghatározza, hogy hol nyíljanak meg a szerkesztőablakok. A 'left' vagy 'right' használata esetén az aktív szerkesztőablaktól jobbra vagy balra nyílnak meg az újak. A 'first' vagy 'last' esetén a szerkesztőablakok a jelenleg aktív ablaktól függetlenül nyílnak meg.", "revealIfOpen": "Meghatározza, hogy egy szerkesztőablak fel legyen-e fedve, ha már meg van nyitva a látható csoportok bármelyiképben. Ha le van tiltva, akkor egy új szerkesztőablak nyílik az aktív szerkesztőablak-csoportban. Ha engedélyezve van, akkor a már megnyitott szerkesztőablak lesz felfedve egy új megnyitása helyett. Megjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva, pl. ha egy adott szerkesztőablak egy konkrét csoportban vagy a jelenleg aktív csoport mellett van menyitva.", - "commandHistory": "Meghatározza, hogy mennyi legutóbb használt parancs jelenjen meg a parancskatalógus előzményeinek listájában. Az előzmények kikapcsolásához állítsa az értéket 0-ra.", + "commandHistory": "Meghatározza, hogy hány legutóbb használt parancs jelenjen meg a parancskatalógus előzményeinek listájában. Az előzmények kikapcsolásához állítsa az értéket nullára.", "preserveInput": "Meghatározza, hogy a legutóbb beírt parancs automatikusan helyre legyen-e állítva a parancskatalógus következő megnyitása során.", "closeOnFocusLost": "Meghatározza, hogy a gyors megnyitás automatikusan bezáródjon-e amint elveszíti a fókuszt.", "openDefaultSettings": "Meghatározza, hogy a beállítások megnyitásakor megnyíljon-e egy szerkesztő az összes alapértelmezett beállítással.", @@ -50,7 +47,7 @@ "restoreWindows": "Meghatározza, hogy újraindítás után hogyan vannak ismét megnyitva az ablakok. A 'none' választása esetén mindig üres munkaterület indul, 'one' esetén a legutóbb használt ablak nyílik meg újra, a 'folders' megnyitja az összes megnyitott mappát, míg az 'all' újranyitja az összes ablakot az előző munkamenetből.", "restoreFullscreen": "Meghatározza, hogy az ablak teljesképernyős módban nyíljon-e meg, ha kilépéskor teljes képernyős módban volt.", "zoomLevel": "Meghatározza az ablak nagyítási szintjét. Az eredei méret 0, és minden egyes plusz (pl. 1) vagy mínusz (pl. -1) 20%-kal nagyobb vagy kisebb nagyítási szintet jelent. Tizedestört megadása esetén a nagyítási szint finomabban állítható.", - "title": "Meghatározza az ablak címét az aktív szerkesztőablak alapján. A változók a környezet alapján vannak behelyettesítve:\n${activeEditorShort}: pl. myFile.txt\n${activeEditorMedium}: pl. myFolder/myFile.txt\n${activeEditorLong}: pl. /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: pl. myFolder\n${folderPath}: pl. /Users/Development/myFolder\n${rootName}: pl. myFolder1, myFolder2, myFolder3\n${rootPath}: pl. /Users/Development/myWorkspace\n${appName}: pl. VS Code\n${dirty}: módosításjelző, ami jelzi, ha az aktív szerkesztőablak tartalma módosítva lett\n${separator}: feltételes elválasztó (\" - \"), ami akkor jelenik meg, ha olyan változókkal van körülvéve, amelyeknek van értéke\n", + "title": "Meghatározza az ablak címét az aktív szerkesztőablak alapján. A változók a környezet alapján vannak behelyettesítve:\n${activeEditorShort}: a fájl neve (pl. myFile.txt)\n${activeEditorMedium}: a fájl relatív elérési útja a munkaterület mappájához képest (pl. myFolder/myFile.txt)\n${activeEditorLong}: a fájl teljes elérési útja (pl. /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: azon munkaterületi mappa a neve, amelyben a fájl található (pl. myFolder)\n${folderPath}: azon munkaterületi mappa elérési útja, amelyben a fájl található (pl. /Users/Development/myFolder)\n${rootName}: a munkaterület neve (pl. myFolder vagy myWorkspace)\n${rootPath}: a munkaterület elérési útja (pl. /Users/Development/myWorkspace)\n${appName}: pl. VS Code\n${dirty}: módosításjelző, ami jelzi, ha az aktív szerkesztőablak tartalma módosítva lett\n${separator}: feltételes elválasztó (\" - \"), ami akkor jelenik meg, ha olyan változókkal van körülvéve, amelyeknek van értéke", "window.newWindowDimensions.default": "Az új ablakok a képernyő közepén nyílnak meg.", "window.newWindowDimensions.inherit": "Az új ablakok ugyanolyan méretben és ugyanazon a helyen jelennek meg, mint a legutoljára aktív ablak.", "window.newWindowDimensions.maximized": "Az új ablakok teljes méretben nyílnak meg.", diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 4020242c40c..7c16965748a 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, hibakeresés", "debugAriaLabel": "Írja be a futtatandó konfiguráció nevét.", + "addConfigTo": "Konfiguráció hozzáadása ({0})...", + "addConfiguration": "Konfiguráció hozzáadása...", "noConfigurationsMatching": "Nincs illeszkedő hibakeresési konfiguráció", "noConfigurationsFound": "Nem található hibakeresési konfiguráció. Készítsen egy 'launch.json' fájlt." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..1bd18dd9a99 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Hibakeresés" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..72630bc8424 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debugFocusVariablesView": "Váltás a változókra", + "debugFocusWatchView": "Váltás a figyelőlistára", + "debugFocusCallStackView": "Váltás a hívási veremre", + "debugFocusBreakpointsView": "Váltás a töréspontokra" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index fffc1aad27f..a54b3a8b776 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Konfigurációk a 'launch.json' első változatának elkészítéséhez.", "vscode.extension.contributes.debuggers.languages": "Azon nyelvek listája, amelyeknél ez a hibakeresési kiegészítő alapértelmezett hibakeresőnek tekinthető.", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Ha meg van adva, a VS Code ezt a parancsot fogja hívni a hibakeresési illesztő futtatható állománya elérési útjának és az átadandó argumentumok meghatározásához.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Ha meg van határozva, a VS Code ezt a parancsot fogja hívni az ennek a kiegészítőnek küldött \"debug\" vagy \"run\" parancsok esetén.", "vscode.extension.contributes.debuggers.configurationSnippets": "Kódtöredékek új 'launch.json'-konfigurációk hozzáadásához.", "vscode.extension.contributes.debuggers.configurationAttributes": "JSON-sémakonfigurációk a 'launch.json' validálásához.", "vscode.extension.contributes.debuggers.windows": "Windows-specifikus beállítások.", diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 3945df51449..da4586921b6 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,10 @@ "breakpointRemoved": "Töréspont eltávoíltva, {0}. sor, fájl: {1}", "compoundMustHaveConfigurations": "A kombinációk \"configurations\" tulajdonságát be kell állítani több konfiguráció elindításához.", "configMissing": "A(z) '{0}' konfiguráció hiányzik a 'launch.json'-ból.", - "debugRequestNotSupported": "A kiválasztott hibakeresési konfigurációban a(z) `{0}` attribútum értéke nem támogatott: '{1}'.", - "debugRequesMissing": "A(z) '{0}' attribútum hiányzik a kiválasztott hibakeresési konfigurációból.", + "debugRequestNotSupported": "A(z) `{0}` attribútumnak nem támogatott értéke van ('{1}') a kiválasztott hibakeresési konfigurációban.", + "debugRequesMissing": "A(z) `{0}` attribútum hiányzik a kiválasztott hibakeresési konfigurációból.", "debugTypeNotSupported": "A megadott hibakeresési típus ('{0}') nem támogatott.", - "debugTypeMissing": "A kiválasztott indítási konfigurációnak hiányzik a 'type' tulajdonsága.", + "debugTypeMissing": "A kiválasztott indítási konfigurációnak hiányzik a `type` tulajdonsága.", "preLaunchTaskErrors": "Buildelési hibák léptek fel a(z) '{0}' preLaunchTask futása közben.", "preLaunchTaskError": "Buildelési hiba lépett fel a(z) '{0}' preLaunchTask futása közben.", "preLaunchTaskExitCode": "A(z) '{0}' preLaunchTask a következő hibakóddal fejeződött be: {1}.", diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 929096a6c43..9c979492ec3 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -8,5 +8,5 @@ "replVariableAriaLabel": "A(z) {0} változó értéke: {1}, REPL, hibakeresés", "replExpressionAriaLabel": "A(z) {0} kifejezés értéke: {1}, REPL, hibakeresés", "replValueOutputAriaLabel": "{0}, REPL, hibakeresés", - "replKeyValueOutputAriaLabel": "A(z) {0} kimeneti változó értéke: {1}, REPL, hibakeresés" + "replRawObjectAriaLabel": "{0} repl-változó értéke: {1}, REPL, hibakeresés" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index 0992f340c4a..d032a29e684 100644 --- a/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Fájlok", + "filesCategory": "Fájl", "revealInSideBar": "Megjelenítés az oldalsávon", "acceptLocalChanges": "A lemezen lévő tartalom felülírása a saját módosításokkal", "revertLocalChanges": "Saját módosítások elvetése és a lemezen lévő tartalom visszaállítása" diff --git a/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.i18n.json index b495b205cd5..2f76c2de05a 100644 --- a/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "Törli a(z) '{0}' nevű fájlt?", "undoBin": "Helyreállíthatja a lomtárból.", "undoTrash": "Helyreállíthatja a kukából.", + "doNotAskAgain": "Ne kérdezze meg újra", "confirmDeleteMessageFolder": "Törli a(z) {0} mappát és a teljes tartalmát?", "confirmDeleteMessageFile": "Véglegesen törli a következőt: {0}?", "irreversible": "A művelet nem vonható vissza!", @@ -37,8 +38,6 @@ "openToSide": "Megnyitás oldalt", "compareSource": "Kijelölés összehasonlításhoz", "globalCompareFile": "Aktív fájl összehasonlítása...", - "pickHistory": "Válasszon egy korábban megnyitott fájlt az összehasonlításhoz", - "unableToFileToCompare": "A kiválasztott fájl nem hasonlítható össze a következővel: '{0}'.", "openFileToCompare": "Fájlok összehasonlításához elősször nyisson meg egy fájlt.", "compareWith": "'{0}' összehasonlítása a következővel: '{1}'", "compareFiles": "Fájlok összehasonlítása", @@ -47,7 +46,7 @@ "saveAs": "Mentés másként...", "saveAll": "Összes mentése", "saveAllInGroup": "Összes mentése a csoportban", - "saveFiles": "Módosított fájlok mentése", + "saveFiles": "Összes fájl mentése", "revert": "Fájl visszaállítása", "focusOpenEditors": "Váltás a megnyitott szerkesztőablakok nézetre", "focusFilesExplorer": "Váltás a fájlkezelőre", diff --git a/i18n/hun/src/vs/workbench/parts/files/browser/files.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/files/browser/files.contribution.i18n.json index 4cea0462d06..a6c7fe4eaef 100644 --- a/i18n/hun/src/vs/workbench/parts/files/browser/files.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/browser/files.contribution.i18n.json @@ -40,10 +40,14 @@ "dynamicHeight": "Meghatározza, hogy a megnyitott szerkesztőablakok szakasz magassága automatikusan illeszkedjen a megnyitott elemek számához vagy sem.", "autoReveal": "Meghatározza, hogy a fájlkezelőben automatikusan fel legyenek fedve és ki legyenek jelölve a fájlok, amikor megnyitják őket.", "enableDragAndDrop": "Meghatározza, hogy a fájlkezelőben áthelyezhetők-e a fájlok és mappák húzással.", + "confirmDragAndDrop": "Meghatározza, hogy a fájlkezelő kérjen-e megerősítést fájlok és mappák húzással történő áthelyezése esetén.", + "confirmDelete": "Meghatározza, hogy a fájlkezelő kérjen-e megerősítést a fájlok lomtárba történő helyezése esetén.", "sortOrder.default": "A fájlok és mappák név szerint vannak rendezve, ABC-sorrendben. A mappák a fájlok előtt vannak listázva.", "sortOrder.mixed": "A fájlok és mappák név szerint vannak rendezve, ABC-sorrendben. A fájlok és a mappák közösen vannak rendezve.", "sortOrder.filesFirst": "A fájlok és mappák név szerint vannak rendezve, ABC-sorrendben. A fájlok a mappák előtt vannak listázva.", "sortOrder.type": "A fájlok és mappák a kiterjesztésük szerint vannak rendezve, ABC-sorrendben. A mappák a fájlok előtt vannak listázva.", "sortOrder.modified": "A fájlok és mappák a legutolsó módosítás dátuma szerint vannak rendezve, csökkenő sorrendben. A mappák a fájlok előtt vannak listázva.", - "sortOrder": "Meghatározza a fájlok és mappák rendezési módját a fájlkezelőben. Az alapértelmezett rendezésen túl beállítható 'mixed' (a fájlok és mappák közösen vannak rendezve), 'type' (rendezés fájltípus szerint), 'modified' (rendezés utolsó módosítási dátum szerint) vagy 'filesFirst' (fájlok a mappák elé vannak rendezve) is." + "sortOrder": "Meghatározza a fájlok és mappák rendezési módját a fájlkezelőben. Az alapértelmezett rendezésen túl beállítható 'mixed' (a fájlok és mappák közösen vannak rendezve), 'type' (rendezés fájltípus szerint), 'modified' (rendezés utolsó módosítási dátum szerint) vagy 'filesFirst' (fájlok a mappák elé vannak rendezve) is.", + "explorer.decorations.colors": "Meghatározza, hogy a fájldekorációk használjanak-e színeket.", + "explorer.decorations.badges": "Meghatározza, hogy a fájldekorációk használjanak-e jelvényeket." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/hun/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 924c7ac5593..30d6d309142 100644 --- a/i18n/hun/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,8 @@ { "noWorkspace": "Nincs mappa megnyitva", "explorerSection": "Fájlkezelő szakasz", - "noWorkspaceHelp": "Még nem nyitott meg mappát", + "noWorkspaceHelp": "Még nem adott mappát a munkaterülethez.", + "addFolder": "Mappa hozzáadása", + "noFolderHelp": "Még nem nyitott meg mappát", "openFolder": "Mappa megnyitása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/hun/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index 21ef2846403..07cd01d7b7a 100644 --- a/i18n/hun/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "Nem lehet feloldani a következő mappát: {0}", "fileInputAriaLabel": "Adja meg a fájl nevét. Nyomjon 'Enter'-t a megerősítéshez vagy 'Escape'-et a megszakításhoz.", "filesExplorerViewerAriaLabel": "{0}, Fájlkezelő", "dropFolders": "Szeretné hozzáadni a mappákat a munkaterülethez?", "dropFolder": "Szeretné hozzáadni a mappát a munkaterülethez?", "addFolders": "Mappák hozzá&&adása", "addFolder": "Mappa hozzá&&adása", + "confirmMove": "Biztosan át szeretné helyezni a következőt: '{0}'?", + "doNotAskAgain": "Ne kérdezze meg újra", "confirmOverwriteMessage": "A célmappában már létezik '{0}' nevű elem. Le szeretné cserélni?", "irreversible": "A művelet nem vonható vissza!", "replaceButtonLabel": "&&Csere" diff --git a/i18n/hun/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..c9127f9169b --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Problémák", + "tooltip.1": "A fájlban 1 probléma található", + "tooltip.N": "A fájlban {0} probléma található", + "markers.showOnFile": "Fájlokban és mappákban található hibák és figyelmeztetések megjelenítése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index ee0b9750f56..69b1a883b74 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Az ebben a fájlban elhelyezett beállítások felülírják az alapértelmezett beállításokat.", - "errorInvalidConfiguration": "Nem sikerült írni a beállításokba. Javítsa a fájlban található hibákat/figyelmeztetéseket, majd próbálja újra!", "emptyWorkspaceSettingsHeader": "Az ebben a fájlban elhelyezett beállítások felülírják a felhasználói beállításokat.", "emptyFolderSettingsHeader": "Az ebben a fájlban elhelyezett beállítások felülírják a munkaterületre vonatkozó beállításokat.", "defaultFolderSettingsTitle": "Alapértelmezett mappabeállítások", diff --git a/i18n/hun/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/hun/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 41ec82c33f7..949b0eb4dcf 100644 --- a/i18n/hun/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "Ebben a kontextusban nem engedélyezett a(z) {0} parancs futtatása.", "recentlyUsed": "legutóbb használt", "morecCommands": "további parancsok", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "Parancs nem található" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index 8e8c7a2962e..165c4dd23c2 100644 --- a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "changes": "{0}. módosítás (összesen: {1})", + "change": "{0}. módosítás (összesen: {1})", + "show previous change": "Előző módosítás megjelenítése", + "show next change": "Következő módosítás megjelenítése", "editorGutterModifiedBackground": "A szerkesztőablak margójának háttérszíne a módosított soroknál.", "editorGutterAddedBackground": "A szerkesztőablak margójának háttérszíne a hozzáadott soroknál.", "editorGutterDeletedBackground": "A szerkesztőablak margójának háttérszíne a törölt soroknál.", diff --git a/i18n/hun/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index ed407924b94..9a084ee3454 100644 --- a/i18n/hun/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,7 @@ "exclude": "Globális minták konfigurálása fájlok és mappák keresésből való kizárásához. Örökli az összes globális mintát a fliex.exclude beállításból.", "exclude.boolean": "A globális minta, amire illesztve lesznek a fájlok elérési útjai. A minta engedélyezéséhez vagy letiltásához állítsa igaz vagy hamis értékre.", "exclude.when": "További ellenőrzés elvégzése az illeszkedő fájlok testvérein. Az illeszkedő fájl nevéhez használja a $(basename) változót!", - "useRipgrep": "Meghatározza, hogy a szövegben való kereséshez a ripgrep van-e használva.", + "useRipgrep": "Meghatározza, hogy a szövegben és fájlokban való kereséshez a ripgrep van-e használva.", "useIgnoreFilesByDefault": "Meghatározza, hogy a .gitignore és .ignore fájlok használva vannak-e az új munkaterületeken a kereséshez.", "search.quickOpen.includeSymbols": "Meghatározza, hogy a fájlok gyors megnyitásánál megjelenjenek-e a globális szimbólumkereső találatai." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 81ca25b06ea..3fe3f8642b4 100644 --- a/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Keresési eredmények törlése", "FocusNextSearchResult.label": "Váltás a következő keresési eredményre", "FocusPreviousSearchResult.label": "Váltás az előző keresési eredményre", - "RemoveAction.label": "Eltávolítás", "file.replaceAll.label": "Összes cseréje", "match.replace.label": "Csere" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 94cfdc9e1d9..94208b9eca9 100644 --- a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Kódrészleteket szolgáltat.", "vscode.extension.contributes.snippets-language": "Azon nyelv azonosítója, amely számára szolgáltatva van ez a kódrészlet.", "vscode.extension.contributes.snippets-path": "A kódrészlet-fájl elérési útja. Az elérési út relatív a kiegészítő mappájához, és általában a következővel kezdődik: './snippets/',", - "badFile": "A(z) \"{0}\" kódrészletet tartalmazó fájlt nem sikerült beolvasni.", "badVariableUse": "A(z) \"{0}\" kódrészlet nagy valószínűséggel keveri a kódrészletváltozók és a kódrészlet-helyjelölők fogalmát. További információ a következő oldalon található: https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax", + "badFile": "A(z) \"{0}\" kódrészletet tartalmazó fájlt nem sikerült beolvasni.", "source.snippet": "Felhasználói kódrészlet", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 26736788a2f..ad07b544ef3 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -14,6 +14,7 @@ "runningTasks": "Futó feladatok megjelenítése", "tasks": "Feladatok", "TaskSystem.noHotSwap": "A feladatvégrehajtó motor megváltoztatása egy futó, aktív feladat esetén az ablak újraindítását igényli.", + "TaskServer.folderIgnored": "A(z) {0} mappa figyelmen kívül van hagyva, mert 0.1.0-s verziójú feladatkonfigurációt használ.", "TaskService.noBuildTask1": "Nincs buildelési feladat definiálva. Jelöljön meg egy feladatot az 'isBuildCommand' tulajdonsággal a tasks.json fájlban!", "TaskService.noBuildTask2": "Nincs buildelési feladat definiálva. Jelöljön meg egy feladatot a 'build' csoporttal a tasks.json fájlban!", "TaskService.noTestTask1": "Nincs tesztelési feladat definiálva. Jelöljön meg egy feladatot az 'isTestCommand' tulajdonsággal a tasks.json fájlban!", @@ -30,6 +31,7 @@ "TaskSystem.activeSame.noBackground": "A(z) '{0}' feladat már aktív. A feladat befejezéséhez használja `Feladat megszakítása` parancsot a Feladatok menüből!", "TaskSystem.active": "Már fut egy feladat. Szakítsa meg, mielőtt egy másik feladatot futtatna.", "TaskSystem.restartFailed": "Nem sikerült a(z) {0} feladat befejezése és újraindítása.", + "TaskService.noConfiguration": "Hiba: a(z) {0} feladatok felderítése nem szolgáltatott feladatot a következő konfigurációhoz:\n{1}\nA feladat figyelmen kívül lesz hagyva.\n", "TaskSystem.configurationErrors": "Hiba: a megadott feladatkonfigurációban validációs hibák vannak, és nem használható. Először javítsa ezeket a hibákat!", "taskService.ignoreingFolder": "Feladatkonfiguráció figyelmen kívül hagyva a munkaterület {0} nevű mappája esetében. Több mappás munkaterületen a feladatok támogatásához az összes mappának a 2.0-s verziójú feladatkonfigurációt kell használni.\n", "TaskSystem.invalidTaskJson": "Hiba. A tasks.json fájlban szintaktikai hibák találhatók. Javítsa ezeket a hibákat feladatvégrehajtás előtt.\n", diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index edc638fe092..9abe5fcaf6f 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -17,6 +17,7 @@ "terminal.integrated.fontFamily": "Meghatározza a terminál betűtípusát. Alapértelmezett értéke az editor.fontFamily értéke.", "terminal.integrated.fontSize": "Meghatározza a terminálban használt betű méretét, pixelekben.", "terminal.integrated.lineHeight": "Meghatározza a sormagasságot a terminálban. A tényleges méret a megadott szám és a terminál betűméretének szorzatából jön ki.", + "terminal.integrated.enableBold": "Engedélyezve van-e a félkövér szöveg a terminálban. A működéshez szükséges, hogy a terminál shell támogassa a félkövér betűket.", "terminal.integrated.cursorBlinking": "Meghatározza, hogy a terminál kurzora villog-e.", "terminal.integrated.cursorStyle": "Meghatározza a terminál kurzorának stílusát.", "terminal.integrated.scrollback": "Meghatározza, hogy a terminál legfeljebb hány sort tárol a pufferben.", diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 9883a94a201..c671a91c989 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Új terminál", "workbench.action.terminal.focus": "Váltás a terminálra", "workbench.action.terminal.focusNext": "Váltás a következő terminálra", - "workbench.action.terminal.focusAtIndex": "Váltás a(z) {0}. terminálra", "workbench.action.terminal.focusPrevious": "Váltás az előző terminálra", "workbench.action.terminal.paste": "Beillesztés az aktív terminálba", "workbench.action.terminal.DefaultShell": "Alapértelmezett shell kiválasztása", diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 15f0f130a04..1f792eaa3ac 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Másolás", - "createNewTerminal": "Új terminál", "paste": "Beillesztés", "selectAll": "Összes kijelölése", "clear": "Törlés" diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index babb2962c46..45f5c16180a 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "Rendben, ne jelenítse meg újra", "terminal.integrated.chooseWindowsShell": "Válassza ki a preferált terminál shellt! Ez később módosítható a beállításokban.", "terminalService.terminalCloseConfirmationSingular": "Van egy aktív terminálmunkamenet. Szeretné megszakítani?", - "terminalService.terminalCloseConfirmationPlural": "{0} aktív terminálmunkamenet van. Szeretné megszakítani?", - "yes": "Igen" + "terminalService.terminalCloseConfirmationPlural": "{0} aktív terminálmunkamenet van. Szeretné megszakítani?" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..209303272b7 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "A beállítások összefoglaló leírása. Ez a címke jelenik meg a beállítások fájlban egy különálló megjegyzésként.", + "vscode.extension.contributes.configuration.properties": "A konfigurációs tulajdonságok leírása.", + "scope.window.description": "Ablakspecifikus beállítás, ami konfigurálható a felhasználói vagy munkaterületi beállításokban.", + "scope.resource.description": "Erőforrásspecifikus beállítás, ami beállítható a felhasználói, munkaterületi és mappaszintű beállításokban.", + "scope.description": "A hatókör, amire a beállítás vonatkozik. Az elérhető hatókörök: `window` és `resource`.", + "vscode.extension.contributes.configuration": "Konfigurációs beállításokat szolgáltat.", + "invalid.title": "a 'configuration.title' értékét karakterláncként kell megadni", + "vscode.extension.contributes.defaultConfiguration": "Adott nyelvre vonatkozóan szerkesztőbeállításokat szolgáltat.", + "invalid.properties": "A 'configuration.properties' értékét egy objektumként kell megadni", + "invalid.allOf": "A 'configuration.allOf' elavult, és használata nem javasolt. Helyette több konfigurációs szakaszt kell átadni tömbként a 'configuration' értékeként.", + "workspaceConfig.folders.description": "A munkaterületre betöltött mappák listája.", + "workspaceConfig.path.description": "Egy fájl elérési útja, pl. `/root/folderA` vagy `./folderA` relatív elérési út esetén, ami a munkaterületfájl helye alapján lesz feloldva.", + "workspaceConfig.name.description": "A mappa neve. Nem kötelező megadni.", + "workspaceConfig.uri.description": "A mappa URI-ja", + "workspaceConfig.settings.description": "Munkaterület-beállítások", + "workspaceConfig.extensions.description": "Munkaterület-kiegészítők", + "unknownWorkspaceProperty": "Ismeretlen munkaterület-konfigurációs tulajdonság" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/hun/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/hun/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index c20612f1980..c5c7acc39f4 100644 --- a/i18n/hun/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/hun/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -6,6 +6,7 @@ { "schema.token.settings": "A token színe és stílusa.", "schema.token.foreground": "A token előtérszíne.", + "schema.token.background.warning": "A tokenek háttérszíne jelenleg nem támogatott.", "schema.token.fontStyle": "A szabály betűtípusának stílusa: 'italic', 'bold', 'underline', vagy ezek kombinációja", "schema.fontStyle.error": "A betűtípus stílusa 'italic', 'bold', 'underline', vagy ezek kombinációja lehet.", "schema.properties.name": "A szabály leírása.", diff --git a/i18n/hun/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/hun/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index b93f26958fa..1a824863bdd 100644 --- a/i18n/hun/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/hun/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -33,5 +33,6 @@ "schema.fontSize": "Betűkészlet használata esetén a betűkészlet mérete a szöveg betűkészletének méretéhez képest, százalékban. Ha nincs megadva, akkor a betűkészlet-definícióban megadott érték van használva.", "schema.fontId": "Betűkészlet használata esetén a betűkészlet azonosítója. Ha nincs megadva, akkor az első betűkészlet-definíció van használva.", "schema.light": "Fájlikon-társítások világos témák használata esetén. Nem kötelező megadni.", - "schema.highContrast": "Fájlikon-társítások nagy kontrasztú témák használata esetén. Nem kötelező megadni." + "schema.highContrast": "Fájlikon-társítások nagy kontrasztú témák használata esetén. Nem kötelező megadni.", + "schema.hidesExplorerArrows": "Meghatározza, hogy a fájlkezelőben megjelenő nyilak el legyenek-e rejtve, amikor ez a téma aktív." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/hun/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..4dace3f126c --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "TextMate-színtémákat szolgáltat.", + "vscode.extension.contributes.themes.id": "Az ikontéma felhasználói beállításokban használt azonosítója.", + "vscode.extension.contributes.themes.label": "A színtéma felhasználói felületen megjelenő neve.", + "vscode.extension.contributes.themes.uiTheme": "A szerkesztőablak körül megjelenő elemek alaptémája. A 'vs' a világos, a 'vs-dark' a sötét színtéma, a 'hc-black' pedig a sötét, nagy kontrasztú téma.", + "vscode.extension.contributes.themes.path": "A tmTheme-fájl elérési útja. Az elérési út relatív a kiegészítő mappájához képest, és általában './themes/themeFile.tmTheme'.", + "reqarray": "a(z) `{0}` kiegszítési pontot tömbként kell megadni", + "reqpath": "Hiányzó karakterlánc a `contributes.{0}.path`-ban. A megadott érték: {1}", + "invalid.path.1": "A `contributes.{0}.path` ({1}) nem a kiegészítő mappáján belül található ({2}). Emiatt előfordulhat, hogy a kiegészítő nem lesz hordozható." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..91291d589e7 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Hiba a fájlikonokat leíró fájl feldolgozása közben: {0}" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..bdbe180864e --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Fájlikontémákat szolgáltat.", + "vscode.extension.contributes.iconThemes.id": "Az ikontéma felhasználói beállításokban használt azonosítója.", + "vscode.extension.contributes.iconThemes.label": "Az ikontéma felhasználói felületen megjelenő neve.", + "vscode.extension.contributes.iconThemes.path": "A témadefiníciós fájl elérési útja. Az elérési út relatív a kiegészítő mappájához képest, és általában ./icons/awesome-icon-theme.json'.", + "reqarray": "a(z) `{0}` kiegszítési pontot tömbként kell megadni", + "reqpath": "Hiányzó karakterlánc a `contributes.{0}.path`-ban. A megadott érték: {1}", + "reqid": "Hiányzó karakterlánc a `contributes.{0}.id`-ben. A megadott érték: {1}", + "invalid.path.1": "A `contributes.{0}.path` ({1}) nem a kiegészítő mappáján belül található ({2}). Emiatt előfordulhat, hogy a kiegészítő nem lesz hordozható." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index c1c24477811..f65a2da76bc 100644 --- a/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "TextMate-színtémákat szolgáltat.", - "vscode.extension.contributes.themes.id": "A téma felhasználói beállításokban használt azonosítója.", - "vscode.extension.contributes.themes.label": "A színtéma felhasználói felületen megjelenő neve.", - "vscode.extension.contributes.themes.uiTheme": "A szerkesztőablak körül megjelenő elemek alaptémája. A 'vs' a világos, a 'vs-dark' a sötét színtéma, a 'hc-black' pedig a sötét, nagy kontrasztú téma.", - "vscode.extension.contributes.themes.path": "A tmTheme-fájl elérési útja. Az elérési út relatív a kiegészítő mappájához képest, és általában './themes/themeFile.tmTheme'.", - "vscode.extension.contributes.iconThemes": "Fájlikontémákat szolgáltat.", - "vscode.extension.contributes.iconThemes.id": "Az ikontéma felhasználói beállításokban használt azonosítója.", - "vscode.extension.contributes.iconThemes.label": "Az ikontéma felhasználói felületen megjelenő neve.", - "vscode.extension.contributes.iconThemes.path": "A témadefiníciós fájl elérési útja. Az elérési út relatív a kiegészítő mappájához képest, és általában ./icons/awesome-icon-theme.json'.", "migration.completed": "Új témabeállítások lettek hozzáadva a felhasználói beállításokhoz. Biztonsági mentés a következő helyen érhető el: {0}.", "error.cannotloadtheme": "Nem sikerült betölteni a(z) '{0}' témát: {1}.", - "reqarray": "a(z) `{0}` kiegszítési pontot tömbként kell megadni", - "reqpath": "Hiányzó karakterlánc a `contributes.{0}.path`-ban. A megadott érték: {1}", - "invalid.path.1": "A `contributes.{0}.path` ({1}) nem a kiegészítő mappáján belül található ({2}). Emiatt előfordulhat, hogy a kiegészítő nem lesz hordozható.", - "reqid": "Hiányzó karakterlánc a `contributes.{0}.id`-ben. A megadott érték: {1}", "error.cannotloadicontheme": "Nem sikerült megnyitni a(z) '{0}' témát", - "error.cannotparseicontheme": "Hiba a fájlikonokat leíró fájl feldolgozása közben: {0}", "colorTheme": "Meghatározza a munkaterületen használt színtémát.", "colorThemeError": "A téma ismeretlen vagy nincs telepítve.", "iconTheme": "Meghatározza a munkaterületen használt ikontémát. 'null' érték esetén nem jelenik meg egyetlen fájlikon sem.", "noIconThemeDesc": "Nincsenek fájlikonok", "iconThemeError": "A fájlikontéma ismeretlen vagy nincs telepítve.", "workbenchColors": "Felülírja az aktuális színtémában definiált színeket.", - "workbenchColors.deprecated": "A beállítás már nem kísérleti, és át lett nevezve 'workbench.colorCustomizations'-re.", - "workbenchColors.deprecatedDescription": "Használja a 'workbench.colorCustomizations' tulajdonságot helyette.", "editorColors": "Felülírja az aktuális színtémában definiált, szerkesztőablakhoz kapcsolódó színeket és betűstílusokat.", "editorColors.comments": "Meghatározza a megjegyzések színét és stílusát.", "editorColors.strings": "Meghatározza a sztringliterálok színét és stílusát.", diff --git a/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..dbbe55dc9e3 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Munkaterület konfigurációs fájljának megnyitása", + "close": "Bezárás" +} \ No newline at end of file diff --git a/i18n/ita/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/ita/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index da8de5ed00e..f99b5799775 100644 --- a/i18n/ita/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/ita/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "ad esempio myFile.txt", - "activeEditorMedium": "ad esempio myFolder/myFile.txt", - "activeEditorLong": "ad esempio /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "ad es. myFolder1, myFolder2, myFolder3", - "rootPath": "ad esempio /Users/Development/myProject", - "folderName": "ad es. myFolder", - "folderPath": "ad es. /Users/Development/myFolder", + "activeEditorShort": "il nome del file (ad esempio MyFile.txt)", + "activeEditorMedium": "il percorso del file relativo alla cartella dell'area di lavoro (ad es. myFolder/myFile.txt)", + "activeEditorLong": "il percorso completo del file (ad es. /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "nome dell'area di lavoro (ad es. myFolder o myWorkspace)", + "rootPath": "percorso dell'area di lavoro (ad es. /Users/Development/myWorkspace)", + "folderName": "nome della cartella dell'area di lavoro in cui è contenuto il file (ad es. myFolder)", + "folderPath": "percorso della cartella dell'area di lavoro in cui è contenuto il file (ad es. /Users/Development/myFolder)", "appName": "ad esempio VS Code", "dirty": "un indicatore dirty se l'editor attivo è dirty", "separator": "un separatore condizionale (' - ') visualizzato solo se circondato da variabili con valori", diff --git a/i18n/ita/extensions/emmet/package.i18n.json b/i18n/ita/extensions/emmet/package.i18n.json index 6d5829bd5ff..f232e705ff6 100644 --- a/i18n/ita/extensions/emmet/package.i18n.json +++ b/i18n/ita/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Aumenta di 10", "command.decrementNumberByTen": "Riduci di 10", "emmetSyntaxProfiles": "Consente di definire il profilo per la sintassi specificata oppure di usare un profilo personalizzato con regole specifiche.", - "emmetExclude": "Matrice di linguaggi in cui le abbreviazioni Emmet non devono essere espanse.", - "emmetExtensionsPath": "Percorso di una cartella contenente snippet e profili Emmet.'", - "emmetShowExpandedAbbreviation": "Mostra le abbreviazioni emmet espanse come suggerimenti.\nL'opzione \"inMarkupAndStylesheetFilesOnly\" si applica a html, haml, jade, slim, xml, xsl, css, scss, sass, less e stylus.\nL'opzione \"sempre\" (always) si applica a tutte le parti del file indipendentemente dal markup/css.", - "emmetShowAbbreviationSuggestions": "Mostra possibili abbreviazioni emmet come suggerimenti. Non si applica a fogli di stile o quando emmet.showExpandedAbbreviation è impostata a \"mai\" (never).", - "emmetIncludeLanguages": "Abilita le abbreviazioni emmet in linguaggi che non sono normalmente supportati. Aggiungere un mapping tra il linguaggio ed il linguaggio supportato da emmet.\n Ad esempio: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Variabili da utilizzare nei frammenti di emmet", - "emmetTriggerExpansionOnTab": "Se abilitate, le abbreviazioni Emmet vengono espanse quando si preme TAB.", "emmetPreferences": "Preferenze usate per modificare il comportamento di alcune azioni e i resolver di Emmet.", "emmetPreferencesIntUnit": "Unità di misura predefinita per i valori integer", "emmetPreferencesFloatUnit": "Unità di misura predefinita per i valori float", @@ -44,5 +37,7 @@ "emmetPreferencesCssBetween": "Simbolo da inserire tra la proprietà CSS e il valore quando si espandono le abbreviazioni CSS", "emmetPreferencesSassBetween": "Simbolo da inserire tra la proprietà CSS e il valore quando si espandono le abbreviazioni CSS nei file Sass", "emmetPreferencesStylusBetween": "Simbolo da inserire tra la proprietà CSS e il valore quando si espandono le abbreviazioni CSS nei file Stylus", - "emmetShowSuggestionsAsSnippets": "Se è true, i suggerimenti Emmet verranno visualizzati come frammenti consentendo di ordinarli in base all'impostazione editor.snippetSuggestions." + "emmetPreferencesFilterCommentBefore": "Una definizione di commento che deve essere inserita prima dell'elemento corrispondente quando viene applicato il filtro commenti.", + "emmetPreferencesFilterCommentAfter": "Una definizione di commento che deve essere posizionato dopo l'elemento corrispondente quando viene applicato il filtro commenti.", + "emmetPreferencesFilterCommentTrigger": "Un elenco delimitato da virgole di nomi di attributi che dovrebbero esistere come abbreviazione per il filtro commenti da applicare" } \ No newline at end of file diff --git a/i18n/ita/extensions/git/out/commands.i18n.json b/i18n/ita/extensions/git/out/commands.i18n.json index 16a12505d76..09e5850f8cd 100644 --- a/i18n/ita/extensions/git/out/commands.i18n.json +++ b/i18n/ita/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Clonazione del repository GIT...", "openrepo": "Apri repository", "proposeopen": "Aprire il repository clonato?", - "path to init": "Percorso della cartella", - "provide path": "Specificare un percorso di cartella per inizializzare un repository GIT", + "init repo": "Inizializza repository", + "create repo": "Inizializza repository", + "are you sure": "Questo creerà un repository Git in '{0}'. Sei sicuro di voler continuare?", "HEAD not available": "La versione HEAD di '{0}' non è disponibile.", "confirm stage files with merge conflicts": "Preparare per il commit {0} file con conflitti di merge?", "confirm stage file with merge conflicts": "Preparare per il commit {0} con conflitti di merge?", diff --git a/i18n/ita/extensions/git/out/repository.i18n.json b/i18n/ita/extensions/git/out/repository.i18n.json index 0b2210016a0..9088cc9c340 100644 --- a/i18n/ita/extensions/git/out/repository.i18n.json +++ b/i18n/ita/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Eliminato da noi", "both added": "Entrambi aggiunti", "both modified": "Entrambi modificati", + "untracked, short": "U", + "modified, short": "M", "commit": "Esegui commit", "merge changes": "Esegui merge delle modifiche", "staged changes": "Modifiche preparate per il commit", diff --git a/i18n/ita/extensions/git/package.i18n.json b/i18n/ita/extensions/git/package.i18n.json index fd78ff2a50b..8844282381c 100644 --- a/i18n/ita/extensions/git/package.i18n.json +++ b/i18n/ita/extensions/git/package.i18n.json @@ -15,6 +15,8 @@ "command.stageAll": "Prepara tutte le modifiche per commit", "command.stageSelectedRanges": "Prepara per il commit intervalli selezionati", "command.revertSelectedRanges": "Ripristina intervalli selezionati", + "command.stageChange": "Prepara modifica per commit", + "command.revertChange": "Annulla modifica", "command.unstage": "Annulla preparazione modifiche per commit", "command.unstageAll": "Annulla preparazione di tutte le modifiche per commit", "command.unstageSelectedRanges": "Annulla preparazione per il commit di intervalli selezionati", diff --git a/i18n/ita/extensions/typescript/package.i18n.json b/i18n/ita/extensions/typescript/package.i18n.json index 21866260c71..e881e2dc9e0 100644 --- a/i18n/ita/extensions/typescript/package.i18n.json +++ b/i18n/ita/extensions/typescript/package.i18n.json @@ -44,7 +44,8 @@ "typescript.npm": "Specifica il percorso dell'eseguibile NPM utilizzato per l'acquisizione automatica delle definizioni di tipi. Richiede TypeScript >= 2.3.4.", "typescript.check.npmIsInstalled": "Controlla se NPM è installato per l'acquisizione automatica delle definizioni di tipi", "javascript.nameSuggestions": "Abilita/disabilita l'inclusione di nomi univoci dal file negli elenchi di suggerimento di JavaScript.", - "typescript.tsc.autoDetect": "Controlla se la rilevazione automatica di attività tsc è on/off.", + "typescript.tsc.autoDetect": "Controlla l'auto-rilevazione di attività di tsc. 'off' disabilita questa funzionalità. 'build' crea solo attività di singola compilazione esecuzione. 'watch' crea solo attività di compilazione e controllo. 'on' crea attività sia di tipo 'build' che 'watch'. Il valore predefinito è 'on'.", "typescript.problemMatchers.tsc.label": "Problemi TypeScript", - "typescript.problemMatchers.tscWatch.label": "Problemi TypeScript (modalità espressione di controllo)" + "typescript.problemMatchers.tscWatch.label": "Problemi TypeScript (modalità espressione di controllo)", + "typescript.quickSuggestionsForPaths": "Attiva/Disattiva suggerimenti rapidi quando si digita un percorso di importazione." } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/ita/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 76cf5a81fb0..97a23bba223 100644 --- a/i18n/ita/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Sostituisci", "label.replaceAllButton": "Sostituisci tutto", "label.toggleReplaceButton": "Attiva/Disattiva modalità sostituzione", - "title.matchesCountLimit": "Vengono evidenziati solo i primi 999 risultati, ma tutte le operazioni di ricerca funzionano sull'intero testo.", "label.matchesLocation": "{0} di {1}", "label.noResults": "Nessun risultato" } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/ita/src/vs/editor/contrib/find/common/findController.i18n.json index 0b6e1248aab..753c08a072a 100644 --- a/i18n/ita/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Trova selezione successiva", "previousSelectionMatchFindAction": "Trova selezione precedente", "startReplace": "Sostituisci", - "addSelectionToNextFindMatch": "Aggiungi selezione a risultato ricerca successivo", - "addSelectionToPreviousFindMatch": "Aggiungi selezione a risultato ricerca precedente", - "moveSelectionToNextFindMatch": "Sposta ultima selezione a risultato ricerca successivo", - "moveSelectionToPreviousFindMatch": "Sposta ultima selezione a risultato ricerca precedente", - "selectAllOccurrencesOfFindMatch": "Seleziona tutte le occorrenze del risultato ricerca", - "changeAll.label": "Cambia tutte le occorrenze", "showNextFindTermAction": "Mostra il termine di ricerca successivo", "showPreviousFindTermAction": "Mostra il termine di ricerca precedente" } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/ita/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 732a2e19079..af2b081d453 100644 --- a/i18n/ita/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Aggiungi cursore sopra", "mutlicursor.insertBelow": "Aggiungi cursore sotto", - "mutlicursor.insertAtEndOfEachLineSelected": "Aggiungi cursore alla fine delle righe" + "mutlicursor.insertAtEndOfEachLineSelected": "Aggiungi cursore alla fine delle righe", + "addSelectionToNextFindMatch": "Aggiungi selezione a risultato ricerca successivo", + "addSelectionToPreviousFindMatch": "Aggiungi selezione a risultato ricerca precedente", + "moveSelectionToNextFindMatch": "Sposta ultima selezione a risultato ricerca successivo", + "moveSelectionToPreviousFindMatch": "Sposta ultima selezione a risultato ricerca precedente", + "selectAllOccurrencesOfFindMatch": "Seleziona tutte le occorrenze del risultato ricerca", + "changeAll.label": "Cambia tutte le occorrenze" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json index 8e09cda877c..1d0c0c88c61 100644 --- a/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Formato colore non valido. Usare #RGB, #RGBA, #RRGGBB o #RRGGBBAA", "schema.colors": "Colori usati nell'area di lavoro.", "foreground": "Colore primo piano. Questo colore è utilizzato solo se non viene sovrascritto da un componente.", "errorForeground": "Colore primo piano globale per i messaggi di errore. Questo colore è utilizzato solamente se non viene sottoposto a override da un componente.", diff --git a/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 4d31bf1f0c4..91e26eba907 100644 --- a/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -13,6 +13,7 @@ "select": "&&Seleziona", "selectWorkspace": "Seleziona cartelle per l'area di lavoro", "removeFolderFromWorkspace": "Rimuovi cartella dall'area di lavoro", + "openFolderSettings": "Apri impostazioni cartella", "saveWorkspaceAsAction": "Salva area di lavoro come...", "save": "&&Salva", "saveWorkspace": "Salva area di lavoro", diff --git a/i18n/ita/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index d8cbee32bd5..bee5fb6341a 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Nascondi barra attività", - "activityBarAriaLabel": "Cambio visualizzazione attiva", "globalActions": "Azioni globali" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..33e0b7a1979 --- /dev/null +++ b/i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Cambio visualizzazione attiva" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..427b8914624 --- /dev/null +++ b/i18n/ita/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "Visualizzazioni aggiuntive", + "numberBadge": "{0} ({1})", + "manageExtension": "Gestisci estensione", + "titleKeybinding": "{0} ({1})", + "toggle": "Attiva/Disattiva visualizzazione bloccata" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 766b02a726a..aa914d12c1d 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "Mostra editor nel secondo gruppo", "groupThreePicker": "Mostra editor nel terzo gruppo", "allEditorsPicker": "Mostra tutti gli editor aperti", - "view": "Visualizza" + "view": "Visualizza", + "file": "File" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 9b0548995db..358f121a809 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "Il comando '{0}' non è attualmente abilitato e non può essere eseguito.", "manageExtension": "Gestisci estensione" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json index 52b4f223124..f17ae8d5fa8 100644 --- a/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,14 @@ "workspaces": "Aree di lavoro", "developer": "Sviluppatore", "showEditorTabs": "Controlla se visualizzare o meno gli editor aperti in schede.", - "workbench.editor.labelFormat.default": "Visualizza il nome del file. Quando le schede sono abilitate e due file presentano lo stesso nome in un unico gruppo, vengono aggiunte le sezioni distintive del percorso di ciascun file. Quando le schede sono disabilitate, viene visualizzato il percorso relativo alla radice dell'area di lavoro se l'editor è attivo.", "workbench.editor.labelFormat.short": "Visualizza il nome del file seguito dal relativo nome di directory.", - "workbench.editor.labelFormat.medium": "Visualizza il nome del file seguito dal percorso corrispondente relativo alla radice dell'area di lavoro.", "workbench.editor.labelFormat.long": "Visualizza il nome del file seguito dal relativo percorso assoluto.", "tabDescription": "Controlla il formato dell'etichetta per un editor. Se si modifica questa impostazione, ad esempio, risulterà più agevole individuare il percorso di un file:\n- short: 'parent'\n- medium: 'workspace/src/parent'\n- long: '/home/user/workspace/src/parent'\n- default: '.../parent', quando un'altra scheda condivide lo stesso titolo, oppure il percorso relativo dell'area di lavoro se le schede sono disabilitate", "editorTabCloseButton": "Controlla la posizione dei pulsanti di chiusura delle schede dell'editor oppure li disabilita quando è impostata su 'off'.", "showIcons": "Controlla se visualizzare o meno un'icona per gli editor aperti. Richiede l'abilitazione anche di un tema dell'icona.", "enablePreview": "Controlla se gli editor aperti vengono visualizzati come anteprima. Le anteprime editor vengono riutilizzate finché vengono mantenute (ad esempio tramite doppio clic o modifica) e vengono visualizzate in corsivo.", "enablePreviewFromQuickOpen": "Controlla se gli editor aperti da Quick Open vengono visualizzati come anteprima. Le anteprime editor vengono riutilizzate finché vengono mantenute, ad esempio tramite doppio clic o modifica.", - "editorOpenPositioning": "Controlla la posizione in cui vengono aperti gli editor. Selezionare 'left' o 'right' per aprire gli editor a sinistra o a destra di quello attualmente attivo. Selezionare 'first' o 'last' per aprire gli editor indipendentemente da quello attualmente attivo.", "revealIfOpen": "Controlla se un editor viene visualizzato in uno qualsiasi dei gruppi visibili se viene aperto. Se l'opzione è disabilitata, un editor verrà aperto preferibilmente nel gruppo di editor attualmente attivo. Se è abilitata, un editor già aperto verrà visualizzato e non aperto di nuovo nel gruppo di editor attualmente attivo. Nota: in alcuni casi questa impostazione viene ignorata, ad esempio quando si forza l'apertura di un editor in un gruppo specifico oppure a lato del gruppo attualmente attivo.", - "commandHistory": "Controlla il numero di comandi usati di recente da mantenere nella cronologia per il riquadro comandi. Impostare su 0 per disabilitare la cronologia dei comandi.", "preserveInput": "Controlla se l'ultimo input digitato nel riquadro comandi deve essere ripristinato alla successiva riapertura del riquadro.", "closeOnFocusLost": "Controlla se Quick Open deve essere chiuso automaticamente quando perde lo stato attivo.", "openDefaultSettings": "Controlla se all'apertura delle impostazioni viene aperto anche un editor che mostra tutte le impostazioni predefinite.", @@ -50,7 +46,6 @@ "restoreWindows": "Controlla la modalità di riapertura delle finestre dopo un riavvio. Selezionare 'none' per iniziare sempre con un'area di lavoro vuota, 'one' per riaprire l'ultima finestra usata, 'folders' per riaprire tutte le finestre con cartelle aperte oppure 'all' per riaprire tutte le finestre dell'ultima sessione.", "restoreFullscreen": "Controlla se una finestra deve essere ripristinata a schermo intero se è stata chiusa in questa modalità.", "zoomLevel": "Consente di modificare il livello di zoom della finestra. Il valore originale è 0 e ogni incremento superiore (ad esempio 1) o inferiore (ad esempio -1) rappresenta un aumento o una diminuzione del 20% della percentuale di zoom. È anche possibile immettere valori decimali per modificare il livello di zoom con maggiore granularità.", - "title": "Controlla il titolo della finestra in base all'editor attivo. Le variabili vengono sostituite in base al contesto:\n${activeEditorShort}: ad esempio myFile.txt\n${activeEditorMedium}: ad esempio myFolder/myFile.txt\n${activeEditorLong}: ad esempio /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: ad esempio myFolder\n${folderPath}: ad esempio /Users/Development/myFolder\n${rootName}: ad esempio myFolder1, myFolder2, myFolder3\n${rootPath}: ad esempio /Users/Development/myWorkspace\n${appName}: ad esempio VS Code\n${dirty}: indicatore dirty se l'editor attivo è dirty\n${separator}: separatore condizionale (\" - \") visualizzato solo quando è racchiuso tra variabili con valori", "window.newWindowDimensions.default": "Apre nuove finestre al centro della schermata.", "window.newWindowDimensions.inherit": "Apre nuove finestre le cui dimensioni sono uguali a quelle dell'ultima finestra attiva.", "window.newWindowDimensions.maximized": "Apre nuove finestre ingrandite a schermo intero.", diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index b3b797b17a0..cd95d333b64 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, debug", "debugAriaLabel": "Digitare il nome di una configurazione di avvio da eseguire.", + "addConfigTo": "Aggiungi configurazione ({0})...", + "addConfiguration": "Aggiungi configurazione...", "noConfigurationsMatching": "Non esistono configurazioni di debug corrispondenti", "noConfigurationsFound": "Non è stata trovata alcuna configurazione di debug. Creare un file 'launch.json'." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..8eeb71caf1a --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Debug" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 2b0ce6dfdf4..7729690837e 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Configurazioni per generare la versione iniziale di 'launch.json'.", "vscode.extension.contributes.debuggers.languages": "Elenco dei linguaggi. per cui l'estensione di debug può essere considerata il \"debugger predefinito\".", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Se è specificato, Visual Studio Code chiamerà questo comando per determinare il percorso eseguibile della scheda di debug e gli argomenti da passare.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Se è specificato, Visual Studio Code chiamerà questo comando per le azioni \"debug\" o \"run\" previste come destinazione di questa estensione.", "vscode.extension.contributes.debuggers.configurationSnippets": "Frammenti per l'aggiunta di nuove configurazioni in 'launch.json'.", "vscode.extension.contributes.debuggers.configurationAttributes": "Configurazioni dello schema JSON per la convalida di 'launch.json'.", "vscode.extension.contributes.debuggers.windows": "Impostazioni specifiche di Windows.", diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 70ec9c0d711..c70e4e525c6 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,7 @@ "breakpointRemoved": "Rimosso un punto di interruzione a riga {0} del file {1}", "compoundMustHaveConfigurations": "Per avviare più configurazioni, deve essere impostato l'attributo \"configurations\" dell'elemento compounds.", "configMissing": "In 'launch.json' manca la configurazione '{0}'.", - "debugRequestNotSupported": "La configurazione di debug scelta contiene un valore di attributo `{0}` che non è supportato: '{1}'.", - "debugRequesMissing": "Nella configurazione di debug scelta manca l'attributo '{0}'.", "debugTypeNotSupported": "Il tipo di debug configurato '{0}' non è supportato.", - "debugTypeMissing": "Manca la proprietà 'type' per la configurazione di avvio scelta.", "preLaunchTaskErrors": "Sono stati rilevati errori di compilazione durante preLaunchTask '{0}'.", "preLaunchTaskError": "È stato rilevato un errore di compilazione durante preLaunchTask '{0}'.", "preLaunchTaskExitCode": "L'attività di preavvio '{0}' è stata terminata ed è stato restituito il codice di uscita {1}.", diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index fff7cbcba9e..2740934029a 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "Lo stato dell'oggetto viene acquisito dalla prima valutazione", "replVariableAriaLabel": "Il valore della variabile {0} è {1}, ciclo Read Eval Print, debug", "replExpressionAriaLabel": "Il valore dell'espressione {0} è {1}, ciclo Read Eval Print, debug", - "replValueOutputAriaLabel": "{0}, ciclo Read Eval Print, debug", - "replKeyValueOutputAriaLabel": "Il valore della variabile di output {0} è {1}, ciclo Read Eval Print, debug" + "replValueOutputAriaLabel": "{0}, ciclo Read Eval Print, debug" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/ita/src/vs/workbench/parts/files/browser/fileActions.i18n.json index f1f608e1731..d68d405085a 100644 --- a/i18n/ita/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -37,8 +37,6 @@ "openToSide": "Apri lateralmente", "compareSource": "Seleziona per il confronto", "globalCompareFile": "Confronta file attivo con...", - "pickHistory": "Selezionare un file aperto in precedenza per il confronto", - "unableToFileToCompare": "Non è possibile confrontare il file selezionato con '{0}'.", "openFileToCompare": "Aprire prima un file per confrontarlo con un altro file.", "compareWith": "Confronta '{0}' con '{1}'", "compareFiles": "Confronta file", @@ -47,7 +45,6 @@ "saveAs": "Salva con nome...", "saveAll": "Salva tutto", "saveAllInGroup": "Salva tutto nel gruppo", - "saveFiles": "Salva file modificati ma non salvati", "revert": "Ripristina file", "focusOpenEditors": "Stato attivo su visualizzazione editor aperti", "focusFilesExplorer": "Stato attivo su Esplora file", diff --git a/i18n/ita/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/ita/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 9ae2216ff99..586895b4e44 100644 --- a/i18n/ita/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,6 @@ { "noWorkspace": "Nessuna cartella aperta", "explorerSection": "Sezione Esplora file", - "noWorkspaceHelp": "Non ci sono ancora cartelle aperte.", + "noFolderHelp": "Non ci sono ancora cartelle aperte.", "openFolder": "Apri cartella" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..bcb8c50044f --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Problemi" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 237ebccfb39..36b2ac76a3a 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Inserire le impostazioni qui per sovrascrivere quelle predefinite.", - "errorInvalidConfiguration": "Impossibile scrivere nelle impostazioni. Correggere eventuali errori o avvisi nel file e riprovare.", "emptyWorkspaceSettingsHeader": "Inserire le impostazioni qui per sovrascrivere le impostazioni utente.", "emptyFolderSettingsHeader": "Inserire le impostazioni cartella qui per sovrascrivere quelle dell'area di lavoro.", "defaultFolderSettingsTitle": "Impostazioni cartella predefinite", diff --git a/i18n/ita/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/ita/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 28964d0cf5c..543c602df83 100644 --- a/i18n/ita/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "Il comando '{0}' non è abilitato nel contesto corrente.", "recentlyUsed": "usate di recente", "morecCommands": "altri comandi", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "Non ci sono comandi corrispondenti" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index 7b4843f3a16..65fd721bb17 100644 --- a/i18n/ita/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,6 @@ "exclude": "Consente di configurare i criteri GLOB per escludere file e cartelle nelle ricerche. Eredita tutti i criteri GLOB dall'impostazione files.exclude.", "exclude.boolean": "Criterio GLOB da usare per trovare percorsi file. Impostare su True o False per abilitare o disabilitare il criterio.", "exclude.when": "Controllo aggiuntivo sugli elementi di pari livello di un file corrispondente. Usare $(basename) come variabile del nome file corrispondente.", - "useRipgrep": "Controlla se usare ripgrep durante la ricerca di testo", "useIgnoreFilesByDefault": "Controlla se utilizzare i file .gitignore e .ignore come impostazione predefinita durante la ricerca in una nuova area di lavoro", "search.quickOpen.includeSymbols": "Configurare questa opzione per includere i risultati di una ricerca di simboli globale nei risultati dei file per Quick Open." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 942721004df..7faf8ff218a 100644 --- a/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Cancella risultati della ricerca", "FocusNextSearchResult.label": "Sposta lo stato attivo sul risultato della ricerca successivo", "FocusPreviousSearchResult.label": "Sposta lo stato attivo sul risultato della ricerca precedente", - "RemoveAction.label": "Rimuovi", "file.replaceAll.label": "Sostituisci tutto", "match.replace.label": "Sostituisci" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 09e4993b61b..8b2ae57561b 100644 --- a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Frammenti per contributes.", "vscode.extension.contributes.snippets-language": "Identificatore di linguaggio per cui si aggiunge come contributo questo frammento.", "vscode.extension.contributes.snippets-path": "Percorso del file snippets. È relativo alla cartella delle estensioni e in genere inizia con './snippets/'.", - "badFile": "Non è stato possibile leggere il file di frammento \"{0}\".", "badVariableUse": "Il frammento \"{0}\" molto probabilmente confonde variabili-frammento con segnaposti-frammento. Vedere https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax per ulteriori dettagli.", + "badFile": "Non è stato possibile leggere il file di frammento \"{0}\".", "source.snippet": "Frammento utente", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index ad495da28bf..9941d145008 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Nuovo terminale", "workbench.action.terminal.focus": "Sposta stato attivo su terminale", "workbench.action.terminal.focusNext": "Sposta stato attivo su terminale successivo", - "workbench.action.terminal.focusAtIndex": "Sposta stato attivo su terminale {0}", "workbench.action.terminal.focusPrevious": "Sposta stato attivo su terminale precedente", "workbench.action.terminal.paste": "Incolla nel terminale attivo", "workbench.action.terminal.DefaultShell": "Selezionare la Shell di Default", diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index e32834163e9..adc0b4440da 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Copia", - "createNewTerminal": "Nuovo terminale", "paste": "Incolla", "selectAll": "Seleziona tutto", "clear": "Cancella" diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index e21d2d1aaf0..6055f7da096 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "OK, non visualizzare più", "terminal.integrated.chooseWindowsShell": "Seleziona la shell di terminale preferita - è possibile modificare questa impostazione dopo", "terminalService.terminalCloseConfirmationSingular": "C'è una sessione di terminale attiva. Terminarla?", - "terminalService.terminalCloseConfirmationPlural": "Ci sono {0} sessioni di terminale attive. Terminarle?", - "yes": "Sì" + "terminalService.terminalCloseConfirmationPlural": "Ci sono {0} sessioni di terminale attive. Terminarle?" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..afd8ffa11fc --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -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. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Riepilogo delle impostazioni. Questa etichetta verrà usata nel file di impostazioni come commento di separazione.", + "vscode.extension.contributes.configuration.properties": "Descrizione delle proprietà di configurazione.", + "scope.window.description": "Configurazione specifica della finestra, che può essere configurata nelle impostazioni dell'utente o dell'area di lavoro.", + "scope.resource.description": "Configurazione specifica di risorse, che possono essere configurate nelle impostazioni utente, in quelle dell'area di lavoro o di una cartella.", + "vscode.extension.contributes.configuration": "Impostazioni di configurazione di contributes.", + "invalid.title": "'configuration.title' deve essere una stringa", + "vscode.extension.contributes.defaultConfiguration": "Aggiunge come contributo le impostazioni di configurazione predefinite dell'editor in base al linguaggio.", + "invalid.properties": "'configuration.properties' deve essere un oggetto", + "invalid.allOf": "'configuration.allOf' è deprecato e non deve più essere usato. Passare invece una matrice di sezioni di configurazione al punto di aggiunta contributo 'configuration'.", + "workspaceConfig.folders.description": "Elenco di cartelle da caricare nell'area di lavoro.", + "workspaceConfig.path.description": "Percorso di file, ad esempio `/root/folderA` o `./folderA` per un percorso relativo che verrà risolto in base alla posizione del file dell'area di lavoro.", + "workspaceConfig.name.description": "Nome facoltativo per la cartella. ", + "unknownWorkspaceProperty": "La proprietà di configurazione dell'area di lavoro è sconosciuta" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/ita/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/ita/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..34e0bc8f5e8 --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contributes textmate color themes.", + "vscode.extension.contributes.themes.id": "ID del tema dell'icona usato nelle impostazioni utente.", + "vscode.extension.contributes.themes.label": "Etichetta del tema colori visualizzata nell'interfaccia utente.", + "vscode.extension.contributes.themes.uiTheme": "Tema di base che definisce i colori nell'editor: 'vs' è il tema colori chiaro, mentre 'vs-dark' è il tema colori scuro e 'hc-black' è il tema a contrasto elevato scuro.", + "vscode.extension.contributes.themes.path": "Percorso del file tmTheme. È relativo alla cartella delle estensioni e corrisponde in genere a './themes/themeFile.tmTheme'.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "È previsto un valore stringa in `contributes.{0}.path`. Valore specificato: {1}", + "invalid.path.1": "Valore previsto di `contributes.{0}.path` ({1}) da includere nella cartella dell'estensione ({2}). L'estensione potrebbe non essere più portatile." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..b0f9faf6b52 --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problems parsing file icons file: {0}" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..53cc79371c9 --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "ID del tema dell'icona usato nelle impostazioni utente.", + "vscode.extension.contributes.iconThemes.label": "Etichetta del tema dell'icona visualizzata nell'interfaccia utente.", + "vscode.extension.contributes.iconThemes.path": "Percorso del file di definizione del tema dell'icona. È relativo alla cartella delle estensioni e corrisponde in genere a './icons/awesome-icon-theme.json'.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "È previsto un valore stringa in `contributes.{0}.path`. Valore specificato: {1}", + "reqid": "È previsto un valore stringa in `contributes.{0}.id`. Valore specificato: {1}", + "invalid.path.1": "Valore previsto di `contributes.{0}.path` ({1}) da includere nella cartella dell'estensione ({2}). L'estensione potrebbe non essere più portatile." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index d6ed75ea2e1..97d1cdc1754 100644 --- a/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "ID del tema dell'icona usato nelle impostazioni utente.", - "vscode.extension.contributes.themes.label": "Etichetta del tema colori visualizzata nell'interfaccia utente.", - "vscode.extension.contributes.themes.uiTheme": "Tema di base che definisce i colori nell'editor: 'vs' è il tema colori chiaro, mentre 'vs-dark' è il tema colori scuro e 'hc-black' è il tema a contrasto elevato scuro.", - "vscode.extension.contributes.themes.path": "Percorso del file tmTheme. È relativo alla cartella delle estensioni e corrisponde in genere a './themes/themeFile.tmTheme'.", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "ID del tema dell'icona usato nelle impostazioni utente.", - "vscode.extension.contributes.iconThemes.label": "Etichetta del tema dell'icona visualizzata nell'interfaccia utente.", - "vscode.extension.contributes.iconThemes.path": "Percorso del file di definizione del tema dell'icona. È relativo alla cartella delle estensioni e corrisponde in genere a './icons/awesome-icon-theme.json'.", "migration.completed": "Sono state aggiunte nuove impostazioni tema alle impostazioni utente. Backup disponibile in {0}.", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "È previsto un valore stringa in `contributes.{0}.path`. Valore specificato: {1}", - "invalid.path.1": "Valore previsto di `contributes.{0}.path` ({1}) da includere nella cartella dell'estensione ({2}). L'estensione potrebbe non essere più portatile.", - "reqid": "È previsto un valore stringa in `contributes.{0}.id`. Valore specificato: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "Specifica il tema dell'icona usato nell'area di lavoro oppure 'null' se non viene visualizzato alcun icona di file.", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Sostituisce i colori del tema colori attualmente selezionato.", - "workbenchColors.deprecated": "L'impostazione non è più sperimentale ed è stata rinominata in 'workbench.colorCustomizations'", - "workbenchColors.deprecatedDescription": "In alternativa, usare 'workbench.colorCustomizations'", "editorColors": "Sostituisce i colori dell'editor e lo stile dei font nel tema colori attualmente selezionato.", "editorColors.comments": "Imposta i colori e gli stili per i commenti", "editorColors.strings": "Imposta i colori e gli stili per i valori letterali stringa.", diff --git a/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..5cfa730d8ff --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Apri file di configurazione dell'area di lavoro", + "close": "Chiudi" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 7c9fffc491f..f8b65e69685 100644 --- a/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "例: myFile.txt", - "activeEditorMedium": "例: myFolder/myFile.txt", - "activeEditorLong": "例: /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "例: myFolder1, myFolder2, myFolder3", - "rootPath": "例: /Users/Development/myProject", - "folderName": "例: myFolder", - "folderPath": "例: /Users/Development/myFolder", + "activeEditorShort": "ファイル名 (例: myFile.txt)", + "activeEditorMedium": "ワークスペース フォルダーに相対的なファイルのパス (例: myFolder/myFile.txt)", + "activeEditorLong": "ファイルの完全なパス (例: /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "ワークスペースの名前 (例: myFolder または myWorkspace)", + "rootPath": "ワークスペースのファイル パス (例: /Users/Development/myWorkspace)", + "folderName": "ファイルが含まれているワークスペース フォルダーの名前 (例: myFolder)", + "folderPath": "ファイルが含まれているワークスペース フォルダーのファイル パス (例: /Users/Development/myFolder)", "appName": "例: VS Code", "dirty": "アクティブなエディターがダーティである場合のダーティ インジケーター", "separator": "値のある変数で囲まれた場合にのみ表示される条件付き区切り記号 (' - ')", diff --git a/i18n/jpn/extensions/emmet/package.i18n.json b/i18n/jpn/extensions/emmet/package.i18n.json index d8400d06d02..01629a8bcec 100644 --- a/i18n/jpn/extensions/emmet/package.i18n.json +++ b/i18n/jpn/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "10 ずつ増加", "command.decrementNumberByTen": "10 ずつ減少", "emmetSyntaxProfiles": "指定した構文に対してプロファイルを定義するか、特定の規則がある独自のプロファイルをご使用ください。", - "emmetExclude": "Emmet 省略記法を展開すべきでない言語の配列。", - "emmetExtensionsPath": "Emmet のプロファイルとスニペットを含むフォルダーへのパス。", - "emmetShowExpandedAbbreviation": "候補として、展開された Emmet 省略記法を表示します。\n\"inMarkupAndStylesheetFilesOnly\" オプションは、html、haml、jade、slim、xml、xsl、css、scss、sass、less、および stylus に適用されます。\n\"always\" オプションは、マークアップ / css に関係なく、ファイルのすべての部分に適用されます。", - "emmetShowAbbreviationSuggestions": "候補として考えられる Emmet 省略記法を表示します。 スタイルシートや emmet.showExpandedAbbreviation が \"never\" に設定されている場合は適用されません。", - "emmetIncludeLanguages": "既定でサポートされていない言語で Emmet 省略記法を有効にします。 言語と Emmet がサポートする言語の間にマッピングを追加します。\n例: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Emmet のスニペットで使用される変数 ", - "emmetTriggerExpansionOnTab": "これをオンにすると、TAB キーを押したときに emmet 省略記法が展開されます.", "emmetPreferences": "Emmet の一部のアクションやリゾルバーの動作の変更に使用される基本設定。", "emmetPreferencesIntUnit": "整数値に使用する既定の単位", "emmetPreferencesFloatUnit": "float 値に使用する既定の単位", @@ -44,5 +37,7 @@ "emmetPreferencesCssBetween": "CSS の略語を展開するときに CSS プロパティと値の間に配置されるシンボル ", "emmetPreferencesSassBetween": "Sass ファイルで CSS の略語を展開するときに CSS プロパティと値の間に配置されるシンボル ", "emmetPreferencesStylusBetween": "Stylus ファイルで CSS の略語を展開するときに CSS プロパティと値の間に配置されるシンボル ", - "emmetShowSuggestionsAsSnippets": "true の場合、emmet 候補では、editor.snippetSuggestions 設定に従ってそれらを並べてスニペットとして表示されます。" + "emmetPreferencesFilterCommentBefore": "コメント フィルター使用時、一致した要素の前に配置するコメントの定義。 ", + "emmetPreferencesFilterCommentAfter": "コメント フィルター使用時、一致した要素の後に配置するコメントの定義。", + "emmetPreferencesFilterCommentTrigger": "コメント フィルターに適用される略語に存在する属性名のカンマ区切りのリスト" } \ No newline at end of file diff --git a/i18n/jpn/extensions/git/out/commands.i18n.json b/i18n/jpn/extensions/git/out/commands.i18n.json index af7b32febd1..e825de0716d 100644 --- a/i18n/jpn/extensions/git/out/commands.i18n.json +++ b/i18n/jpn/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Git リポジトリを複製しています...", "openrepo": "リポジトリを開く", "proposeopen": "複製したリポジトリを開きますか?", - "path to init": "フォルダーのパス", - "provide path": "初期化する Git リポジトリへのフォルダー パスを入力してください", + "init repo": "リポジトリの初期化", + "create repo": "リポジトリの初期化", + "are you sure": "'{0}' に Git リポジトリを作成します。続行してもよろしいですか?", "HEAD not available": "'{0}' の HEAD バージョンは利用できません。", "confirm stage files with merge conflicts": "マージの競合がある {0} 個のファイルをステージしてもよろしいですか?", "confirm stage file with merge conflicts": "マージの競合がある {0} をステージしてもよろしいですか? ", diff --git a/i18n/jpn/extensions/git/out/repository.i18n.json b/i18n/jpn/extensions/git/out/repository.i18n.json index 553e8a8277f..11c4d9a6d7f 100644 --- a/i18n/jpn/extensions/git/out/repository.i18n.json +++ b/i18n/jpn/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "こちら側による削除", "both added": "双方とも追加", "both modified": "双方とも変更", + "untracked, short": "U", + "modified, short": "M", "commit": "コミット", "merge changes": "変更のマージ", "staged changes": "ステージング済みの変更", diff --git a/i18n/jpn/extensions/git/package.i18n.json b/i18n/jpn/extensions/git/package.i18n.json index ffdb7e9c5a1..e176e6c6ec0 100644 --- a/i18n/jpn/extensions/git/package.i18n.json +++ b/i18n/jpn/extensions/git/package.i18n.json @@ -12,12 +12,14 @@ "command.openFile": "ファイルを開く", "command.openHEADFile": "HEAD のファイルを開く", "command.stage": "変更のステージング", - "command.stageAll": "すべての変更のステージング", - "command.stageSelectedRanges": "選択した範囲をステージする", + "command.stageAll": "すべての変更をステージ", + "command.stageSelectedRanges": "選択した範囲をステージ", "command.revertSelectedRanges": "選択範囲を元に戻す", + "command.stageChange": "変更のステージング", + "command.revertChange": "変更を元に戻す", "command.unstage": "変更のステージング解除", "command.unstageAll": "すべての変更のステージング解除", - "command.unstageSelectedRanges": "選択した範囲をアンステージする", + "command.unstageSelectedRanges": "選択した範囲のステージを解除", "command.clean": "変更を破棄", "command.cleanAll": "すべての変更を破棄", "command.commit": "Commit", diff --git a/i18n/jpn/extensions/typescript/package.i18n.json b/i18n/jpn/extensions/typescript/package.i18n.json index 7d6417ebf7d..48300f99d35 100644 --- a/i18n/jpn/extensions/typescript/package.i18n.json +++ b/i18n/jpn/extensions/typescript/package.i18n.json @@ -44,7 +44,8 @@ "typescript.npm": "型定義の自動取得に使用される NPM 実行可能ファイルへのパスを指定します。TypeScript 2.3.4 以上が必要です。", "typescript.check.npmIsInstalled": "型定義の自動取得に NPM がインストールされているかどうかを確認します。", "javascript.nameSuggestions": "JavaScript の候補リスト内でファイルから一意の名前を含むかどうかを有効/無効にします。", - "typescript.tsc.autoDetect": "tsc タスクの自動検出をオンにするかオフにするかを制御します。", + "typescript.tsc.autoDetect": "tsc タスクの自動検出を制御します。'off' はこの機能を無効にします。'build' は 1 つのコンパイル実行タスクのみを表示します。'watch' はコンパイルとウォッチ タスクのみを表示します。'on' はビルド タスクとウォッチ タスクの両方を表示します。既定値は 'on' です。", "typescript.problemMatchers.tsc.label": "TypeScript の問題", - "typescript.problemMatchers.tscWatch.label": "TypeScript の問題 (ウォッチ モード)" + "typescript.problemMatchers.tscWatch.label": "TypeScript の問題 (ウォッチ モード)", + "typescript.quickSuggestionsForPaths": "Import パスを入力するときのクイック候補を有効/無効にします。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/jpn/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 17c146860ec..b91635cb4cd 100644 --- a/i18n/jpn/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "置換", "label.replaceAllButton": "すべて置換", "label.toggleReplaceButton": "置換モードの切り替え", - "title.matchesCountLimit": "最初の 999 の結果だけを強調表示しますが、テキスト全体を検索します。", - "label.matchesLocation": "{1} の {0}", + "label.matchesLocation": "{0} / {1} 件", "label.noResults": "結果なし" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/jpn/src/vs/editor/contrib/find/common/findController.i18n.json index c8149938eee..93947cdf9ce 100644 --- a/i18n/jpn/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "次の選択項目を検索", "previousSelectionMatchFindAction": "前の選択項目を検索", "startReplace": "置換", - "addSelectionToNextFindMatch": "選択した項目を次の一致項目に追加", - "addSelectionToPreviousFindMatch": "選んだ項目を前の一致項目に追加する", - "moveSelectionToNextFindMatch": "最後に選択した項目を次の一致項目に移動", - "moveSelectionToPreviousFindMatch": "最後に選んだ項目を前の一致項目に移動する", - "selectAllOccurrencesOfFindMatch": "一致するすべての出現箇所を選択します", - "changeAll.label": "すべての出現箇所を変更", "showNextFindTermAction": "次の検索語句を表示", "showPreviousFindTermAction": "前の検索語句を表示" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/jpn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 47f31c8a681..0df6dca88c6 100644 --- a/i18n/jpn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "カーソルを上に挿入", "mutlicursor.insertBelow": "カーソルを下に挿入", - "mutlicursor.insertAtEndOfEachLineSelected": "カーソルを行末に挿入" + "mutlicursor.insertAtEndOfEachLineSelected": "カーソルを行末に挿入", + "addSelectionToNextFindMatch": "選択した項目を次の一致項目に追加", + "addSelectionToPreviousFindMatch": "選んだ項目を前の一致項目に追加する", + "moveSelectionToNextFindMatch": "最後に選択した項目を次の一致項目に移動", + "moveSelectionToPreviousFindMatch": "最後に選んだ項目を前の一致項目に移動する", + "selectAllOccurrencesOfFindMatch": "一致するすべての出現箇所を選択します", + "changeAll.label": "すべての出現箇所を変更" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json index 69cc08c144e..55a15149aaf 100644 --- a/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "無効な色形式です。 #RGB、#RGBA、#RRGGBB、#RRGGBBAA のいずれかを使用してください", "schema.colors": "ワークベンチで使用する色。", "foreground": "全体の前景色。この色は、コンポーネントによってオーバーライドされていない場合にのみ使用されます。", "errorForeground": "エラー メッセージ全体の前景色。この色は、コンポーネントによって上書きされていない場合にのみ使用されます。", diff --git a/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json index a72aa05e5aa..cf2a58db97a 100644 --- a/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "ワークスペースにフォルダーを追加...", "add": "追加(&&A)", "addFolderToWorkspaceTitle": "ワークスペースにフォルダーを追加", + "globalRemoveFolderFromWorkspace": "ワークスペースからフォルダーを削除...", "newWorkspace": "新しいワークスペース...", "select": "選択(&&S)", "selectWorkspace": "ワークスペースのフォルダーを選択", "removeFolderFromWorkspace": "ワークスペースからフォルダーを削除", + "openFolderSettings": "フォルダーの設定を開く", "saveWorkspaceAsAction": "名前を付けてワークスペースを保存...", "save": "保存(&&S)", "saveWorkspace": "ワークスペースを保存", "openWorkspaceAction": "ワークスペースを開く...", "openWorkspaceConfigFile": "ワークスペースの構成ファイルを開く", + "openFolderAsWorkspaceInNewWindow": "新しいウィンドウでワークスペースとしてフォルダーを開く", "workspaceFolderPickerPlaceholder": "ワークスペース フォルダーを選択" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index b9c158c0786..85e7c1f4a9c 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "アクティビティ バーを非表示にする", - "activityBarAriaLabel": "アクティブなビュー スイッチャー", "globalActions": "グローバル操作" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..23e9cfae128 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "アクティブなビュー スイッチャー" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..9edd21a8c9a --- /dev/null +++ b/i18n/jpn/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "その他のビュー", + "numberBadge": "{0} ({1})", + "manageExtension": "拡張機能を管理", + "titleKeybinding": "{0} ({1})", + "toggle": "ビューのピン留めの切り替え" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 198f105b057..86cc5cdfa14 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "2 番目のグループでエディターを表示する", "groupThreePicker": "3 番目のグループのエディターを表示する", "allEditorsPicker": "開いているエディターをすべて表示する", - "view": "表示" + "view": "表示", + "file": "ファイル" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 8056b34fd1f..e750906b858 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "コマンド '{0}' は現在有効ではなく、実行できません。", "manageExtension": "拡張機能を管理" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json index 880049ace58..a4a1c53595c 100644 --- a/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,16 +10,13 @@ "workspaces": "ワークスペース", "developer": "開発者", "showEditorTabs": "開いているエディターをタブに表示するかどうかを制御します。", - "workbench.editor.labelFormat.default": "ファイルの名前を表示します。タブが有効かつ1 つのグループの2 つの同名ファイルに各ファイルのパスの区切り記号が追加されます。タブを無効にすると、エディターがアクティブな時にワークスペースのルートへの相対パスが表示されます。", "workbench.editor.labelFormat.short": "ディレクトリ名に続けてファイル名を表示します。", - "workbench.editor.labelFormat.medium": "ワークスペース ルートからの相対パスに続けてファイル名を表示します。", "workbench.editor.labelFormat.long": "絶対パスに続けてファイル名を表示します。", "tabDescription": "エディターのラベルの書式を制御します。例としてこの設定を変更することでファイルの場所を理解しやすくなります:\n- short: 'parent'\n- medium: 'workspace/src/parent'\n- long: '/home/user/workspace/src/parent'\n- default: '.../parent',  別タブで、同じタイトルを共有する場合や、相対的なワークスペース パス タブが無効になっている場合", "editorTabCloseButton": "エディター タブの閉じるボタンの位置を制御するか、[off] に設定した場合に無効にします。", "showIcons": "開いているエディターをアイコンで表示するかどうかを制御します。これには、アイコンのテーマを有効にする必要もあります。", "enablePreview": "開かれるエディターをプレビューとして表示するかどうかを制御します。プレビュー エディターは (例: ダブル クリックまたは編集などによって) 変更される時まで再利用し、斜体で表示します。", "enablePreviewFromQuickOpen": "Quick Open で開いたエディターをプレビューとして表示するかどうかを制御します。プレビュー エディターは、保持されている間、再利用されます (ダブルクリックまたは編集などによって)。", - "editorOpenPositioning": "エディターを開く場所を制御します。[左] または [右] を選択して、現在アクティブになっているエディターの左または右にエディターを開きます。[最初] または [最後] を選択して、現在アクティブになっているエディターとは別個にエディターを開きます。", "revealIfOpen": "任意の表示グループが開かれた場合に、そこにエディターを表示するかどうかを制御します。無効にした場合、エディターは現在のアクティブなエディター グループに優先して開かれます。有効にした場合は、現在のアクティブなエディター グループにもう一度開くのではなく、既に開いているエディターが表示されます。特定のグループ内や現在アクティブなグループの横に強制的にエディターを開いた場合などに、この設定が無視される場合もあることにご注意ください。", "commandHistory": "コマンド パレットで最近使用したコマンド履歴を保持する数を制御します。0 に設定するとコマンド履歴を無効にします。", "preserveInput": "次回開いたとき、コマンド パレットの最後の入力を復元するかどうかを制御します。", @@ -50,7 +47,7 @@ "restoreWindows": "再起動後にワークスペースを再度開く方法を制御します。'none' を選択すると常に空のワークスペースで開始します。'one' を選択すると最後に使用したウィンドウを再度開きます。'folders' を選択すると開かれていたフォルダーとすべてのウィンドウを再度開きます。'all' を選択すると前回のセッションのすべてのウィンドウを再度開きます。", "restoreFullscreen": "全画面表示モードで終了した場合に、ウィンドウを全画面表示モードに復元するかどうかを制御します。", "zoomLevel": "ウィンドウのズーム レベルを調整します。元のサイズは 0 で、1 つ上げるごとに (1 など) 20% ずつ拡大することを表し、1 つ下げるごとに (-1 など) 20% ずつ縮小することを表します。小数点以下の桁数を入力して、さらに細かくズーム レベルを調整することもできます。", - "title": "アクティブなエディターに基づいてウィンドウのタイトルを制御します。変数は、コンテキストに基づいて置換されます:\n${activeEditorShort}: 例: myFile.txt\n${activeEditorMedium}: 例: myFolder/myFile.txt\n${activeEditorLong}: 例: /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: 例: myFolder\n${folderPath}: 例: /Users/Development/myFolder\n${rootName}: 例: myFolder1, myFolder2, myFolder3\n${rootPath}: 例: /Users/Development/myWorkspace\n${appName}: 例: VS Code\n${dirty}: アクティブなエディターがダーティである場合のダーティ インジゲーター\n${separator}: 値のある変数で囲まれた場合にのみ表示される条件付き区切り記号 (\" - \")", + "title": "アクティブなエディターに基づいてウィンドウのタイトルを制御します。変数は、コンテキストに基づいて置換されます:\n${activeEditorShort}: ファイル名 (例: myFile.txt)\n${activeEditorMedium}: ワークスペース フォルダーへの相対パス (例: myFolder/myFile.txt)\n${activeEditorLong}: ファイルの完全なパス (例: /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: ファイルが含まれているワークスペース フォルダー名 (例: myFolder)\n${folderPath}: ァイルが含まれているワークスペース フォルダーのファイルパス (例: /Users/Development/myFolder)\n${rootName}: ワークスペースの名前 (例: myFolder や myWorkspace)\n${rootPath}: ワークスペースのファイル パス (例: /Users/Development/myWorkspace)\n${appName}: 例: VS Code\n${dirty}: アクティブなエディターがダーティである場合のダーティ インジゲーター\n${separator}: 値のある変数で囲まれた場合にのみ表示される条件付き区切り記号 (\" - \")", "window.newWindowDimensions.default": "新しいウィンドウを画面の中央に開きます。", "window.newWindowDimensions.inherit": "新しいウィンドウを、最後にアクティブだったウィンドウと同じサイズで開きます。", "window.newWindowDimensions.maximized": "新しいウィンドウを最大化した状態で開きます。", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 24b30de36ed..f9530ecfb90 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}、デバッグ", "debugAriaLabel": "実行する起動構成の名前を入力してください。", + "addConfigTo": "設定 ({0}) の追加 ...", + "addConfiguration": "構成の追加...", "noConfigurationsMatching": "一致するデバッグ構成はありません", "noConfigurationsFound": "デバッグ構成が見つかりません。'launch.json' ファイルを作成してください。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..9465d938566 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "デバッグ" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..b317922a971 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debugFocusVariablesView": "変数にフォーカス", + "debugFocusWatchView": "ウォッチにフォーカス", + "debugFocusCallStackView": "コールスタックにフォーカス", + "debugFocusBreakpointsView": "ブレークポイントにフォーカス" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 03f52be8c47..84777c482b2 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "初期 'launch.json' を生成するための構成。", "vscode.extension.contributes.debuggers.languages": "デバッグ拡張機能が \"既定のデバッガー\" とされる言語の一覧。", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "指定されている場合、VS Code はこのコマンドを呼び出し、デバッグ アダプターの実行可能パスと、渡す引数を決定します。", - "vscode.extension.contributes.debuggers.startSessionCommand": "VS Code が指定されている場合、この拡張機能を対象とする \"デバッグ\" または \"実行\" アクションにこのコマンドが呼び出されます。", "vscode.extension.contributes.debuggers.configurationSnippets": "'launch.json' に新しい構成を追加するためのスニペット。", "vscode.extension.contributes.debuggers.configurationAttributes": "'launch.json' を検証するための JSON スキーマ構成。", "vscode.extension.contributes.debuggers.windows": "Windows 固有の設定。", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 86136d977a5..37262b21f31 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,10 @@ "breakpointRemoved": "ブレークポイントを削除しました。行 {0}、ファイル {1}", "compoundMustHaveConfigurations": "複合構成を開始するには、複合に \"configurations\" 属性が設定されている必要があります。", "configMissing": "構成 '{0}' が 'launch.json' 内にありません。", - "debugRequestNotSupported": "選択したデバッグ構成ではサポートされていない属性値 `{0}` : '{1}'。", - "debugRequesMissing": "選択しているデバッグ構成に '{0}' 属性が含まれていません ", + "debugRequestNotSupported": "選択しているデバッグ構成で `{0}` 属性はサポートされない値 '{1}' を指定しています。", + "debugRequesMissing": "選択しているデバッグ構成に `{0}` 属性が含まれていません。", "debugTypeNotSupported": "構成されているデバッグの種類 '{0}' はサポートされていません。", - "debugTypeMissing": "選択された起動構成のプロパティ 'type' がありません。", + "debugTypeMissing": "選択している起動構成の `type` プロパティがありません。", "preLaunchTaskErrors": "preLaunchTask '{0}' の実行中にビルド エラーが検出されました。", "preLaunchTaskError": "preLaunchTask '{0}' の実行中にビルド エラーが検出されました。", "preLaunchTaskExitCode": "preLaunchTask '{0}' が終了コード {1} で終了しました。", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 38c84790727..57032e9d668 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -8,5 +8,5 @@ "replVariableAriaLabel": "変数 {0} に値 {1} があります、Read Eval Print Loop、デバッグ", "replExpressionAriaLabel": "式 {0} に値 {1} があります、Read Eval Print Loop、デバッグ", "replValueOutputAriaLabel": "{0}、Read Eval Print Loop、デバッグ", - "replKeyValueOutputAriaLabel": "出力変数 {0} に値 {1} があります、Read Eval Print Loop、デバッグ" + "replRawObjectAriaLabel": "Repl 変数 {0} に値 {1} があります、Read Eval Print Loop、デバッグ" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/browser/fileActions.i18n.json index b11053bec02..c73b9e75a7e 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "'{0}' を削除しますか?", "undoBin": "ごみ箱から復元できます。", "undoTrash": "ゴミ箱から復元できます。", + "doNotAskAgain": "再度表示しない", "confirmDeleteMessageFolder": "'{0}' とその内容を完全に削除してもよろしいですか?", "confirmDeleteMessageFile": "'{0}' を完全に削除してもよろしいですか?", "irreversible": "このアクションは元に戻すことができません。", @@ -37,8 +38,6 @@ "openToSide": "横に並べて開く", "compareSource": "比較対象の選択", "globalCompareFile": "アクティブ ファイルを比較しています...", - "pickHistory": "比較対象として、以前に開いたファイルを選択する", - "unableToFileToCompare": "選択されたファイルを '{0}' と比較できません。", "openFileToCompare": "まずファイルを開いてから別のファイルと比較してください", "compareWith": "'{0}' と '{1}' を比較", "compareFiles": "ファイルの比較", @@ -47,7 +46,7 @@ "saveAs": "名前を付けて保存...", "saveAll": "すべて保存", "saveAllInGroup": "グループ内のすべてを保存する", - "saveFiles": "ダーティ ファイルを保存", + "saveFiles": "すべてのファイルを保存", "revert": "ファイルを元に戻す", "focusOpenEditors": "開いているエディターのビューにフォーカスする", "focusFilesExplorer": "ファイル エクスプローラーにフォーカスを置く", @@ -58,7 +57,7 @@ "openFile": "ファイルを開く...", "openFileInNewWindow": "新しいウィンドウでアクティブ ファイルを開く", "openFileToShowInNewWindow": "まずファイルを開いてから新しいウィンドウで開きます", - "revealInWindows": "エクスプローラーで表示します", + "revealInWindows": "エクスプローラーで表示", "revealInMac": "Finder で表示します", "openContainer": "このアイテムのフォルダーを開く", "revealActiveFileInWindows": "Windows エクスプローラーでアクティブ ファイルを表示する", diff --git a/i18n/jpn/src/vs/workbench/parts/files/browser/files.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/browser/files.contribution.i18n.json index c1dd7969f73..a34064cb71f 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/browser/files.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/browser/files.contribution.i18n.json @@ -40,10 +40,14 @@ "dynamicHeight": "開いているエディターのセクションの高さを要素の数に合わせて動的に調整するかどうかを制御します。", "autoReveal": "エクスプローラーでファイルを開くとき、自動的にファイルの内容を表示して選択するかどうかを制御します。", "enableDragAndDrop": "ドラッグ アンド ドロップを使用したファイルとフォルダーの移動をエクスプローラーが許可するかどうかを制御します。", + "confirmDragAndDrop": "ドラッグ アンド ドロップによるファイルやフォルダーの移動時にエクスプローラーが確認を求めるかどうかを制御します。", + "confirmDelete": "ごみ箱を経由したファイル削除時にエクスプローラーが確認を求めるかどうかを制御します。", "sortOrder.default": "ファイルとフォルダーをアルファベット順に名前で並び替えます。フォルダーはファイルの前に表示されます。", "sortOrder.mixed": "ファイルとフォルダーをアルファベット順に名前で並び替えます。ファイルはフォルダーと混交して表示されます。", "sortOrder.filesFirst": "ファイルとフォルダーをアルファベット順に名前で並び替えます。ファイルはフォルダーの前に表示されます。", "sortOrder.type": "ファイルとフォルダーをアルファベット順に拡張子で並び替えます。フォルダーはファイルの前に表示されます。", "sortOrder.modified": "ファイルとフォルダーを降順に最終更新日で並び替えます。フォルダーはファイルの前に表示されます。", - "sortOrder": "エクスプローラー内のファイルとフォルダーの並び順を制御します。既定の並び順に加えて、'mixed' (ファイルとフォルダーを混交した並び順)、' type' (ファイルの種類順)、' modified' (最終更新日時順)、または 'filesFirst' (フォルダーの前にファイルを並べる) のいずれかの並び順に設定できます。 " + "sortOrder": "エクスプローラー内のファイルとフォルダーの並び順を制御します。既定の並び順に加えて、'mixed' (ファイルとフォルダーを混交した並び順)、' type' (ファイルの種類順)、' modified' (最終更新日時順)、または 'filesFirst' (フォルダーの前にファイルを並べる) のいずれかの並び順に設定できます。 ", + "explorer.decorations.colors": "ファイルの装飾に配色を使用するかどうかを制御します。", + "explorer.decorations.badges": "ファイルの装飾にバッジを使用するかどうかを制御します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 93f172ab424..ac152686d08 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,8 @@ { "noWorkspace": "開いているフォルダーがありません", "explorerSection": "ファイル エクスプローラー セクション", - "noWorkspaceHelp": "まだフォルダーを開いていません。", + "noWorkspaceHelp": "まだフォルダーをワークスペースに追加していません。", + "addFolder": "フォルダーの追加", + "noFolderHelp": "まだフォルダーを開いていません。", "openFolder": "フォルダーを開く" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index 2199fe2e71e..2a38faa864f 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "{0} フォルダーを解決できません", "fileInputAriaLabel": "ファイル名を入力します。Enter キーを押して確認するか、Esc キーを押して取り消します。", "filesExplorerViewerAriaLabel": "{0}、ファイル エクスプローラー", "dropFolders": "ワークスペースにフォルダーを追加しますか?", "dropFolder": "ワークスペースにフォルダーを追加しますか?", "addFolders": "フォルダーの追加(&&A)", "addFolder": "フォルダーの追加(&&A)", + "confirmMove": "'{0}' を移動しますか?", + "doNotAskAgain": "再度表示しない", "confirmOverwriteMessage": "'{0}' は保存先フォルダーに既に存在します。置き換えてもよろしいですか。", "irreversible": "このアクションは元に戻すことができません。", "replaceButtonLabel": "置換(&&R)" diff --git a/i18n/jpn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..1f12247ced5 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "問題", + "tooltip.1": "このファイルに 1 つの問題", + "tooltip.N": "このファイルに {0} 個の問題", + "markers.showOnFile": "ファイルとフォルダーにエラーと警告を表示します。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 72cb0a9b0ae..c087aadd823 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "既定の設定を上書きするには、このファイル内に設定を挿入します。", - "errorInvalidConfiguration": "設定を書き込めません。ファイル内のエラー/警告を修正してからもう一度お試しください。", "emptyWorkspaceSettingsHeader": "ユーザー設定を上書きするには、このファイル内に設定を挿入します。", "emptyFolderSettingsHeader": "ワークスペースの設定を上書きするには、このファイル内にフォルダーの設定を挿入します。", "defaultFolderSettingsTitle": "既定のフォルダー設定", diff --git a/i18n/jpn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/jpn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index b0aca24403e..306d7198a6b 100644 --- a/i18n/jpn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "コマンド '{0}' は現在のコンテキストでは無効です。", "recentlyUsed": "最近使用したもの", "morecCommands": "その他のコマンド", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "一致するコマンドはありません" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index 3eaaf1477f2..043a0f4014f 100644 --- a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "changes": "{1} 個のうち {0} 個の変更", + "change": "{1} 個のうち {0} 個の変更 ", + "show previous change": "前の変更箇所を表示", + "show next change": "次の変更箇所を表示", "editorGutterModifiedBackground": "編集された行を示すエディター余白の背景色。", "editorGutterAddedBackground": "追加された行を示すエディター余白の背景色。", "editorGutterDeletedBackground": "削除された行を示すエディター余白の背景色。", diff --git a/i18n/jpn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index d39ad81f948..68c9699706e 100644 --- a/i18n/jpn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,7 @@ "exclude": "検索でファイルとフォルダーを除外するために glob パターンを構成します。files.exclude 設定からすべての glob パターンを継承します。", "exclude.boolean": "ファイル パスの照合基準となる glob パターン。これを true または false に設定すると、パターンがそれぞれ有効/無効になります。", "exclude.when": "一致するファイルの兄弟をさらにチェックします。一致するファイル名の変数として $(basename) を使用します。", - "useRipgrep": "テキスト検索で ripgrep を使用するかどうかを制御します", + "useRipgrep": "テキストとファイル検索で ripgrep を使用するかどうかを制御します", "useIgnoreFilesByDefault": "新しいワークスペースで検索するときに、既定で .gitignore ファイルを使用するか .ignore ファイルを使用するかを制御します。", "search.quickOpen.includeSymbols": "グローバル シンボル検索の結果を、Quick Open の結果ファイルに含めるように構成します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json index ab57a31ce38..1aa0dfacb0e 100644 --- a/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "検索結果のクリア", "FocusNextSearchResult.label": "次の検索結果にフォーカス", "FocusPreviousSearchResult.label": "前の検索結果にフォーカス", - "RemoveAction.label": "削除", "file.replaceAll.label": "すべて置換", "match.replace.label": "置換" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index adb4b5b9a1d..057c918a74d 100644 --- a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "スニペットを提供します。", "vscode.extension.contributes.snippets-language": "このスニペットの提供先の言語識別子です。", "vscode.extension.contributes.snippets-path": "スニペット ファイルのパス。拡張機能フォルダーの相対パスであり、通常 './snippets/' で始まります。", - "badFile": "スニペット ファイル \"{0}\" を読み込むことができませんでした。", "badVariableUse": "スニペット \"{0}\" は、スニペット変数とスニペット プレースホルダーを混乱させる可能性が非常にあります。詳細については https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax をご覧ください。", + "badFile": "スニペット ファイル \"{0}\" を読み込むことができませんでした。", "source.snippet": "ユーザー スニペット", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index b93c884904a..ec353f855bf 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -14,6 +14,7 @@ "runningTasks": "実行中のタスクを表示", "tasks": "タスク", "TaskSystem.noHotSwap": "アクティブなタスクを実行しているタスク実行エンジンを変更するには、ウィンドウの再読み込みが必要です", + "TaskServer.folderIgnored": "{0} フォルダーはタスク バージョン 0.1.0 を使用しているために無視されます", "TaskService.noBuildTask1": "ビルド タスクが定義されていません。tasks.json ファイルでタスクに 'isBuildCommand' というマークを付けてください。", "TaskService.noBuildTask2": "ビルド タスクが定義されていません。tasks.json ファイルでタスクに 'build' グループとしてマークを付けてください。", "TaskService.noTestTask1": "テスト タスクが定義されていません。tasks.json ファイルでタスクに 'isTestCommand' というマークを付けてください。", @@ -30,6 +31,7 @@ "TaskSystem.activeSame.noBackground": "'{0}' タスクは既にアクティブです。タスクを終了するにはタスク メニューから`タスクの終了...` を使用してください。 ", "TaskSystem.active": "既に実行中のタスクがあります。まずこのタスクを終了してから、別のタスクを実行してください。", "TaskSystem.restartFailed": "タスク {0} を終了して再開できませんでした", + "TaskService.noConfiguration": "エラー: {0} タスク検出は次の構成に対してタスクを提供していません:\n{1}\nこのタスクは無視されます。\n", "TaskSystem.configurationErrors": "エラー: 指定したタスク構成に検証エラーがあり、使用できません。最初にエラーを修正してください。", "taskService.ignoreingFolder": "ワークスペース フォルダー {0} のタスク構成を無視します。マルチ フォルダー ワークスペース タスクのサポートには、すべてのフォルダーがタスク バージョン 2.0.0 を使用する必要があります。\n", "TaskSystem.invalidTaskJson": "エラー: tasks.json ファイルの内容に構文エラーがあります。訂正してからタスクを実行してください。\n", diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 4d0ecdd18b0..76dbf9d84f0 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -17,6 +17,7 @@ "terminal.integrated.fontFamily": "端末のフォント ファミリを制御します。既定値は editor.fontFamily になります。", "terminal.integrated.fontSize": "ターミナルのフォント サイズをピクセル単位で制御します。", "terminal.integrated.lineHeight": "ターミナルの行の高さを制御します。この数値にターミナルのフォント サイズを乗算すると、実際の行の高さ (ピクセル単位) になります。", + "terminal.integrated.enableBold": "ターミナル内でテキストを太字にするかどうか。ターミナル シェルのサポートが必要なことに注意してください。", "terminal.integrated.cursorBlinking": "ターミナルのカーソルを点滅させるかどうかを制御します。", "terminal.integrated.cursorStyle": "端末のカーソルのスタイルを制御します。", "terminal.integrated.scrollback": "端末がそのバッファーに保持できる最大行数を制御します。", diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 3c51dcd1d5d..6015fb400ae 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "新しいターミナル", "workbench.action.terminal.focus": "端末にフォーカス", "workbench.action.terminal.focusNext": "次の端末にフォーカス", - "workbench.action.terminal.focusAtIndex": "ターミナル {0} にフォーカス", "workbench.action.terminal.focusPrevious": "前のターミナルにフォーカス", "workbench.action.terminal.paste": "アクティブなターミナルに貼り付け", "workbench.action.terminal.DefaultShell": "既定のシェルの選択", diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 0c5802f9502..acbc00bf882 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "コピー", - "createNewTerminal": "新しいターミナル", "paste": "貼り付け", "selectAll": "すべて選択", "clear": "クリア" diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 0303f610bb0..42ec3aff619 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "OK、今後は表示しない", "terminal.integrated.chooseWindowsShell": "優先するターミナル シェルを選択します。これは後で設定から変更できます", "terminalService.terminalCloseConfirmationSingular": "アクティブなターミナル セッションが 1 つあります。中止しますか?", - "terminalService.terminalCloseConfirmationPlural": "アクティブなターミナル セッションが {0} 個あります。中止しますか?", - "yes": "はい" + "terminalService.terminalCloseConfirmationPlural": "アクティブなターミナル セッションが {0} 個あります。中止しますか?" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..d93af154acf --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -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. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "設定の概要です。このラベルは、設定ファイルでコメントの区切り文字として使用します。", + "vscode.extension.contributes.configuration.properties": "構成のプロパティの説明です。", + "scope.window.description": "ウィンドウ固有の構成。ユーザーまたはワークスペースの設定で構成できます。", + "scope.resource.description": "リソース固有の構成。ユーザー、ワークスペース、またはフォルダーの設定で構成できます。", + "scope.description": "構成が適用される範囲。 使用可能なスコープは `window` と ` resource` です。", + "vscode.extension.contributes.configuration": "構成の設定を提供します。", + "invalid.title": "'configuration.title' は、文字列である必要があります", + "vscode.extension.contributes.defaultConfiguration": "言語ごとに既定のエディター構成の設定を提供します。", + "invalid.properties": "'configuration.properties' は、オブジェクトである必要があります", + "invalid.allOf": "'configuration.allOf' は非推奨で使用できなくなります。代わりに 'configuration' コントリビューション ポイントに複数の構成セクションを配列として渡します。", + "workspaceConfig.folders.description": "ワークスペースで読み込まれるフォルダーのリスト。", + "workspaceConfig.path.description": "ファイルパス。例: `/root/folderA` または `./folderA` のようなワークスペース ファイルの場所に対して解決される相対パス。", + "workspaceConfig.name.description": "フォルダーにつけるオプションの名前。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/jpn/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index 2773e1cc1be..31dd84eaa5c 100644 --- a/i18n/jpn/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -6,6 +6,7 @@ { "schema.token.settings": "トークンの色とスタイル。", "schema.token.foreground": "トークンの前景色。", + "schema.token.background.warning": "トークンの背景色は、現在サポートされていません。", "schema.token.fontStyle": "ルールのフォント スタイル: '斜体'、'太字'、'下線' のいずれかまたはこれらの組み合わせ", "schema.fontStyle.error": "フォント スタイルは '斜体'、'太字'、'下線'を組み合わせる必要があります。", "schema.properties.name": "ルールの説明。", diff --git a/i18n/jpn/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index a38d55a5642..335b53c2495 100644 --- a/i18n/jpn/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -33,5 +33,6 @@ "schema.fontSize": "フォントを使用する場合: テキスト フォントに対するフォントサイズの割合。設定されていない場合、既定値はフォント定義のサイズになります。", "schema.fontId": "フォントを使用する場合: フォントの ID。設定されていない場合、既定値は最初のフォント定義になります。", "schema.light": "明るい配色テーマでのファイル アイコンの任意の関連付け。", - "schema.highContrast": "ハイ コントラスト配色テーマでのファイル アイコンの任意の関連付け。" + "schema.highContrast": "ハイ コントラスト配色テーマでのファイル アイコンの任意の関連付け。", + "schema.hidesExplorerArrows": "このテーマがアクティブな時に、エクスプローラーの矢印を非表示にするかどうかを構成します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..c985a8de47f --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "TextMate の配色テーマを提供します。", + "vscode.extension.contributes.themes.id": "ユーザー設定で使用されるアイコン テーマの ID。", + "vscode.extension.contributes.themes.label": "UI で表示される配色テーマのラベル。", + "vscode.extension.contributes.themes.uiTheme": "エディターの周囲の色を定義する基本テーマ: 'vs' は明るい色のテーマで、'vs-dark' は濃い色のテーマです。'hc-black' は濃い色のハイ コントラストのテーマです。", + "vscode.extension.contributes.themes.path": "tmTheme ファイルのパス。拡張機能フォルダーに対する相対パスで、通常 './themes/themeFile.tmTheme' です。", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "`contributes.{0}.path` に文字列が必要です。提供された値: {1}", + "invalid.path.1": "拡張機能のフォルダー ({2}) の中に `contributes.{0}.path` ({1}) が含まれている必要があります。これにより拡張を移植できなくなる可能性があります。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..26366aa3de6 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "アイコン ファイルの解析中に問題が発生しました: {0}" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..b9a14b3199a --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "ユーザー設定で使用されるアイコン テーマの ID。", + "vscode.extension.contributes.iconThemes.label": "UI に表示されるアイコン テーマのラベル。", + "vscode.extension.contributes.iconThemes.path": "アイコン テーマの定義ファイルのパス。このパスは拡張フォルダーの相対パスであり、通常は './icons/awesome-icon-theme.json' です。", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "`contributes.{0}.path` に文字列が必要です。提供された値: {1}", + "reqid": "`contributes.{0}.id` に文字列が必要です。提供された値: {1}", + "invalid.path.1": "拡張機能のフォルダー ({2}) の中に `contributes.{0}.path` ({1}) が含まれている必要があります。これにより拡張を移植できなくなる可能性があります。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 18938fb3a92..db40a8ef3c1 100644 --- a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "TextMate の配色テーマを提供します。", - "vscode.extension.contributes.themes.id": "ユーザー設定で使用されるアイコン テーマの ID。", - "vscode.extension.contributes.themes.label": "UI で表示される配色テーマのラベル。", - "vscode.extension.contributes.themes.uiTheme": "エディターの周囲の色を定義する基本テーマ: 'vs' は明るい色のテーマで、'vs-dark' は濃い色のテーマです。'hc-black' は濃い色のハイ コントラストのテーマです。", - "vscode.extension.contributes.themes.path": "tmTheme ファイルのパス。拡張機能フォルダーに対する相対パスで、通常 './themes/themeFile.tmTheme' です。", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "ユーザー設定で使用されるアイコン テーマの ID。", - "vscode.extension.contributes.iconThemes.label": "UI に表示されるアイコン テーマのラベル。", - "vscode.extension.contributes.iconThemes.path": "アイコン テーマの定義ファイルのパス。このパスは拡張フォルダーの相対パスであり、通常は './icons/awesome-icon-theme.json' です。", "migration.completed": "ユーザー設定に新しいテーマの設定が追加されました。{0} に利用可能なバックアップがあります。", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "`contributes.{0}.path` に文字列が必要です。提供された値: {1}", - "invalid.path.1": "拡張機能のフォルダー ({2}) の中に `contributes.{0}.path` ({1}) が含まれている必要があります。これにより拡張を移植できなくなる可能性があります。", - "reqid": "`contributes.{0}.id` に文字列が必要です。提供された値: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "アイコン ファイルの解析中に問題が発生しました: {0}", "colorTheme": "ワークベンチで使用する配色テーマを指定します。", "colorThemeError": "テーマが不明、またはインストールされていません。", "iconTheme": "ワークベンチで使用するアイコンのテーマを指定します。'null' を指定するとファイル アイコンが表示されなくなります。", "noIconThemeDesc": "ファイル アイコンがありません", "iconThemeError": "ファイル アイコンのテーマが不明、またはインストールされていません。", "workbenchColors": "現在選択している配色テーマで配色を上書きします。", - "workbenchColors.deprecated": "この設定はもう試験的なものではなく、名前が 'workbench.colorCustomizations' に変更されています", - "workbenchColors.deprecatedDescription": "代わりに 'workbench.colorCustomizations' を使用してください", "editorColors": "現在選択している配色テーマで配色とフォント スタイルを上書きします。", "editorColors.comments": "コメントの色とスタイルを設定します", "editorColors.strings": "文字列リテラルの色とスタイルを設定します。", diff --git a/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..963427aa46c --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "ワークスペースの構成ファイルを開く", + "close": "閉じる" +} \ No newline at end of file diff --git a/i18n/kor/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/kor/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index c2b4c21ed25..3fd8cdf57b3 100644 --- a/i18n/kor/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/kor/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "예: myFile.txt", - "activeEditorMedium": "예: myFolder/myFile.txt", - "activeEditorLong": "예: /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "예: myFolder1, myFolder2, myFolder3", - "rootPath": "예: /Users/Development/myProject", - "folderName": "예: myFolder", - "folderPath": "예: /Users/Development/myFolder", "appName": "예: VS Code", "dirty": "활성 편집기가 더티인 경우 더티 표시기", "separator": "값이 있는 변수로 둘러싸인 경우에만 표시되는 조건부 구분 기호 (' - ')", diff --git a/i18n/kor/extensions/emmet/package.i18n.json b/i18n/kor/extensions/emmet/package.i18n.json index 0576d669667..7b41ed8ca2a 100644 --- a/i18n/kor/extensions/emmet/package.i18n.json +++ b/i18n/kor/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "10씩 증가", "command.decrementNumberByTen": "10씩 감소", "emmetSyntaxProfiles": "지정된 구문에 대한 프로필을 정의하거나 특정 규칙이 포함된 고유한 프로필을 사용하세요.", - "emmetExclude": "Emmet 약어를 확장하면 안 되는 언어의 배열입니다.", - "emmetExtensionsPath": "Emmet 프로필 및 코드 조각이 포함된 폴더의 경로입니다.'", - "emmetShowExpandedAbbreviation": "확장된 emmet 약어를 제안으로 표시합니다.\n\"inMarkupAndStylesheetFilesOnly\" 옵션이 html, haml, jade, slim, xml, xsl, css, scss, sass, less 및 stylus에 적용됩니다.\n\"always\" 옵션이 마크업/css에 관계없이 파일의 모든 부분에 적용됩니다.", - "emmetShowAbbreviationSuggestions": "가능한 emmet 약어를 제안으로 표시합니다. 스타일시트에는 적용되지 않고 emmet.showExpandedAbbreviation이 \"never\"로 설정되어 있을 때도 적용되지 않습니다.", - "emmetIncludeLanguages": "기본 지원되지 않는 언어에서 emmet 약어를 사용합니다. 언어와 emmet 지원 언어 사이에 매핑을 추가합니다.\n예: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "emmet 조각에 사용되는 변수", - "emmetTriggerExpansionOnTab": "사용하도록 설정하면 emmet 약어는 키를 눌렀을 때 확장됩니다.", "emmetPreferences": "Emmet의 일부 작업 및 해결 프로그램의 동작을 수정하는 데 사용되는 기본 설정입니다.", "emmetPreferencesIntUnit": "정수 값의 기본 단위", "emmetPreferencesFloatUnit": "부동 소수점 값의 기본 단위", @@ -43,6 +36,5 @@ "emmetPreferencesStylusAfter": "Stylus 파일에서 CSS 약어를 확장할 때 CSS 속성의 끝에 배치할 기호", "emmetPreferencesCssBetween": "CSS 약어를 확장할 때 CSS 속성 및 값 사이에 배치할 기호", "emmetPreferencesSassBetween": "Sass 파일에서 CSS 약어를 확장할 때 CSS 속성 및 값 사이에 배치할 기호", - "emmetPreferencesStylusBetween": "Stylus 파일에서 CSS 약어를 확장할 때 CSS 속성 및 값 사이에 배치할 기호", - "emmetShowSuggestionsAsSnippets": "True이면 emmet 제안이 코드 조각으로 표시되며 editor.snippetSuggestions 설정에 따라 코드 조각을 정렬할 수 있습니다." + "emmetPreferencesStylusBetween": "Stylus 파일에서 CSS 약어를 확장할 때 CSS 속성 및 값 사이에 배치할 기호" } \ No newline at end of file diff --git a/i18n/kor/extensions/git/out/commands.i18n.json b/i18n/kor/extensions/git/out/commands.i18n.json index 74283128949..1e7920f8a21 100644 --- a/i18n/kor/extensions/git/out/commands.i18n.json +++ b/i18n/kor/extensions/git/out/commands.i18n.json @@ -12,8 +12,8 @@ "cloning": "Git 리포지토리를 복제하는 중...", "openrepo": "리포지토리 열기", "proposeopen": "복제된 리포지토리를 여시겠습니까?", - "path to init": "폴더 경로", - "provide path": "Git 리포지토리를 초기화할 폴더 경로를 입력하세요.", + "init repo": "리포지토리 초기화", + "create repo": "리포지토리 초기화", "HEAD not available": "'{0}'의 HEAD 버전이 없습니다.", "confirm stage files with merge conflicts": "병합 충돌이 있는 {0} 파일을 스테이징하시겠습니까?", "confirm stage file with merge conflicts": "병합 충돌이 있는 {0}을(를) 스테이징하시겠습니까?", diff --git a/i18n/kor/extensions/git/out/repository.i18n.json b/i18n/kor/extensions/git/out/repository.i18n.json index c5c45af0062..6334a9e47ef 100644 --- a/i18n/kor/extensions/git/out/repository.i18n.json +++ b/i18n/kor/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "본인이 삭제함", "both added": "둘 다 추가됨", "both modified": "둘 다 수정됨", + "untracked, short": "U", + "modified, short": "M", "commit": "커밋", "merge changes": "변경 내용 병합", "staged changes": "스테이징된 변경 내용", diff --git a/i18n/kor/extensions/typescript/package.i18n.json b/i18n/kor/extensions/typescript/package.i18n.json index 9024eb3187d..7077f24ff61 100644 --- a/i18n/kor/extensions/typescript/package.i18n.json +++ b/i18n/kor/extensions/typescript/package.i18n.json @@ -44,7 +44,6 @@ "typescript.npm": "자동 입력 인식에 사용된 NPM 실행 파일 경로를 지정합니다. TypeScript >= 2.3.4가 필요합니다.", "typescript.check.npmIsInstalled": "자동 입력 인식에 대해 NPM이 설치되어 있는지 확인합니다.", "javascript.nameSuggestions": "JavaScript 제안 목록의 파일에서 고유한 이름 포함을 사용/사용 안 함으로 설정합니다.", - "typescript.tsc.autoDetect": "tsc 작업의 자동 검색을 켜거나 끕니다.", "typescript.problemMatchers.tsc.label": "TypeScript 문제", "typescript.problemMatchers.tscWatch.label": "TypeScript 문제(감시 모드)" } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/kor/src/vs/editor/contrib/find/browser/findWidget.i18n.json index c60d6d54352..e90c793f848 100644 --- a/i18n/kor/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "바꾸기", "label.replaceAllButton": "모두 바꾸기", "label.toggleReplaceButton": "바꾸기 모드 설정/해제", - "title.matchesCountLimit": "처음 999개의 결과가 강조 표시되지만 모든 찾기 작업은 전체 텍스트에 대해 수행됩니다.", "label.matchesLocation": "{0}/{1}", "label.noResults": "결과 없음" } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/kor/src/vs/editor/contrib/find/common/findController.i18n.json index d0e58fa206e..7201d1ab08f 100644 --- a/i18n/kor/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "다음 선택 찾기", "previousSelectionMatchFindAction": "이전 선택 찾기", "startReplace": "바꾸기", - "addSelectionToNextFindMatch": "다음 일치 항목 찾기에 선택 항목 추가", - "addSelectionToPreviousFindMatch": "이전 일치 항목 찾기에 선택 항목 추가", - "moveSelectionToNextFindMatch": "다음 일치 항목 찾기로 마지막 선택 항목 이동", - "moveSelectionToPreviousFindMatch": "마지막 선택 항목을 이전 일치 항목 찾기로 이동", - "selectAllOccurrencesOfFindMatch": "일치 항목 찾기의 모든 항목 선택", - "changeAll.label": "모든 항목 변경", "showNextFindTermAction": "다음 검색어 표시", "showPreviousFindTermAction": "이전 검색어 표시" } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/kor/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 2cd42573465..af6f5d6235c 100644 --- a/i18n/kor/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "위에 커서 추가", "mutlicursor.insertBelow": "아래에 커서 추가", - "mutlicursor.insertAtEndOfEachLineSelected": "줄 끝에 커서 추가" + "mutlicursor.insertAtEndOfEachLineSelected": "줄 끝에 커서 추가", + "addSelectionToNextFindMatch": "다음 일치 항목 찾기에 선택 항목 추가", + "addSelectionToPreviousFindMatch": "이전 일치 항목 찾기에 선택 항목 추가", + "moveSelectionToNextFindMatch": "다음 일치 항목 찾기로 마지막 선택 항목 이동", + "moveSelectionToPreviousFindMatch": "마지막 선택 항목을 이전 일치 항목 찾기로 이동", + "selectAllOccurrencesOfFindMatch": "일치 항목 찾기의 모든 항목 선택", + "changeAll.label": "모든 항목 변경" } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json index 98c0d356e83..8e8997c7ddf 100644 --- a/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "잘못된 색 형식입니다. #RGB, #RGBA, #RRGGBB 또는 #RRGGBBAA를 사용하세요.", "schema.colors": "워크벤치에서 사용되는 색입니다.", "foreground": "전체 전경색입니다. 이 색은 구성 요소에서 재정의하지 않은 경우에만 사용됩니다.", "errorForeground": "오류 메시지에 대한 전체 전경색입니다. 이 색은 구성 요소에서 재정의하지 않은 경우에만 사용됩니다.", diff --git a/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json index b414854fcac..b3a4fc27abc 100644 --- a/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -13,6 +13,7 @@ "select": "선택(&&S)", "selectWorkspace": "작업 영역 폴더 선택", "removeFolderFromWorkspace": "작업 영역에서 폴더 삭제", + "openFolderSettings": "폴더 설정 열기", "saveWorkspaceAsAction": "작업 영역을 다른 이름으로 저장", "save": "저장(&&S)", "saveWorkspace": "작업 영역 저장", diff --git a/i18n/kor/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index 775ac027185..6ab66076b97 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "작업 막대 숨기기", - "activityBarAriaLabel": "활성 뷰 전환기", "globalActions": "전역 작업" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..f515e983418 --- /dev/null +++ b/i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "활성 뷰 전환기" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..882b528591a --- /dev/null +++ b/i18n/kor/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "추가 뷰", + "numberBadge": "{0}({1})", + "manageExtension": "확장 관리", + "titleKeybinding": "{0}({1})", + "toggle": "뷰 고정 전환" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 29467820136..32f439e8de1 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "두 번째 그룹에 편집기 표시", "groupThreePicker": "세 번째 그룹에 편집기 표시", "allEditorsPicker": "열려 있는 모든 편집기 표시", - "view": "보기" + "view": "보기", + "file": "파일" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 1b2e94b2c53..1a622afa7d4 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "'{0}' 명령은 현재 사용하도록 설정되지 않아 실행할 수 없습니다.", "manageExtension": "확장 관리" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json index 7c9f66647d9..22baa2ccddf 100644 --- a/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,14 @@ "workspaces": "작업 영역", "developer": "개발자", "showEditorTabs": "열려 있는 편집기를 탭에서 표시할지 여부를 제어합니다.", - "workbench.editor.labelFormat.default": "파일 이름을 표시합니다. 탭이 사용하도록 설정되어 있고 하나의 그룹에서 파일 2개의 이름이 동일하면, 각 파일 경로의 특정 섹션이 추가됩니다. 탭이 사용하도록 설정되어 있지 않으면, 작업 영역 루트에 대한 경로는 편집기가 활성 상태일 때 표시됩니다.", "workbench.editor.labelFormat.short": "디렉터리 이름 앞에 오는 파일의 이름을 표시합니다.", - "workbench.editor.labelFormat.medium": "작업 영역 루트를 기준으로 하는 상대 경로 앞에 오는 파일의 이름을 표시합니다.", "workbench.editor.labelFormat.long": "절대 경로 앞에 오는 파일의 이름을 표시합니다.", "tabDescription": "편집기의 레이블 형식을 제어합니다. 예를 들어 이 설정을 변경하면 파일의 위치를 더 쉽게 파악할 수 있습니다.:\n- 짧게: 'parent'\n- 중간: 'workspace/src/parent'\n- 길게: '/home/user/workspace/src/parent'\n- 기본값: '.../parent', 다른 탭이 동일한 제목을 공유하거나, 탭을 사용하지 않도록 설정한 경우 작업 영역 상대 경로", "editorTabCloseButton": "편집기의 탭 닫기 단추의 위치를 제어하거나 'off'로 설정된 경우 이 단추를 사용하지 않도록 설정합니다.", "showIcons": "열린 편집기를 아이콘과 함께 표시할지 여부를 제어합니다. 이를 위해서는 아이콘 테마도 사용하도록 설정해야 합니다.", "enablePreview": "열려 있는 편집기를 미리 보기로 표시할지 여부를 제어합니다. 미리 보기 편집기는 유지된 상태까지(예: 두 번 클릭 또는 편집을 통해) 다시 사용되며 기울임꼴 글꼴 스타일로 표시됩니다.", "enablePreviewFromQuickOpen": "Quick Open에서 연 편집기를 미리 보기로 표시할지 여부를 제어합니다. 미리 보기 편집기는 유지된 상태까지(예: 두 번 클릭 또는 편집을 통해) 다시 사용됩니다.", - "editorOpenPositioning": "편집기가 열리는 위치를 제어합니다. 현재 활성 편집기의 왼쪽 또는 오른쪽에서 편집기를 열려면 '왼쪽' 또는 '오른쪽'을 선택합니다. 현재 활성 편집기와 독립적으로 편집기를 열려면 '처음' 또는 '마지막'을 선택합니다.", "revealIfOpen": "편집기를 여는 경우 보이는 그룹 중 하나에 표시할지 여부를 제어합니다. 사용하지 않도록 설정할 경우 편집기가 기본적으로 현재 활성 편집기 그룹에 열립니다. 사용하도록 설정할 경우 현재 활성 편집기 그룹에서 편집기가 다시 열리지 않고 이미 열린 편집기가 표시됩니다. 강제로 편집기가 특정 그룹에서 열리거나 현재 활성 그룹 옆에 열리도록 하는 등의 일부 경우에는 이 설정이 무시됩니다.", - "commandHistory": "명령 팔레트 기록에 최근 사용 명령을 몇 개 유지할지 결정합니다. 0으로 설정하면 명령 기록을 사용하지 않습니다.", "preserveInput": "다음에 열 때 마지막으로 명령 팔레트에 입력한 내용을 복원할지 결정합니다.", "closeOnFocusLost": "Quick Open가 포커스를 잃으면 자동으로 닫을지 여부를 제어합니다.", "openDefaultSettings": "설정을 열면 모든 기본 설정을 표시하는 편집기도 열리는지 여부를 제어합니다.", @@ -50,7 +46,6 @@ "restoreWindows": "다시 시작한 이후에 창을 다시 여는 방법을 설정합니다. 'none'을 선택하면 항상 빈 작업 영역으로 시작하고 'one'을 선택하면 마지막으로 작업한 창이 다시 열리고 'folders'를 선택하면 열었던 폴더가 포함된 모든 창이 다시 열리며 'all'을 선택하면 지난 세션의 모든 창이 다시 열립니다.", "restoreFullscreen": "창이 전체 화면 모드에서 종료된 경우 창을 전체 화면 모드로 복원할지 여부를 제어합니다.", "zoomLevel": "창의 확대/축소 수준을 조정합니다. 원래 크기는 0이고 각 상한 증분(예: 1) 또는 하한 증분(예: -1)은 20% 더 크거나 더 작게 확대/축소하는 것을 나타냅니다. 10진수를 입력하여 확대/축소 수준을 세부적으로 조정할 수도 있습니다.", - "title": "활성 편집기를 기반으로 창 제목을 제어합니다. 변수는 컨텍스트를 기반으로 대체됩니다. \n${activeEditorShort}: 예: myFile.txt\n${activeEditorMedium}: 예: myFolder/myFile.txt\n${activeEditorLong}: 예: /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: 예: myFolder\n${folderPath}: 예: /Users/Development/myFolder\n${rootName}: 예: myFolder1, myFolder2, myFolder3\n${rootPath}: 예: /Users/Development/myWorkspace\n${appName}: 예: VS Code\n${dirty}: 활성 편집기가 더티인 경우 더티 표시기\n${separator}: 값이 있는 변수로 둘러싸인 경우에만 표시되는 조건부 구분 기호(\" - \")", "window.newWindowDimensions.default": "화면 가운데에서 새 창을 엽니다.", "window.newWindowDimensions.inherit": "마지막 활성 창과 동일한 크기로 새 창을 엽니다.", "window.newWindowDimensions.maximized": "최대화된 새 창을 엽니다.", diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 674839cc069..753a861d411 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, 디버그", "debugAriaLabel": "실행할 시작 구성의 이름을 입력하세요.", + "addConfigTo": "구성 추가 ({0})...", + "addConfiguration": "구성 추가...", "noConfigurationsMatching": "일치하는 디버그 구성 없음", "noConfigurationsFound": "디버그 구성을 찾을 수 없습니다. 'launch.json' 파일을 만드세요." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..416944e28fd --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "디버그" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 2b0632b1635..0db91f83b2f 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "초기 'launch.json'을 생성하기 위한 구성입니다.", "vscode.extension.contributes.debuggers.languages": "디버그 확장이 \"기본 디버거\"로 간주될 수 있는 언어 목록입니다.", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "지정하는 경우 VS Code에서 이 명령을 호출하여 디버그 어댑터의 실행 파일 경로 및 전달할 인수를 확인합니다.", - "vscode.extension.contributes.debuggers.startSessionCommand": "지정하는 경우 VS Code에서 이 확장을 대상으로 하는 \"디버그\" 또는 \"실행\" 작업에 대해 이 명령을 호출합니다.", "vscode.extension.contributes.debuggers.configurationSnippets": "'launch.json'에 새 구성을 추가하는 코드 조각입니다.", "vscode.extension.contributes.debuggers.configurationAttributes": "'launch.json'의 유효성 검사를 위한 JSON 스키마 구성입니다.", "vscode.extension.contributes.debuggers.windows": "Windows 특정 설정", diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 7b4fa4d91c9..13125eab426 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,7 @@ "breakpointRemoved": "파일 {1}, 줄 {0}에서 중단점이 제거되었습니다.", "compoundMustHaveConfigurations": "여러 구성을 시작하려면 복합에 \"configurations\" 특성 집합이 있어야 합니다.", "configMissing": "'{0}' 구성이 'launch.json'에 없습니다.", - "debugRequestNotSupported": "선택한 디버그 구성에 지원되지 않는 특성 값 `{0}`: '{1}'이(가) 있습니다.", - "debugRequesMissing": "선택한 디버그 구성에 특성 '{0}'이(가) 없습니다.", "debugTypeNotSupported": "구성된 디버그 형식 '{0}'은(는) 지원되지 않습니다.", - "debugTypeMissing": "선택한 시작 구성에 대한 'type' 속성이 없습니다.", "preLaunchTaskErrors": "preLaunchTask '{0}' 진행 중에 빌드 오류가 감지되었습니다.", "preLaunchTaskError": "preLaunchTask '{0}' 진행 중에 빌드 오류가 감지되었습니다.", "preLaunchTaskExitCode": "preLaunchTask '{0}'이(가) {1} 종료 코드와 함께 종료되었습니다.", diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 9c417b8c7dd..1da0363bd93 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "개체 상태는 첫 번재 평가에서 캡처됩니다.", "replVariableAriaLabel": "{0} 변수에 {1} 값이 있습니다. 읽기 평가 인쇄 루프, 디버그", "replExpressionAriaLabel": "{0} 식에 {1} 값이 있습니다. 읽기 평가 인쇄 루프, 디버그", - "replValueOutputAriaLabel": "{0}, 읽기 평가 인쇄 루프, 디버그", - "replKeyValueOutputAriaLabel": "출력 변수 {0}에 {1} 값이 있습니다. 읽기 평가 인쇄 루프, 디버그" + "replValueOutputAriaLabel": "{0}, 읽기 평가 인쇄 루프, 디버그" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/kor/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 8bcb4133777..1f93f5ae2c6 100644 --- a/i18n/kor/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -37,8 +37,6 @@ "openToSide": "측면에서 열기", "compareSource": "비교를 위해 선택", "globalCompareFile": "활성 파일을 다음과 비교...", - "pickHistory": "비교할 이전에 연 파일 선택", - "unableToFileToCompare": "선택한 파일을 '{0}'과(와) 비교할 수 없습니다.", "openFileToCompare": "첫 번째 파일을 열어서 다른 파일과 비교합니다.", "compareWith": "'{0}'과(와) '{1}' 비교", "compareFiles": "파일 비교", @@ -47,7 +45,6 @@ "saveAs": "다른 이름으로 저장...", "saveAll": "모두 저장", "saveAllInGroup": "그룹의 모든 항목 저장", - "saveFiles": "더티 파일 저장", "revert": "파일 되돌리기", "focusOpenEditors": "열려 있는 편집기 뷰에 포커스", "focusFilesExplorer": "파일 탐색기에 포커스", diff --git a/i18n/kor/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/kor/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 643334c6aba..42fb83a81b7 100644 --- a/i18n/kor/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,6 @@ { "noWorkspace": "열린 폴더 없음", "explorerSection": "파일 탐색기 섹션", - "noWorkspaceHelp": "아직 폴더를 열지 않았습니다.", + "noFolderHelp": "아직 폴더를 열지 않았습니다.", "openFolder": "폴더 열기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..9a5ca02f322 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "문제" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 393b61b671f..fa4d6d2e024 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "설정을 여기에 넣어서 기본 설정을 덮어씁니다.", - "errorInvalidConfiguration": "설정에 쓸 수 없습니다. 파일에서 오류/경고를 해결하고 다시 시도하세요.", "emptyWorkspaceSettingsHeader": "설정을 여기에 넣어서 사용자 설정을 덮어씁니다.", "emptyFolderSettingsHeader": "폴더 설정을 여기에 넣어서 작업 영역 설정을 덮어씁니다.", "defaultFolderSettingsTitle": "기본 폴더 설정", diff --git a/i18n/kor/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/kor/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 3643111bada..a8785cacb78 100644 --- a/i18n/kor/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "'{0}' 명령은 현재 컨텍스트에서 사용할 수 없습니다.", "recentlyUsed": "최근에 사용한 항목", "morecCommands": "기타 명령", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "일치하는 명령 없음" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index eda87691830..4b214694baf 100644 --- a/i18n/kor/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,6 @@ "exclude": "검색에서 파일 및 폴더를 제외하도록 GLOB 패턴을 구성합니다. files.exclude 설정에서 모든 GLOB 패턴을 상속합니다.", "exclude.boolean": "파일 경로를 일치시킬 GLOB 패턴입니다. 패턴을 사용하거나 사용하지 않도록 설정하려면 true 또는 false로 설정하세요.", "exclude.when": "일치하는 파일의 형제에 대한 추가 검사입니다. $(basename)을 일치하는 파일 이름에 대한 변수로 사용하세요.", - "useRipgrep": "텍스트 검색에서 ripgrep 사용 여부를 제어합니다.", "useIgnoreFilesByDefault": "새 작업 영역에서 검색할 때 기본적으로 .gitignore 파일 및 .ignore 파일을 사용할지 여부를 제어합니다.", "search.quickOpen.includeSymbols": "Quick Open에 대한 파일 결과에 전역 기호 검색 결과를 포함하도록 구성합니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json index d8c432f8bb0..ffeb7ea9a94 100644 --- a/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "검색 결과 지우기", "FocusNextSearchResult.label": "다음 검색 결과에 포커스", "FocusPreviousSearchResult.label": "이전 검색 결과에 포커스", - "RemoveAction.label": "제거", "file.replaceAll.label": "모두 바꾸기", "match.replace.label": "바꾸기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index b80c311ab32..0bac25f2467 100644 --- a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "코드 조각을 적용합니다.", "vscode.extension.contributes.snippets-language": "이 코드 조각이 적용되는 언어 식별자입니다.", "vscode.extension.contributes.snippets-path": "코드 조각 파일의 경로입니다. 이 경로는 확장 폴더의 상대 경로이며 일반적으로 './snippets/'로 시작합니다.", - "badFile": "코드 조각 파일 \"{0}\"을(를) 읽을 수 없습니다.", "badVariableUse": "\"{0}\"-snippet은 snippet-variables 및 snippet-placeholders와 혼동하기 쉽습니다. 자세한 내용은\n https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax를 참조하세요.", + "badFile": "코드 조각 파일 \"{0}\"을(를) 읽을 수 없습니다.", "source.snippet": "사용자 코드 조각", "detail.snippet": "{0}({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 110ad443882..9415bbb9140 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "새 터미널", "workbench.action.terminal.focus": "터미널에 포커스", "workbench.action.terminal.focusNext": "다음 터미널에 포커스", - "workbench.action.terminal.focusAtIndex": "{0} 터미널로 포커스 이동", "workbench.action.terminal.focusPrevious": "이전 터미널에 포커스", "workbench.action.terminal.paste": "활성 터미널에 붙여넣기", "workbench.action.terminal.DefaultShell": "기본 셸 선택", diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 9fe74c319a1..08eba97a0dc 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "복사", - "createNewTerminal": "새 터미널", "paste": "붙여넣기", "selectAll": "모두 선택", "clear": "지우기" diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 81c70b66b79..b21bf5b25fa 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "다시 표시 안 함", "terminal.integrated.chooseWindowsShell": "기본으로 설정할 터미널 셸을 선택하세요. 나중에 설정에서 이 셸을 변경할 수 있습니다.", "terminalService.terminalCloseConfirmationSingular": "활성 터미널 세션이 있습니다. 종료할까요?", - "terminalService.terminalCloseConfirmationPlural": "{0}개의 활성 터미널 세션이 있습니다. 종료할까요?", - "yes": "예" + "terminalService.terminalCloseConfirmationPlural": "{0}개의 활성 터미널 세션이 있습니다. 종료할까요?" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..4fdc20a33c2 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -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. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "설정을 요약합니다. 이 레이블은 설정 파일에서 구분 주석으로 사용됩니다.", + "vscode.extension.contributes.configuration.properties": "구성 속성에 대한 설명입니다.", + "scope.window.description": "[사용자] 설정 또는 [작업 영역] 설정에서 구성할 수 있는 창 특정 구성입니다.", + "scope.resource.description": "사용자, 작업 영역 또는 폴더 설정에서 구성할 수 있는 리소스 특정 구성", + "scope.description": "구성이 적용되는 범위입니다. 사용 가능 범위는 '창'과 '리소스'입니다.", + "vscode.extension.contributes.configuration": "구성 설정을 적용합니다.", + "invalid.title": "'configuration.title'은 문자열이어야 합니다.", + "vscode.extension.contributes.defaultConfiguration": "언어별로 기본 편집기 구성 설정을 적용합니다.", + "invalid.properties": "'configuration.properties'는 개체여야 합니다.", + "invalid.allOf": "'configuration.allOf'는 사용되지 않으며 더 이상 사용해서는 안됩니다. 대신 여러 구성 섹션을 배열로 'configuration' 기여 지점에 전달하세요.", + "workspaceConfig.folders.description": "작업 영역에 로드되는 폴더 목록입니다.", + "workspaceConfig.path.description": "파일 경로입니다. 예: `/root/folderA` 또는 `./folderA`(작업 영역 파일의 위치를 기준으로 확인할 상대 경로인 경우)", + "workspaceConfig.name.description": "폴더에 대한 선택적 이름입니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/kor/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/kor/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..4bcd1e891d3 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contributes textmate color themes.", + "vscode.extension.contributes.themes.id": "사용자 설정에 사용된 아이콘 테마의 ID입니다.", + "vscode.extension.contributes.themes.label": "UI에 표시되는 색 테마의 레이블입니다.", + "vscode.extension.contributes.themes.uiTheme": "편집기 주변의 색을 정의하는 기본 테마입니다. 'vs'는 밝은색 테마이고, 'vs-dark'는 어두운색 테마입니다. 'hc-black'은 어두운 고대비 테마입니다.", + "vscode.extension.contributes.themes.path": "tmTheme 파일의 경로입니다. 확장 폴더의 상대 경로이며 일반적으로 './themes/themeFile.tmTheme'입니다.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "`contributes.{0}.path`에 문자열이 필요합니다. 제공된 값: {1}", + "invalid.path.1": "확장 폴더({2})에 포함할 `contributes.{0}.path`({1})가 필요합니다. 확장이 이식 불가능해질 수 있습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..b0f9faf6b52 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problems parsing file icons file: {0}" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..10f74d38b89 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "사용자 설정에 사용된 아이콘 테마의 ID입니다.", + "vscode.extension.contributes.iconThemes.label": "UI에 표시된 아이콘 테마의 레이블입니다.", + "vscode.extension.contributes.iconThemes.path": "아이콘 테마 정의 파일의 경로입니다. 확장 폴더의 상대 경로이며 일반적으로 './icons/awesome-icon-theme.json'입니다.", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "`contributes.{0}.path`에 문자열이 필요합니다. 제공된 값: {1}", + "reqid": "`contributes.{0}.id`에 문자열이 필요합니다. 제공된 값: {1}", + "invalid.path.1": "확장 폴더({2})에 포함할 `contributes.{0}.path`({1})가 필요합니다. 확장이 이식 불가능해질 수 있습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 3f05d41e6bb..c7ed3a3fe46 100644 --- a/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "사용자 설정에 사용된 아이콘 테마의 ID입니다.", - "vscode.extension.contributes.themes.label": "UI에 표시되는 색 테마의 레이블입니다.", - "vscode.extension.contributes.themes.uiTheme": "편집기 주변의 색을 정의하는 기본 테마입니다. 'vs'는 밝은색 테마이고, 'vs-dark'는 어두운색 테마입니다. 'hc-black'은 어두운 고대비 테마입니다.", - "vscode.extension.contributes.themes.path": "tmTheme 파일의 경로입니다. 확장 폴더의 상대 경로이며 일반적으로 './themes/themeFile.tmTheme'입니다.", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "사용자 설정에 사용된 아이콘 테마의 ID입니다.", - "vscode.extension.contributes.iconThemes.label": "UI에 표시된 아이콘 테마의 레이블입니다.", - "vscode.extension.contributes.iconThemes.path": "아이콘 테마 정의 파일의 경로입니다. 확장 폴더의 상대 경로이며 일반적으로 './icons/awesome-icon-theme.json'입니다.", "migration.completed": "새 테마 설정이 사용자 설정에 추가되었습니다. {0}에서 백업을 사용할 수 있습니다.", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "`contributes.{0}.path`에 문자열이 필요합니다. 제공된 값: {1}", - "invalid.path.1": "확장 폴더({2})에 포함할 `contributes.{0}.path`({1})가 필요합니다. 확장이 이식 불가능해질 수 있습니다.", - "reqid": "`contributes.{0}.id`에 문자열이 필요합니다. 제공된 값: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "워크벤치에서 사용되는 아이콘 테마를 지정합니다. 'null'로 지정하면 파일 아이콘을 표시하지 않습니다.", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "현재 선택한 색 테마에서 색을 재정의합니다.", - "workbenchColors.deprecated": "이 설정은 더 이상 실험적 설정이 아니며 이름이\n 'workbench.colorCustomizations'로 변경되었습니다.", - "workbenchColors.deprecatedDescription": "대신 'workbench.colorCustomizations'를 사용합니다.", "editorColors": "현재 선택된 색 테마에서 편집기 색상과 글꼴 스타일을 재정의합니다.", "editorColors.comments": "주석의 색 및 스타일을 설정합니다.", "editorColors.strings": "문자열 리터럴의 색 및 스타일을 설정합니다.", diff --git a/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..32a5b42e309 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "작업 영역 구성 파일 열기", + "close": "닫기" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index ab0c10765f7..c86627bbf9c 100644 --- a/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "por exemplo meuArquivo.txt", - "activeEditorMedium": "e.g. minhaPasta/meuArquivo.txt", - "activeEditorLong": "por exemplo /Usuários/Desenvolvimento/meuProjeto/minhaPasta/meuArquivo/txt", - "rootName": "por exemplo: minhaPasta1, minhaPasta2, minhaPasta3", - "rootPath": "por exemplo /Usuários/desenvolvimento/meuProjeto", - "folderName": "por exemplo: minhaPasta", - "folderPath": "por exemplo, /Users/Development/myFolder", + "activeEditorShort": "o nome do arquivo (por exemplo, MyFile. txt)", + "activeEditorMedium": "o caminho do arquivo relativo à pasta de trabalho (por exemplo, myFolder/myFile.txt)", + "activeEditorLong": "o caminho completo do arquivo (por exemplo, /Users/Development/myProject/myFolder/myFile.txt)", + "rootName": "nome da área de trabalho (por exemplo, minhaPasta ou minhaAreadeTrabalho)", + "rootPath": "caminho do arquivo da área de trabalho (por exemplo, /Usuarios/Desenvolvimento/minhaAreadeTrabalho)", + "folderName": "nome do diretório da área de trabalho onde arquivo está localizado (por exemplo, myFolder)", + "folderPath": "caminho do arquivo no diretório da área de trabalho onde o arquivo está localizado (por exemplo, /Users/Development/myFolder)", "appName": "e.g. VS Code", "dirty": "Um indicador de alteração se o editor ativo foi alterado", "separator": "um separador condicional (' - ') que somente é mostrado quando envolvido por variáveis com valores", diff --git a/i18n/ptb/extensions/emmet/package.i18n.json b/i18n/ptb/extensions/emmet/package.i18n.json index 07589c8fc9d..582e68c8fa1 100644 --- a/i18n/ptb/extensions/emmet/package.i18n.json +++ b/i18n/ptb/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Incremento de 10", "command.decrementNumberByTen": "Decrementar por 10", "emmetSyntaxProfiles": "Definir o perfil para a sintaxe especificada ou usar seu próprio perfil com regras específicas.", - "emmetExclude": "Uma matriz de línguagens onde abreviaturas emmet não devem ser expandidas.", - "emmetExtensionsPath": "Caminho para uma pasta que contém os perfis de emmet e trechos de código.'", - "emmetShowExpandedAbbreviation": "Mostra abreviaturas emmet expandidas como sugestões.\nA opção \"inMarkupAndStylesheetFilesOnly\" aplica-se a html, haml, jade, slim, xml, xsl, css, scss, sass, less e stylus.\nA opção \"always\" se aplica a todas as partes do arquivo independentemente de marcação/css.", - "emmetShowAbbreviationSuggestions": "Mostra possíveis abreviaturas emmet como sugestões. Não aplicável em folhas de estilo ou quando emmet.showExpandedAbbreviation é definido como \"nunca\".", - "emmetIncludeLanguages": "Habilita as abreviaturas do emmet em idiomas que não são suportados por padrão. Adicione um mapeamento aqui entre a linguagem e a linguagem emmet suportada.\n Por exemplo: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Variáveis a serem usadas em trechos de código emmet", - "emmetTriggerExpansionOnTab": "Quando habilitado, abreviações emmet são expandidas ao pressionar TAB.", "emmetPreferences": "Preferências usadas para modificar o comportamento de algumas ações e resolvedores de Emmet.", "emmetPreferencesIntUnit": "Unidade padrão para valores inteiros", "emmetPreferencesFloatUnit": "Unidade padrão para valores float", @@ -44,5 +37,7 @@ "emmetPreferencesCssBetween": "Símbolo a ser colocado entre a propriedade CSS e o valor quando expandir abreviaturas CSS", "emmetPreferencesSassBetween": "Símbolo a ser colocado entre a propriedade CSS e o valor quando expandir abreviaturas CSS em arquivos Sass", "emmetPreferencesStylusBetween": "Símbolo a ser colocado entre a propriedade CSS e o valor quando expandir abreviaturas CSS em arquivos Stylus", - "emmetShowSuggestionsAsSnippets": "Se verdadeiro, então as sugestões emmet aparecerão como trechos, permitindo você requisitá-los conforme a configuração de editor.snippetSuggestions." + "emmetPreferencesFilterCommentBefore": "Uma definição de comentário que deve ser colocado antes de elemento correspondente quando um filtro de comentário é aplicado.", + "emmetPreferencesFilterCommentAfter": "Uma definição de comentário que deve ser colocado após o elemento correspondente quando um filtro de comentário é aplicado.", + "emmetPreferencesFilterCommentTrigger": "Uma lista separada por vírgulas de nomes de atributo que deve existir em abreviações para o filtro de comentário a ser aplicado" } \ No newline at end of file diff --git a/i18n/ptb/extensions/git/out/commands.i18n.json b/i18n/ptb/extensions/git/out/commands.i18n.json index 4c72afe876f..d3e314a0e15 100644 --- a/i18n/ptb/extensions/git/out/commands.i18n.json +++ b/i18n/ptb/extensions/git/out/commands.i18n.json @@ -12,8 +12,9 @@ "cloning": "Clonando repositório do Git...", "openrepo": "Abrir Repositório", "proposeopen": "Gostaria de abrir o repositório clonado?", - "path to init": "Caminho da pasta", - "provide path": "Por favor, forneça um caminho de pasta para inicializar um repositório Git", + "init repo": "Inicializar Repositório", + "create repo": "Inicializar Repositório", + "are you sure": "Isto irá criar um repositório Git em '{0}'. Tem certeza que deseja continuar?", "HEAD not available": "Versão HEAD de '{0}' não está disponível.", "confirm stage files with merge conflicts": "Tem certeza que deseja processar {0} arquivos com conflitos de mesclagem?", "confirm stage file with merge conflicts": "Tem certeza que deseja processar {0} com conflitos de mesclagem?", diff --git a/i18n/ptb/extensions/git/out/repository.i18n.json b/i18n/ptb/extensions/git/out/repository.i18n.json index d9855ba9df2..6c47d5f327f 100644 --- a/i18n/ptb/extensions/git/out/repository.i18n.json +++ b/i18n/ptb/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Excluído por nós", "both added": "Ambos adicionados", "both modified": "Ambos modificados", + "untracked, short": "U", + "modified, short": "M", "commit": "Confirmar", "merge changes": "Mesclar Alterações", "staged changes": "Alterações em Etapas", diff --git a/i18n/ptb/extensions/git/package.i18n.json b/i18n/ptb/extensions/git/package.i18n.json index f45cd09fb8b..8ca31f76ec1 100644 --- a/i18n/ptb/extensions/git/package.i18n.json +++ b/i18n/ptb/extensions/git/package.i18n.json @@ -15,6 +15,8 @@ "command.stageAll": "Estagiar Todas Alterações", "command.stageSelectedRanges": "Estagiar Faixas Selecionadas", "command.revertSelectedRanges": "Reverter Faixas Selecionadas", + "command.stageChange": "Mudança de fase", + "command.revertChange": "Reverter a alteração", "command.unstage": "Desestagiar Alterações", "command.unstageAll": "Desestagiar Todas Alterações", "command.unstageSelectedRanges": "Desestagiar Faixas Selecionadas", diff --git a/i18n/ptb/extensions/typescript/package.i18n.json b/i18n/ptb/extensions/typescript/package.i18n.json index 8b7415813f2..4bc0448e7a9 100644 --- a/i18n/ptb/extensions/typescript/package.i18n.json +++ b/i18n/ptb/extensions/typescript/package.i18n.json @@ -44,7 +44,8 @@ "typescript.npm": "Especifica o caminho para o executável do NPM usado para Aquisição de Tipo Automático. Requer TypeScript > = 2.3.4.", "typescript.check.npmIsInstalled": "Verificar se o NPM está instalado para aquisição automática de tipo.", "javascript.nameSuggestions": "Habilitar/desabilitar incluindo nomes exclusivos do arquivo nas listas de sugestão de JavaScript.", - "typescript.tsc.autoDetect": "Controla se a auto-detecção de tarefas tsc estão ligadas ou desligadas.", + "typescript.tsc.autoDetect": "Controla a auto deteção das tarefas de tsc. 'off' desativa esse recurso. 'build' só cria tarefas de compilação de execução única. 'watch' cria apenas tarefas de compilação e monitoramento. 'on' cria ambas as tarefas de compilar e monitoramento. Padrão é 'on'.", "typescript.problemMatchers.tsc.label": "Problemas TypeScript", - "typescript.problemMatchers.tscWatch.label": "Problemas TypeScript (modo observação)" + "typescript.problemMatchers.tscWatch.label": "Problemas TypeScript (modo observação)", + "typescript.quickSuggestionsForPaths": "Ativar/desativar sugestões rápidas quando estiver digitando um caminho de importação." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/ptb/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 473543c0850..fcd5681301a 100644 --- a/i18n/ptb/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Substituir", "label.replaceAllButton": "Substituir Tudo", "label.toggleReplaceButton": "Ativar/desativar modo Substituir", - "title.matchesCountLimit": "Somente os primeiros 999 resultados são realçados, mas todas as operações de pesquisa funcionam em todo o texto.", "label.matchesLocation": "{0} de {1}", "label.noResults": "Nenhum resultado" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/ptb/src/vs/editor/contrib/find/common/findController.i18n.json index 93f4b43b45c..ce656c20f36 100644 --- a/i18n/ptb/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Localizar Próxima Seleção", "previousSelectionMatchFindAction": "Localizar Seleção Anterior", "startReplace": "Substituir", - "addSelectionToNextFindMatch": "Adicionar Seleção ao Próximo Localizar Correspondência", - "addSelectionToPreviousFindMatch": "Adicionar Seleção à Correspondência de Localização Anterior", - "moveSelectionToNextFindMatch": "Mover Última Seleção para Próximo Localizar Correspondência", - "moveSelectionToPreviousFindMatch": "Mover Última Seleção para Correspondência de Localização Anterior", - "selectAllOccurrencesOfFindMatch": "Selecionar Todas as Ocorrências de Localizar Correspondência", - "changeAll.label": "Alterar todas as ocorrências", "showNextFindTermAction": "Mostrar Próximo Termo de Busca", "showPreviousFindTermAction": "Mostrar Termo de Busca Anterior" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/ptb/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index 583be5b3e5c..790c737c8eb 100644 --- a/i18n/ptb/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Inserir cursor acima", "mutlicursor.insertBelow": "Inserir cursor abaixo", - "mutlicursor.insertAtEndOfEachLineSelected": "Adicionar Cursores ao Final das Linhas" + "mutlicursor.insertAtEndOfEachLineSelected": "Adicionar Cursores ao Final das Linhas", + "addSelectionToNextFindMatch": "Adicionar Seleção ao Próximo Localizar Correspondência", + "addSelectionToPreviousFindMatch": "Adicionar Seleção à Correspondência de Localização Anterior", + "moveSelectionToNextFindMatch": "Mover Última Seleção para Próximo Localizar Correspondência", + "moveSelectionToPreviousFindMatch": "Mover Última Seleção para Correspondência de Localização Anterior", + "selectAllOccurrencesOfFindMatch": "Selecionar Todas as Ocorrências de Localizar Correspondência", + "changeAll.label": "Alterar todas as ocorrências" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json index 2c5e3a22276..a6b7b377cac 100644 --- a/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Formato inválido de cor. Use #RGB, #RGBA, #RRGGBB ou #RRGGBBAA", "schema.colors": "Cores usadas no workbench.", "foreground": "Cor de primeiro plano geral. Essa cor é só usada se não for substituída por um componente.", "errorForeground": "Cor de primeiro plano geral para mensagens de erro. Essa cor é só usada se não for substituída por um componente.", diff --git a/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json index f9516787ac6..5a005571d2b 100644 --- a/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,14 +9,17 @@ "addFolderToWorkspace": "Adicionar pasta ao espaço de trabalho...", "add": "&& Adicionar", "addFolderToWorkspaceTitle": "Adicionar pasta ao espaço de trabalho", + "globalRemoveFolderFromWorkspace": "Remover pasta da área de trabalho", "newWorkspace": "Novo espaço de trabalho...", "select": "&&Selecionar", "selectWorkspace": "Selecionar pastas para espaço de trabalho", "removeFolderFromWorkspace": "Remover pasta da área de trabalho", + "openFolderSettings": "Abrir configurações da pasta", "saveWorkspaceAsAction": "Salvar o espaço de trabalho como...", "save": "&&Salvar", "saveWorkspace": "Salvar o espaço de trabalho", "openWorkspaceAction": "Abrir o Espaço de Trabalho...", "openWorkspaceConfigFile": "Abrir o Arquivo de Configuração do Espaço de Trabalho", + "openFolderAsWorkspaceInNewWindow": "Abrir a pasta como espaço de trabalho em nova janela", "workspaceFolderPickerPlaceholder": "Selecione a pasta de trabalho" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index 577ad33d0b4..f42981ec157 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Ocultar a Barra de Atividades", - "activityBarAriaLabel": "Chave do Modo de exibição Ativo", "globalActions": "Ações globais" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..4a4304f83f0 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Chave do Modo de exibição Ativo" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..ab4fa3904b3 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "Visualizações Adicionais", + "numberBadge": "{0} ({1})", + "manageExtension": "Gerenciar Extensão", + "titleKeybinding": "{0} ({1})", + "hide": "Ocultar", + "toggle": "Alternar Visualização Fixa" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index e318ceb9434..d1d8a425227 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "Mostrar editores no segundo grupo", "groupThreePicker": "Mostrar editores no terceiro grupo", "allEditorsPicker": "Mostrar todos editores abertos", - "view": "Exibir" + "view": "Exibir", + "file": "Arquivo" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 4a2adabf5a6..b997093f4f8 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "O comando '{0}' não está habilitado e não pode ser executado.", "manageExtension": "Gerenciar Extensão" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json index 4f521d06910..8f50f5262de 100644 --- a/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,15 @@ "workspaces": "Espaços de trabalho", "developer": "Desenvolvedor", "showEditorTabs": "Controla se os editores abertos devem ou não serem exibidos em abas.", - "workbench.editor.labelFormat.default": "Mostrar o nome do arquivo. Quando as abas estão habilitadas e dois arquivos têm o mesmo nome em um grupo são adicionadas as seções de diferenciação do caminho de cada arquivo. Quando as abas estão desativadas, o caminho relativo para a raiz do espaço de trabalho é mostrado se o editor está ativo.", "workbench.editor.labelFormat.short": "Mostrar o nome do arquivo seguido pelo nome do diretório.", - "workbench.editor.labelFormat.medium": "Mostrar o nome do arquivo seguido pelo seu caminho relativo à raiz do espaço de trabalho.", "workbench.editor.labelFormat.long": "Mostrar o nome do arquivo seguido pelo seu caminho absoluto.", "tabDescription": "Controla o formato do rótulo para um editor. Alterar essa configuração pode por exemplo tornar mais fácil entender a localização de um arquivo:\n- curto: 'parent'\n- médio: 'workspace/src/parent'\n- longa: '/ home/user/workspace/src/parent'\n- padrão: '... /parent, quando outra guia compartilha o mesmo título, ou o caminho relativo do espaço de trabalho se as guias estão desabilitadas", "editorTabCloseButton": "Controla a posição dos botões de fechar das abas do editor ou os desabilita quando configurados para 'desligado'.", "showIcons": "Controla se os editores abertos devem ou não ser exibidos com um ícone. Requer um tema de ícone para ser habilitado. ", "enablePreview": "Controla se editores abertos mostram uma visualização. Editores de visualização são reutilizados até que eles sejam mantidos (por exemplo, através do duplo clique ou edição) e aparecerem com um estilo de fonte em itálico.", "enablePreviewFromQuickOpen": "Controla se os editores abertos da Abertura Rápida são exibidos como visualização. Os editores de visualização são reutilizados até serem preservados (por exemplo, através de um duplo clique ou edição).", - "editorOpenPositioning": "Controla onde os editores serão abertos. Escolha 'esquerda' ou 'direita' para abrir os editores à esquerda ou à direita do \neditor ativo. Selecione 'primeiro' ou 'último' para abrir os editores independentemente do atual.", "revealIfOpen": "Controla se um editor é exibido em qualquer um dos grupos, se aberto. Se desabilitado, um editor será aberto preferencialmente no grupo de editores ativo. Se habilitado, um editor já aberto será exibido no grupo de editores ativo, ao invés de ser aberto novamente. Note que há alguns casos onde esta configuração é ignorada, por exemplo, quando for forçada a abertura de um editor em um grupo específico ou ao lado do grupo atualmente ativo.", - "commandHistory": "Controla o número de comandos recentemente usados mantidos no histórico para a paleta de comandos. Definir como 0 para desativar o histórico de comandos.", + "commandHistory": "Controla o número de comandos usados recentemente a serem mantidos no histórico da paleta de comando. Definir como 0 para desativar o histórico de comandos.", "preserveInput": "Controla se a última entrada digitada na paleta de comandos deve ser restaurada ao abri-la da próxima vez.", "closeOnFocusLost": "Controla se Abertura Rápida deve fechar automaticamente caso perca o foco.", "openDefaultSettings": "Controla se a abertura de configurações também abre um editor mostrando todas as configurações padrão.", @@ -50,7 +47,7 @@ "restoreWindows": "Controla como as janelas serão reabertas após uma reinicialização. Selecione 'nenhum' para sempre iniciar com uma área de trabalho vazia, 'um' para reabrir a última janela que você trabalhou, 'pastas' para reabrir todas as janelas que tinham pastas abertas ou 'todos' para reabrir todas as janelas da sua última sessão.", "restoreFullscreen": "Controla se uma janela deve ser restaurada em modo de tela cheia se ela foi finalizada em modo de tela cheia.", "zoomLevel": "Ajusta o nível de zoom da janela. O tamanho original é 0 e cada aumento (por exemplo, 1) ou redução (por exemplo, -1) representa um zoom 20% maior ou menor. Você também pode digitar decimais para ajustar o nível de zoom com uma granularidade mais fina.", - "title": "Controla o título de janela baseado no editor do ativo. Variáveis são substituídas com base no contexto:\n${activeEditorShort}: por exemplo, MyFile.txt \n${activeEditorMedium}: por exemplo, myFolder/myFile.txt \n${activeEditorLong}: por exemplo, /Users/Development/myProject/myFolder/myFile.txt \n${folderName}: por exemplo myFolder \n${folderPath}: por exemplo, /Users/Development/myFolder \n${rootName}: por exemplo, myFolder1, myFolder2, myFolder3 \n${rootPath}: por exemplo, /Users/Development/myWorkspace \n${appName}: por exemplo, VS Code \n${dirty}: um indicador que mostra se o editor ativo está modificado\n${separator}: um separador condicional (\"-\") que é mostrado apenas quando cercado por variáveis com valores", + "title": "Controla o título de janela baseado no editor ativo. Variáveis são substituídas com base no contexto: \n${activeEditorShort}: o nome do arquivo (por exemplo, MyFile txt)\n${activeEditorMedium}: o caminho do arquivo relativo à pasta da área de trabalho (por exemplo, myFolder/myFile.txt) \n${activeEditorLong}: o caminho completo do arquivo (por exemplo, /Users/Development/myProject/myFolder/myFile.txt) \n${folderName}: nome da pasta de trabalho em que o arquivo está contido (por exemplo, myFolder) \n${folderPath}: caminho do arquivo da pasta de trabalho em que o arquivo está contido (por exemplo, /Users/Development/myFolder) {\n$(rootName}: nome do espaço de trabalho (por exemplo, myFolder ou myWorkspace)\n${rootPath}: caminho do espaço de trabalho (por exemplo, /Users/Development/myWorkspace) \n${appName}: por exemplo, VS Code\n${dirty}: um indicador se o editor ativo foi modificado\n${separator}: um separador condicional (\"-\") que é mostrado apenas quando cercado por variáveis com valores", "window.newWindowDimensions.default": "Abrir novas janelas no centro da tela.", "window.newWindowDimensions.inherit": "Abrir novas janelas com a mesma dimensão da última janela ativa.", "window.newWindowDimensions.maximized": "Abrir novas janelas maximizadas.", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 01955c44965..dd268ebad23 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,7 @@ { "entryAriaLabel": "depurar {0}", "debugAriaLabel": "Digite um nome de uma configuração de lançamento para ser executado.", + "addConfiguration": "Adicionar Configuração...", "noConfigurationsMatching": "Não há configurações de depuração correspondentes", "noConfigurationsFound": "Configurações de depuração não encontradas. Por favor, crie um arquivo 'launch.json'." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..7a6db36a29e --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Depurar" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..86ae4403f16 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debugFocusVariablesView": "Foco em Variáveis", + "debugFocusWatchView": "Foco em Monitoramento", + "debugFocusCallStackView": "Foco em Pilha de Chamadas", + "debugFocusBreakpointsView": "Foco em Pontos de Interrupção" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 05e76d32185..3908acc5028 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Configurações para gerar o 'launch.json' inicial.", "vscode.extension.contributes.debuggers.languages": "Lista de idiomas para os quais a extensão de depuração pode ser considerada o \"depurador padrão\".", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Se especificado VS Code chamará este comando para determinar o caminho do executável do adaptador de depuração e os argumentos para passar.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Se especificado VS Code chamará este comando para as ações de \"depurar\" ou \"executar\" direcionadas para esta extensão.", "vscode.extension.contributes.debuggers.configurationSnippets": "Trechos de código para adicionar novas configurações em 'launch.json'.", "vscode.extension.contributes.debuggers.configurationAttributes": "Configurações de esquema JSON para validar 'launch.json'.", "vscode.extension.contributes.debuggers.windows": "Configurações específicas do Windows.", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index aaf52e5dedb..5e4eb26c208 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,10 @@ "breakpointRemoved": "Ponto de interrupção removido, linha {0}, arquivo {1}", "compoundMustHaveConfigurations": "Composição deve ter o atributo \"configurations\" definido para iniciar várias configurações.", "configMissing": "Configuração '{0}' não tem 'launch.json'.", - "debugRequestNotSupported": "Configuração de depuração escolhido possui um valor de atributo não suportado '{0}': '{1}'.", - "debugRequesMissing": "Atributo '{0}' está faltando para a configuração de depuração escolhida.", + "debugRequestNotSupported": "Atributo '{0}' tem um valor sem suporte '{1}' na configuração de depuração escolhida.", + "debugRequesMissing": "Atributo '{0}' está faltando na configuração de depuração escolhida.", "debugTypeNotSupported": "Tipo de depuração configurado '{0}' não é suportado.", - "debugTypeMissing": "Falta a propriedade 'type' para a configuração de lançamento escolhida.", + "debugTypeMissing": "Falta a propriedade 'tipo' para a configuração de lançamento escolhida.", "preLaunchTaskErrors": "Erros de build foram detectados durante a preLaunchTask '{0}'.", "preLaunchTaskError": "Erro de build foi detectado durante a preLaunchTask '{0}'.", "preLaunchTaskExitCode": "A preLaunchTask '{0}' encerrada com código de saída {1}.", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 4afd6d64d82..5f2a144a70e 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -8,5 +8,5 @@ "replVariableAriaLabel": "Variável {0} tem valor {1}, ler a impressão do valor do loop, depurar", "replExpressionAriaLabel": "Expressão {0} tem valor {1}, ler o laço de avaliação de impressão, depurar", "replValueOutputAriaLabel": " impressão da avaliação do laço de leitura, depurar", - "replKeyValueOutputAriaLabel": "Variável de saída {0} tem valor {1}, ler o loop de avaliação de impressão, depurar" + "replRawObjectAriaLabel": "Variável repl {0} tem valor {1}, ler o loop de avaliação de impressão e depuração" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index 39deecf379b..464da97e4e9 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Arquivos", + "filesCategory": "Arquivo", "revealInSideBar": "Revelar na Barra Lateral", "acceptLocalChanges": "Usar suas alterações e substituir o conteúdo do disco", "revertLocalChanges": "Descartar as alterações e reverter para o conteúdo no disco" diff --git a/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 99af18bd13e..674a4dedbf2 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -23,6 +23,7 @@ "confirmMoveTrashMessageFile": "Tem certeza de que deseja excluir '{0}'?", "undoBin": "Você pode restaurar da lixeira.", "undoTrash": "Você pode restaurar a partir do lixo.", + "doNotAskAgain": "Não me pergunte novamente", "confirmDeleteMessageFolder": "Tem certeza de que deseja excluir permanentemente '{0}' e seu conteúdo?", "confirmDeleteMessageFile": "Tem certeza de que deseja excluir permanentemente '{0}'?", "irreversible": "Esta ação é irreversível!", @@ -37,8 +38,6 @@ "openToSide": "Aberto para o lado", "compareSource": "Selecione para comparar", "globalCompareFile": "Compare o Arquivo Ativo Com...", - "pickHistory": "Selecione um arquivo previamente aberto para comparar com", - "unableToFileToCompare": "O arquivo selecionado não pode ser comparado com '{0}'.", "openFileToCompare": "Abrir um arquivo primeiro para compará-lo com outro arquivo.", "compareWith": "Comparar '{0}' com '{1}'", "compareFiles": "Comparar Arquivos", @@ -47,7 +46,7 @@ "saveAs": "Salvar como...", "saveAll": "Salvar Todos", "saveAllInGroup": "Salvar Todos no Grupo", - "saveFiles": "Salvar Arquivos Sujos", + "saveFiles": "Salvar todos os arquivos", "revert": "Reverter Arquivo", "focusOpenEditors": "Foco na Visualização dos Editores Abertos", "focusFilesExplorer": "Foco no Explorador de Arquivos", diff --git a/i18n/ptb/src/vs/workbench/parts/files/browser/files.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/browser/files.contribution.i18n.json index 8100b458672..0e95d226253 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/browser/files.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/browser/files.contribution.i18n.json @@ -40,10 +40,14 @@ "dynamicHeight": "Controla se a altura da seção de editores abertos deve adaptar-se dinamicamente para o número de elementos ou não.", "autoReveal": "Controla se o explorador deve automaticamente revelar e selecionar arquivos ao abri-los.", "enableDragAndDrop": "Controla se o explorador deve permitir mover arquivos e pastas através de arrastar e soltar.", + "confirmDragAndDrop": "Controla se o explorer deve pedir a confirmação ao mover arquivos ou pastas através de arrastar e soltar.", + "confirmDelete": "Controla se o explorador deve pedir a confirmação ao excluir um arquivo por meio do lixo.", "sortOrder.default": "Arquivos e pastas são classificadas por seus nomes, em ordem alfabética. Pastas são exibidas acima dos arquivos.", "sortOrder.mixed": "Arquivos e pastas são classificadas por seus nomes, em ordem alfabética. Arquivos são misturados com pastas.", "sortOrder.filesFirst": "Arquivos e pastas são classificadas por seus nomes, em ordem alfabética. Os arquivos são exibidos acima das pastas.", "sortOrder.type": "Arquivos e pastas são classificadas de acordo com suas extensões, em ordem alfabética. Pastas são exibidas acima dos arquivos.", "sortOrder.modified": "Arquivos e pastas são classificados de acordo com a data da última modificação, em ordem decrescente. Pastas são exibidas acima dos arquivos.", - "sortOrder": "Controla a ordem de classificação dos arquivos e pastas no explorador. Além da classificação padrão, você pode definir a ordem para 'mixed' (arquivos e pastas misturados), 'type' (por tipo de arquivo), 'modified' (pela data da última modificação) ou 'filesFirst' (exibe os arquivos acima das pastas)." + "sortOrder": "Controla a ordem de classificação dos arquivos e pastas no explorador. Além da classificação padrão, você pode definir a ordem para 'mixed' (arquivos e pastas misturados), 'type' (por tipo de arquivo), 'modified' (pela data da última modificação) ou 'filesFirst' (exibe os arquivos acima das pastas).", + "explorer.decorations.colors": "Controles se as decorações de arquivo devem usar cores.", + "explorer.decorations.badges": "Controles se as decorações de arquivo devem usar identificações." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 38f98ed9420..69f48bde47d 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,8 @@ { "noWorkspace": "Nenhuma Pasta Aberta", "explorerSection": "Seção de Explorador de Arquivos", - "noWorkspaceHelp": "Você ainda não abriu uma pasta.", + "noWorkspaceHelp": "Você ainda não adicionou uma pasta no espaço de trabalho.", + "addFolder": "Adicionar pasta", + "noFolderHelp": "Você ainda não abriu uma pasta.", "openFolder": "Abrir Pasta" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json index d321f8c15ce..f5321d10375 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/browser/views/explorerViewer.i18n.json @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "canNotResolve": "Não pode resolver a pasta {0}", "fileInputAriaLabel": "Digite o Nome do arquivo. Pressione Enter para confirmar ou Escape para cancelar.", "filesExplorerViewerAriaLabel": "{0}, Explorador de Arquivos", "dropFolders": "Você quer adicionar as pastas no espaço de trabalho?", "dropFolder": "Você quer adicionar a pasta no espaço de trabalho?", "addFolders": "&& Adicionar pastas", "addFolder": "&& Adicionar pasta", + "confirmMove": "Tem certeza que deseja mover '{0}'?", + "doNotAskAgain": "Não me pergunte novamente", "confirmOverwriteMessage": "'{0}' já existe na pasta de destino. Deseja substituí-lo?", "irreversible": "Esta ação é irreversível!", "replaceButtonLabel": "&&Substituir" diff --git a/i18n/ptb/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..62c14983ac7 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Problemas", + "tooltip.1": "1 problema neste arquivo", + "tooltip.N": "{0} problemas neste arquivo", + "markers.showOnFile": "Mostre erros e avisos no arquivos e pasta." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 1b5d84180e9..10a0c7ab0f2 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Coloque as suas configurações aqui para substituir as configurações padrão.", - "errorInvalidConfiguration": "Não é possível gravar em configurações. Corrija erros/avisos no arquivo e tente novamente.", "emptyWorkspaceSettingsHeader": "Coloque as suas configurações aqui para substituir as configurações de usuário.", "emptyFolderSettingsHeader": "Coloque as suas configurações de pasta aqui para substituir aqueles das configurações do espaço de trabalho.", "defaultFolderSettingsTitle": "Configurações de pasta padrão", diff --git a/i18n/ptb/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/ptb/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index b6d5cdbd2e5..e45b8e421e8 100644 --- a/i18n/ptb/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "O comando '{0}' não está habilitado no contexto atual.", "recentlyUsed": "usados recentemente", "morecCommands": "outros comandos", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "Não há comandos correspondentes" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json index f9640a94d5a..2ab571fe333 100644 --- a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.i18n.json @@ -4,6 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "changes": "{0} de {1} mudanças", + "change": "{0} de {1} mudança", + "show previous change": "Mostrar a Alteração Anterior", + "show next change": "Mostrar a Próxima Alteração", "editorGutterModifiedBackground": "Cor de fundo da dobra do editor para as linhas que estão modificadas.", "editorGutterAddedBackground": "Cor de fundo da dobra do editor para as linhas que estão adicionadas.", "editorGutterDeletedBackground": "Cor de fundo da dobra do editor para as linhas que estão excluídas.", diff --git a/i18n/ptb/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index 6e7cef32f55..477df0fd694 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,7 @@ "exclude": "Configure os padrões glob para excluir arquivos e pastas nas pesquisas. Herda todos os padrões glob da configuração files.exclude.", "exclude.boolean": "O padrão glob com o qual combinar os caminhos de arquivo. Defina para verdadeiro ou falso para habilitar ou desabilitar o padrão.", "exclude.when": "Verificação adicional nos irmãos de um arquivo correspondente. Use $(basename) como variável para o nome do arquivo correspondente.", - "useRipgrep": "Controla se deve utilizar ripgrep na pesquisa de texto", + "useRipgrep": "Controla se utiliza ripgrep em buscas de texto e de arquivo", "useIgnoreFilesByDefault": "Controla se deve utilizar arquivos .gitignore e .ignore por padrão ao fazer pesquisas em um novo espaço de trabalho.", "search.quickOpen.includeSymbols": "Configurar para incluir resultados de uma pesquisa símbolo global nos resultados do arquivo para Abertura Rápida." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json index cd879d71747..933840a7fc3 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Limpar os Resultados da Pesquisa", "FocusNextSearchResult.label": "Focalizar o Próximo Resultado da Pesquisa", "FocusPreviousSearchResult.label": "Focalizar o Resultado da Pesquisa Anterior", - "RemoveAction.label": "Remover", "file.replaceAll.label": "Substituir Tudo", "match.replace.label": "Substituir" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index d1afc5ef25a..61f582e57b8 100644 --- a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Contribui aos trechos de código.", "vscode.extension.contributes.snippets-language": "Identificador de linguagem para o qual este trecho de código contribui.", "vscode.extension.contributes.snippets-path": "Caminho do arquivo de trechos de código. O caminho é relativo à pasta de extensão e normalmente começa com '. /snippets/'.", - "badFile": "O arquivo de trechos \"{0}\" não pôde ser lido.", "badVariableUse": "O trecho de código \"{0}\" muito provavelmente confunde as variáveis de trecho de código e espaços reservados do trecho de código. Consulte https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax para obter mais detalhes.", + "badFile": "O arquivo de trechos \"{0}\" não pôde ser lido.", "source.snippet": "Trecho de código do usuário", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 526a6233a3d..7841731c435 100644 --- a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -14,6 +14,7 @@ "runningTasks": "Mostrar tarefas em execução", "tasks": "Tarefas", "TaskSystem.noHotSwap": "Alterar o mecanismo de execução da tarefa com uma tarefa ativa executando exige que a janela seja recarregada", + "TaskServer.folderIgnored": "A pasta {0} é ignorada desde que use a versão de tarefas 0.1.0", "TaskService.noBuildTask1": "Nenhuma tarefa de compilação definida. Marque uma tarefa com 'isBuildCommand' no arquivo tasks.json.", "TaskService.noBuildTask2": "Nenhuma tarefa de compilação definida. Marque uma tarefa como um grupo 'build' no arquivo tasks.json.", "TaskService.noTestTask1": "Nenhuma tarefa de teste definida. Marque uma tarefa com 'isTestCommand' no arquivo tasks.json.", @@ -30,6 +31,7 @@ "TaskSystem.activeSame.noBackground": "A tarefa '{0}' já está ativa. Para finalizá-la use 'Finalizar Tarefa' no menu Tarefas.", "TaskSystem.active": "Já existe uma tarefa sendo executada. Finalize-a antes de executar outra tarefa.", "TaskSystem.restartFailed": "Falha ao finalizar e reiniciar a tarefa {0}", + "TaskService.noConfiguration": "Erro: A deteção de tarefa {0} não contribuiu para uma tarefa para a seguinte configuração: {1} a tarefa será ignorada.\n", "TaskSystem.configurationErrors": "Erro: A configuração da tarefa informada possui erros de validação e não pode ser utilizada. Por favor, corrija os erros primeiro.", "taskService.ignoreingFolder": "Ignorar as configurações de tarefa para a pasta de trabalho {0}. Suporte a tarefas de espaço de trabalho de múltiplas pastas requer que todas as pastas usem a versão de tarefas 2.0.0\n", "TaskSystem.invalidTaskJson": "Erro: O conteúdo do arquivo tasks.json possui erros de sintaxe. Por favor, corrija-os antes de executar uma tarefa.\n", diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index b075d6f0b92..f4a78b8d461 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -17,6 +17,7 @@ "terminal.integrated.fontFamily": "Controla a família de fontes do terminal, este padrão é o valor do editor.fontFamily.", "terminal.integrated.fontSize": "Controla o tamanho da fonte em pixels do terminal.", "terminal.integrated.lineHeight": "Controles a altura da linha do terminal, este número é multiplicada pelo tamanho da fonte terminal para obter a altura real da linha em pixels.", + "terminal.integrated.enableBold": "Se deseja habilitar o texto em negrito dentro do terminal, note que isso requer o apoio do shell do terminal.", "terminal.integrated.cursorBlinking": "Controla se o cursor do terminal pisca.", "terminal.integrated.cursorStyle": "Controla o estilo do cursor do terminal.", "terminal.integrated.scrollback": "Controla a quantidade máxima de linhas que o terminal mantém em seu buffer.", diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 7379c161275..2ee45b6deb3 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Novo Terminal", "workbench.action.terminal.focus": "Focalizar Terminal", "workbench.action.terminal.focusNext": "Focalizar Próximo Terminal", - "workbench.action.terminal.focusAtIndex": "Focalizar Terminal {0}", "workbench.action.terminal.focusPrevious": "Focalizar Terminal Anterior", "workbench.action.terminal.paste": "Colar no Terminal Ativo", "workbench.action.terminal.DefaultShell": "Selecionar Shell Padrão", diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 2bbfefe2297..ef05288e718 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Copiar", - "createNewTerminal": "Novo Terminal", "paste": "Colar", "selectAll": "Selecionar Tudo", "clear": "Limpar" diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 08ec4bd9777..83214ad4be8 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "Ok, Nunca Mostrar Novamente", "terminal.integrated.chooseWindowsShell": "Selecione o seu terminal shell preferido, você pode alterar isso mais tarde em suas configurações", "terminalService.terminalCloseConfirmationSingular": "Há uma sessão ativa de terminal, você quer finalizá-la?", - "terminalService.terminalCloseConfirmationPlural": "Existem {0} sessões ativas de terminal, você quer finalizá-las?", - "yes": "Sim" + "terminalService.terminalCloseConfirmationPlural": "Existem {0} sessões ativas de terminal, você quer finalizá-las?" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/ptb/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..5d3bc21b50f --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Um resumo das configurações. Este rótulo será usado no arquivo de configurações como um comentário de separação.", + "vscode.extension.contributes.configuration.properties": "Descrição das propriedades de configuração.", + "scope.window.description": "Janela de configuração específica que pode ser configurada nas configurações do usuário ou área de trabalho.", + "scope.resource.description": "Configuração específica do recurso que pode ser configurada nas configurações do usuário, espaço de trabalho ou pasta.", + "vscode.extension.contributes.configuration": "Contribui às definições de configuração.", + "invalid.title": "'configuration.title' deve ser um string", + "vscode.extension.contributes.defaultConfiguration": "Contribui às definições de configuração padrão do editor por linguagem.", + "invalid.properties": "'configuration.properties' deve ser um objeto", + "invalid.allOf": "'configuration.allOf' está obsoleto e não deve ser usado. Em vez disso, passe várias seções de configuração como uma matriz para o ponto de contribuição 'configuration'.", + "workspaceConfig.folders.description": "Lista de pastas a serem carregadas no espaço de trabalho.", + "workspaceConfig.path.description": "Um caminho para um arquivo. Por exemplo, '/root /pastaA' ou './pastaA' para um caminho relativo que será determinado de acordo com o local do arquivo no espaço de trabalho.", + "workspaceConfig.settings.description": "Configurações de espaço de trabalho", + "workspaceConfig.extensions.description": "Extensões para o espaço de trabalho", + "unknownWorkspaceProperty": "Propriedade de configuração do espaço de trabalho desconhecida" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/ptb/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index 0f7a663082c..ca77d82093c 100644 --- a/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -6,6 +6,7 @@ { "schema.token.settings": "Cores e estilos para o token.", "schema.token.foreground": "Cor do primeiro plano para o token.", + "schema.token.background.warning": "Atualmente as cores de fundo do token não são suportadas.", "schema.token.fontStyle": "Estilo da fonte da regra: um estilo ou uma combinação de 'itálico', 'negrito' e 'sublinhado'", "schema.fontStyle.error": "O estilo da fonte deve ser uma combinação de 'itálico', 'negrito' e 'sublinhado'", "schema.properties.name": "Descrição da regra.", diff --git a/i18n/ptb/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index 3cf20c82de2..ddfc13e6a19 100644 --- a/i18n/ptb/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -33,5 +33,6 @@ "schema.fontSize": "Quando estiver utilizando uma fonte: O tamanho da fonte em porcentagem para a fonte de texto. Se não for definido, o padrão é o tamanho na definição de fonte.", "schema.fontId": "Quando estiver utilizando uma fonte: A identificação da fonte. Se não for definido, o padrão é a primeira definição de fonte.", "schema.light": "Associações opcionais para ícones de arquivo em temas de cor clara.", - "schema.highContrast": "Associações opcionais para ícones de arquivo em temas de alto contraste." + "schema.highContrast": "Associações opcionais para ícones de arquivo em temas de alto contraste.", + "schema.hidesExplorerArrows": "Define se as setas do explorador de arquivos devem ser ocultadas quando este tema está ativo." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..938c7bbea81 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contribui com temas de cores do textmate.", + "vscode.extension.contributes.themes.id": "ID do tema do ícone como usado em configurações do usuário.", + "vscode.extension.contributes.themes.label": "Etiqueta da cor do tema como mostrado na interface do usuário.", + "vscode.extension.contributes.themes.uiTheme": "Tema base de definição das cores do editor: 'vs' é o tema de cor clara, 'vs-dark' é o tema de cor escura. 'hc preto' é o tema escuro de alto contraste.", + "vscode.extension.contributes.themes.path": "Caminho do arquivo tmTheme. O caminho é relativo à pasta de extensão e é normalmente './themes/themeFile.tmTheme'.", + "reqarray": "Ponto de extensão '{0}' deve ser uma matriz.", + "reqpath": "Esperada uma string em `contributes.{0}.path`. Valor informado: {1}", + "invalid.path.1": "É esperado que `contributes.{0}.path` ({1}) seja incluído na pasta da extensão ({2}). Isto pode tornar a extensão não portável." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..f78a56c0249 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problemas de análise do arquivo de ícones: {0}" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..0181b35ac2a --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contribui com temas de ícones de arquivo.", + "vscode.extension.contributes.iconThemes.id": "ID do tema do ícone como usado em configurações do usuário.", + "vscode.extension.contributes.iconThemes.label": "Etiqueta do tema do ícone como mostrado na interface do usuário.", + "vscode.extension.contributes.iconThemes.path": "Caminho do arquivo de definição do tema do ícone. O caminho é relativo à pasta de extensão e é normalmente './icons/awesome-icon-theme.json'.", + "reqarray": "Ponto de extensão '{0}' deve ser uma matriz.", + "reqpath": "Esperada uma string em `contributes.{0}.path`. Valor informado: {1}", + "reqid": "Esperada sequência em 'contributes.{0}.ID'. Valor fornecido: {1}", + "invalid.path.1": "É esperado que `contributes.{0}.path` ({1}) seja incluído na pasta da extensão ({2}). Isto pode tornar a extensão não portável." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index db248225f67..d27ccd6f4ab 100644 --- a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contribui com temas de cores do textmate.", - "vscode.extension.contributes.themes.id": "ID do tema do ícone conforme usado em configurações do usuário.", - "vscode.extension.contributes.themes.label": "Etiqueta da cor do tema como mostrado na interface do usuário.", - "vscode.extension.contributes.themes.uiTheme": "Tema base de definição das cores do editor: 'vs' é o tema de cor clara, 'vs-dark' é o tema de cor escura. 'hc preto' é o tema escuro de alto contraste.", - "vscode.extension.contributes.themes.path": "Caminho do arquivo tmTheme. O caminho é relativo à pasta de extensão e é normalmente './themes/themeFile.tmTheme'.", - "vscode.extension.contributes.iconThemes": "Contribui com temas de ícones de arquivo.", - "vscode.extension.contributes.iconThemes.id": "ID do tema do ícone como usado em configurações do usuário.", - "vscode.extension.contributes.iconThemes.label": "Etiqueta do tema do ícone como mostrado na interface do usuário.", - "vscode.extension.contributes.iconThemes.path": "Caminho do arquivo de definição do tema do ícone. O caminho é relativo à pasta de extensão e é normalmente './icons/awesome-icon-theme.json'.", "migration.completed": "Foram adicionadas novas configurações de tema para as configurações de usuário. Backup está disponível em {0}.", "error.cannotloadtheme": "Não é possível carregar {0}: {1}", - "reqarray": "Ponto de extensão '{0}' deve ser uma matriz.", - "reqpath": "Esperada uma string em `contributes.{0}.path`. Valor informado: {1}", - "invalid.path.1": "É esperado que `contributes.{0}.path` ({1}) seja incluído na pasta da extensão ({2}). Isto pode tornar a extensão não portável.", - "reqid": "Esperada sequência em 'contributes.{0}.ID'. Valor fornecido: {1}", "error.cannotloadicontheme": "Não é possível carregar {0}", - "error.cannotparseicontheme": "Problemas de análise do arquivo de ícones: {0}", "colorTheme": "Especifica o tema de cores usado no espaço de trabalho.", "colorThemeError": "Tema é desconhecido ou não está instalado.", "iconTheme": "Especifica o tema de ícones usado no espaço de trabalho ou 'null' para não mostrar qualquer arquivo de ícones.", "noIconThemeDesc": "Nenhum arquivo de ícones", "iconThemeError": "Arquivo de tema de ícones é desconhecido ou não está instalado.", "workbenchColors": "Substitui as cores do tema do tema de cores atualmente selecionado.", - "workbenchColors.deprecated": "A configuração não é mais experimental e foi renomeada para 'workbench.colorCustomizations'", - "workbenchColors.deprecatedDescription": "Use 'workbench.colorCustomizations'", "editorColors": "Substitui as cores e o estilo da fonte do editor do tema de cores atualmente selecionado.", "editorColors.comments": "Define as cores e estilos para os comentários", "editorColors.strings": "Define as cores e estilos para textos literais.", diff --git a/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..ddf43c7774f --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Abrir o Arquivo de Configuração do Espaço de Trabalho", + "close": "Fechar" +} \ No newline at end of file diff --git a/i18n/rus/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/rus/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 8760c57e674..a691501ffe0 100644 --- a/i18n/rus/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/rus/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "например, myFile.txt", - "activeEditorMedium": "например, myFolder/myFile.txt", - "activeEditorLong": "например, /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "например, myFolder1, myFolder2, myFolder3", - "rootPath": "например, /Users/Development/myProject", - "folderName": "например, myFolder", - "folderPath": "например, /Users/Development/myFolder", "appName": "например, VS Code", "dirty": "индикатор dirty, если активный редактор является \"грязным\"", "separator": "условный разделитель (-), который отображается, только если окружен переменными со значениями", diff --git a/i18n/rus/extensions/emmet/package.i18n.json b/i18n/rus/extensions/emmet/package.i18n.json index 5df2b4e5410..3c7e7099a9d 100644 --- a/i18n/rus/extensions/emmet/package.i18n.json +++ b/i18n/rus/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "Увеличить значение на 10", "command.decrementNumberByTen": "Уменьшить значение на 10", "emmetSyntaxProfiles": "Задайте профиль для указанного синтаксиса или используйте свой собственный профиль с определенными правилами.", - "emmetExclude": "Массив языков, в которых не должны развертываться сокращения Emmet.", - "emmetExtensionsPath": "Путь к папке, содержащей профили Emmet и фрагменты кода.", - "emmetShowExpandedAbbreviation": "Отображает развернутые сокращения Emmet в виде предложений.\nПараметр \"inMarkupAndStylesheetFilesOnly\" применяется к html, haml, jade, slim, xml, xsl, css, scss, sass, less и stylus .\nПараметр \"always\" применяется ко всем частям файла независимо от разметки и стилей.", - "emmetShowAbbreviationSuggestions": "Отображает возможные сокращения Emmet в виде предложений. Не применяется в таблицах стилей или если параметр emmet.showExpandedAbbreviation имеет значение \"never\".", - "emmetIncludeLanguages": "Включает сокращения Emmet в языках, которые не поддерживаются по умолчанию. Здесь можно указать связь между не поддерживаемым и поддерживаемым языками.\nПример: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", - "emmetVariables": "Переменные, которые будут использоваться во фрагментах Emmet", - "emmetTriggerExpansionOnTab": "Если включено, сокращения Emmet разворачиваются при нажатии клавиши TAB.", "emmetPreferences": "Настройки, которые используются для изменения поведения некоторых действий и сопоставителей Emmet.", "emmetPreferencesIntUnit": "Единица по умолчанию для целочисленных значений", "emmetPreferencesFloatUnit": "Единица по умолчанию для значений с плавающей запятой", @@ -43,6 +36,5 @@ "emmetPreferencesStylusAfter": "Символ, который будет помещен в конце свойства CSS при развертывании сокращений CSS в файлах Stylus", "emmetPreferencesCssBetween": "Символ, который будет помещен между свойством CSS и значением при развертывании сокращений CSS", "emmetPreferencesSassBetween": "Символ, который будет помещен между свойством CSS и значением при развертывании сокращений CSS в файлах Sass", - "emmetPreferencesStylusBetween": "Символ, который будет помещен между свойством CSS и значением при развертывании сокращений CSS в файлах Stylus", - "emmetShowSuggestionsAsSnippets": "Если этот параметр имеет значение true, предложения Emmet будут отображаться в виде фрагментов, которые можно упорядочить с помощью параметра editor.snippetSuggestions." + "emmetPreferencesStylusBetween": "Символ, который будет помещен между свойством CSS и значением при развертывании сокращений CSS в файлах Stylus" } \ No newline at end of file diff --git a/i18n/rus/extensions/git/out/commands.i18n.json b/i18n/rus/extensions/git/out/commands.i18n.json index 633cd74962b..f8b4fce36b0 100644 --- a/i18n/rus/extensions/git/out/commands.i18n.json +++ b/i18n/rus/extensions/git/out/commands.i18n.json @@ -12,8 +12,8 @@ "cloning": "Клонируется репозиторий Git...", "openrepo": "Открыть репозиторий", "proposeopen": "Вы хотите открыть клонированный репозиторий?", - "path to init": "Путь к папке", - "provide path": "Укажите путь к папке для инициализации репозитория Git", + "init repo": "Инициализировать репозиторий", + "create repo": "Инициализировать репозиторий", "HEAD not available": "Версия HEAD '{0}' недоступна.", "confirm stage files with merge conflicts": "Вы действительно хотите перенести в промежуточный этап файлы с конфликтами слияния ({0})?", "confirm stage file with merge conflicts": "Вы действительно хотите перенести в промежуточный этап файлы с конфликтами слияния ({0})?", diff --git a/i18n/rus/extensions/git/out/repository.i18n.json b/i18n/rus/extensions/git/out/repository.i18n.json index 053f8f8b45f..019265640e5 100644 --- a/i18n/rus/extensions/git/out/repository.i18n.json +++ b/i18n/rus/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Удалено нами", "both added": "Добавлено обеими сторонами", "both modified": "Изменено обеими сторонами", + "untracked, short": "U", + "modified, short": "M", "commit": "Commit", "merge changes": "Объединить изменения", "staged changes": "Промежуточно сохраненные изменения", diff --git a/i18n/rus/extensions/typescript/package.i18n.json b/i18n/rus/extensions/typescript/package.i18n.json index aeaeec49a6a..15940c3fc59 100644 --- a/i18n/rus/extensions/typescript/package.i18n.json +++ b/i18n/rus/extensions/typescript/package.i18n.json @@ -44,7 +44,6 @@ "typescript.npm": "Указывает путь к исполняемому файлу NPM, используемому для автоматического получения типа. Требуется TypeScript версии 2.3.4 или более поздней версии.", "typescript.check.npmIsInstalled": "Проверяет, установлен ли NPM для автоматического получения типов.", "javascript.nameSuggestions": "Включить/отключить использование уникальных имен из файла в списках предложений JavaScript.", - "typescript.tsc.autoDetect": "Включает или отключает автоматическое определние заданий tsc.", "typescript.problemMatchers.tsc.label": "Проблемы TypeScript", "typescript.problemMatchers.tscWatch.label": "Проблемы TypeScript (режим наблюдения)" } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/rus/src/vs/editor/contrib/find/browser/findWidget.i18n.json index 56455258496..32fb3e012c8 100644 --- a/i18n/rus/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Заменить", "label.replaceAllButton": "Заменить все", "label.toggleReplaceButton": "Режим \"Переключение замены\"", - "title.matchesCountLimit": "Отображаются только первые 999 результатов, но все операции поиска выполняются со всем текстом.", "label.matchesLocation": "{0} из {1}", "label.noResults": "Нет результатов" } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/rus/src/vs/editor/contrib/find/common/findController.i18n.json index 5cbc15bce8a..5c6f87afd29 100644 --- a/i18n/rus/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Найти следующее выделение", "previousSelectionMatchFindAction": "Найти предыдущее выделение", "startReplace": "Заменить", - "addSelectionToNextFindMatch": "Добавить выделение в следующее найденное совпадение", - "addSelectionToPreviousFindMatch": "Добавить выделенный фрагмент в предыдущее найденное совпадение", - "moveSelectionToNextFindMatch": "Переместить последнее выделение в следующее найденное совпадение", - "moveSelectionToPreviousFindMatch": "Переместить последний выделенный фрагмент в предыдущее найденное совпадение", - "selectAllOccurrencesOfFindMatch": "Выбрать все вхождения найденных совпадений", - "changeAll.label": "Изменить все вхождения", "showNextFindTermAction": "Показать следующий найденный термин", "showPreviousFindTermAction": "Показать предыдущий найденный термин" } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/rus/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index de410095204..660193a943e 100644 --- a/i18n/rus/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Добавить курсор выше", "mutlicursor.insertBelow": "Добавить курсор ниже", - "mutlicursor.insertAtEndOfEachLineSelected": "Добавить курсоры к окончаниям строк" + "mutlicursor.insertAtEndOfEachLineSelected": "Добавить курсоры к окончаниям строк", + "addSelectionToNextFindMatch": "Добавить выделение в следующее найденное совпадение", + "addSelectionToPreviousFindMatch": "Добавить выделенный фрагмент в предыдущее найденное совпадение", + "moveSelectionToNextFindMatch": "Переместить последнее выделение в следующее найденное совпадение", + "moveSelectionToPreviousFindMatch": "Переместить последний выделенный фрагмент в предыдущее найденное совпадение", + "selectAllOccurrencesOfFindMatch": "Выбрать все вхождения найденных совпадений", + "changeAll.label": "Изменить все вхождения" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json index dbab65f5dc7..4de61ec7ef4 100644 --- a/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Недопустимый формат цвета. Используйте #RGB, #RGBA, #RRGGBB или #RRGGBBAA", "schema.colors": "Цвета, используемые на рабочем месте.", "foreground": "Общий цвет переднего плана. Этот цвет используется, только если его не переопределит компонент.", "errorForeground": "Общий цвет переднего плана для сообщений об ошибках. Этот цвет используется только если его не переопределяет компонент.", diff --git a/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 3dc67610b94..8ad801af2f1 100644 --- a/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -13,6 +13,7 @@ "select": "&&Выбрать", "selectWorkspace": "Выбрать папки для рабочей области", "removeFolderFromWorkspace": "Удалить папку из рабочей области", + "openFolderSettings": "Открыть параметры папок", "saveWorkspaceAsAction": "Сохранить рабочую область как...", "save": "Сохранить", "saveWorkspace": "Сохранить рабочую область", diff --git a/i18n/rus/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index cdc81741e9e..946bb84393f 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Скрыть панель действий", - "activityBarAriaLabel": "Переключатель активного представления", "globalActions": "Глобальные действия" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..c9f39eaf3a5 --- /dev/null +++ b/i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Переключатель активного представления" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..0e338824c87 --- /dev/null +++ b/i18n/rus/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "Дополнительные представления", + "numberBadge": "{0} ({1})", + "manageExtension": "Управление расширениями", + "titleKeybinding": "{0} ({1})", + "toggle": "Переключить закрепленное представление" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 75bbb3e9519..3c123d9ce41 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "Показать редакторы во второй группе", "groupThreePicker": "Показать редакторы в третьей группе", "allEditorsPicker": "Показать все открытые редакторы", - "view": "Просмотр" + "view": "Просмотр", + "file": "Файл" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index 000e440a7b7..2fc29a94bab 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "Команда \"{0}\" сейчас неактивна, и ее невозможно выполнить.", "manageExtension": "Управление расширениями" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json index 1de29e6dd0e..6887c80a117 100644 --- a/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,14 @@ "workspaces": "Рабочие области", "developer": "Разработчик", "showEditorTabs": "Определяет, должны ли открытые редакторы отображаться на вкладках или нет.", - "workbench.editor.labelFormat.default": "Отображать имя файла. Если вкладки включены и в одной группе есть два файла с одинаковыми именами, будут добавлены различающиеся части пути к каждому из этих файлов. Если вкладки отключены, то для активного редактора отображается путь по отношению к корневому каталогу рабочей области.", "workbench.editor.labelFormat.short": "Отображать имя файла и имя каталога.", - "workbench.editor.labelFormat.medium": "Отображать имя файла и путь к файлу относительно корневого каталога рабочей области.", "workbench.editor.labelFormat.long": "Отображать имя файла и абсолютный путь.", "tabDescription": "Определяет формат метки редактора. Изменив этот параметр, можно сделать более наглядным расположение файла:\n- короткий формат: 'parent'\n- средний формат: 'workspace/src/parent'\n- длинный формат: '/home/user/workspace/src/parent'\n- по умолчанию: '.../parent', если другая вкладка имеет такой же заголовок или относительный путь к рабочей области, если вкладки отключены", "editorTabCloseButton": "Определяет положение кнопок закрытия вкладок редактора или отключает их, если задано значение off.", "showIcons": "Определяет, должны ли открытые редакторы отображаться со значком. Требует включить тему значков.", "enablePreview": "Определяет, отображаются ли открытые редакторы в режиме предварительного просмотра. Редакторы в режиме предварительного просмотра можно использовать, пока они открыты (например, с помощью двойного щелчка мыши или изменения). Текст в таких редакторах отображается курсивом.", "enablePreviewFromQuickOpen": "Определяет, отображаются ли редакторы из Quick Open в режиме предварительного просмотра. Редакторы в режиме предварительного просмотра повторно используются до сохранения (например, с помощью двойного щелчка или изменения).", - "editorOpenPositioning": "Определяет место открытия редакторов. Выберите \"Слева\" или \"Справа\", чтобы открывать редакторы слева или справа от активного сейчас редактора. Выберите \"Первый\" или \"Последний\", чтобы открывать редакторы независимо от активного сейчас редактора.", "revealIfOpen": "Определяет, отображается ли редактор в какой-либо из видимых групп при открытии. Если функция отключена, редактор открывается в текущей активной группе редакторов. Если функция включена, вместо открытия уже открытый редактор будет отображен в текущей активной группе редакторов. Обратите внимание, что в некоторых случаях этот параметр игнорируется, например при принудительном открытии редактора в определенной группе или сбоку от текущей активной группы редакторов.", - "commandHistory": "Определяет количество недавно использованных команд, которые следует хранить в журнале палитры команд. Установите значение 0, чтобы отключить журнал команд.", "preserveInput": "Определяет, следует ли восстановить последнюю введенную команду в палитре команд при следующем открытии палитры.", "closeOnFocusLost": "Управляет автоматическим закрытием Quick Open при потере фокуса.", "openDefaultSettings": "Управляет открытием редактора с отображением всех настроек по умолчанию при открытии настроек.", @@ -50,7 +46,6 @@ "restoreWindows": "Управляет повторным открытием окон после перезапуска. Выберите 'none', чтобы всегда начинать с пустой рабочей области; 'one', чтобы открыть последнее окно, с которым вы работали; 'folders', чтобы открыть все окна с открытыми папками, и 'all', чтобы открыть все окна последнего сеанса.", "restoreFullscreen": "Определяет, должно ли окно восстанавливаться в полноэкранном режиме, если оно было закрыто в полноэкранном режиме.", "zoomLevel": "Настройте масштаб окна. Исходный размер равен 0. Увеличение или уменьшение значения на 1 означает увеличение или уменьшение окна на 20 %. Чтобы более точно задать масштаб, можно также ввести десятичное число.", - "title": "Определяет заголовок окна в зависимости от активного редактора. Подстановка переменных выполняется на основе контекста:\n${activeEditorShort}: например, myFile.txt\n${activeEditorMedium}: например, myFolder/myFile.txt\n${activeEditorLong}: например, /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: например, myFolder\n${folderPath}: например, /Users/Development/myFolder\n${rootName}: например, myFolder1, myFolder2, myFolder3\n${rootPath}: например, /Users/Development/myWorkspace\n${appName}: например, VS Code\n${dirty}: индикатор dirty, если активный редактор является \"грязным\"\n${separator}: условный разделитель (\" - \"), который отображается, только если окружен переменными со значениями ", "window.newWindowDimensions.default": "Открывать новые окна в центре экрана.", "window.newWindowDimensions.inherit": "Открывать новые окна того же размера, что и последнее активное окно.", "window.newWindowDimensions.maximized": "Открывать новые окна в развернутом состоянии.", diff --git a/i18n/rus/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 820bfa6a8c8..4c4a6981903 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "Отладка: {0}", "debugAriaLabel": "Введите имя используемой конфигурации запуска.", + "addConfigTo": "Добавить конфигурацию ({0})...", + "addConfiguration": "Добавить конфигурацию...", "noConfigurationsMatching": "Нет соответствующих конфигураций отладки.", "noConfigurationsFound": "Конфигурации отладки не найдены. Создайте файл \"launch.json\"." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..255ae8e1d50 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Отладка" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 7574689b0ef..63d876aca0d 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "Конфигурации для создания первоначального файла launch.json.", "vscode.extension.contributes.debuggers.languages": "Список языков, для которых расширение отладки может считаться \"отладчиком по умолчанию\".", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Если задано, VS Code будет вызывать эту команду, чтобы определить путь к исполняемому файлу адаптера отладки и передаваемые аргументы.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Если задано, VS Code будет вызывать эту команду для действий \"отладка\" или \"запуск\", предназначенных для этого расширения.", "vscode.extension.contributes.debuggers.configurationSnippets": "Фрагменты для добавления новых конфигураций в launch.json.", "vscode.extension.contributes.debuggers.configurationAttributes": "Конфигурации схемы JSON для проверки launch.json.", "vscode.extension.contributes.debuggers.windows": "Параметры, связанные с Windows.", diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 3333c4ffeb2..94b75507832 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,7 @@ "breakpointRemoved": "Удалена точка останова: строка {0}, файл {1}", "compoundMustHaveConfigurations": "Для составного элемента должен быть задан атрибут configurations для запуска нескольких конфигураций.", "configMissing": "Конфигурация \"{0}\" отсутствует в launch.json.", - "debugRequestNotSupported": "В выбранной конфигурации отладки указано неподдерживаемое значение атрибута '{0}': '{1}'.", - "debugRequesMissing": "В выбранной конфигурации отладки отсутствует атрибут '{0}'.", "debugTypeNotSupported": "Настроенный тип отладки \"{0}\" не поддерживается.", - "debugTypeMissing": "Отсутствует свойство \"type\" для выбранной конфигурации запуска.", "preLaunchTaskErrors": "При выполнении предварительной задачи \"{0}\" обнаружены ошибки.", "preLaunchTaskError": "При выполнении предварительной задачи \"{0}\" обнаружена ошибка.", "preLaunchTaskExitCode": "Выполнение предварительной задачи \"{0}\" завершено с кодом выхода {1}.", diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 4c742d270df..c7556643f1a 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "Состояние объекта записывается после первого вычисления", "replVariableAriaLabel": "Переменная \"{0}\" имеет значение \"{1}\", read–eval–print loop, отладка", "replExpressionAriaLabel": "Выражение \"{0}\" имеет значение \"{1}\", read–eval–print loop, отладка", - "replValueOutputAriaLabel": "{0}, read–eval–print loop, отладка", - "replKeyValueOutputAriaLabel": "Выходная переменная \"{0}\" имеет значение \"{1}\", read–eval–print loop, отладка" + "replValueOutputAriaLabel": "{0}, read–eval–print loop, отладка" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index 9a2b3bf6390..821930bfc87 100644 --- a/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Файлы", + "filesCategory": "Файл", "revealInSideBar": "Показать в боковой панели", "acceptLocalChanges": "Использовать изменения и перезаписать содержимое диска", "revertLocalChanges": "Отменить изменения и вернуться к содержимому на диске" diff --git a/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 61840ca236b..b5890f55c3b 100644 --- a/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -37,8 +37,6 @@ "openToSide": "Открыть сбоку", "compareSource": "Выбрать для сравнения", "globalCompareFile": "Сравнить активный файл с...", - "pickHistory": "Выберите предыдущий открытый файл для сравнения.", - "unableToFileToCompare": "Выбранный файл нельзя сравнить с \"{0}\".", "openFileToCompare": "Чтобы сравнить файл с другим файлом, сначала откройте его.", "compareWith": "Сравнить '{0}' с '{1}'", "compareFiles": "Сравнить файлы", @@ -47,7 +45,6 @@ "saveAs": "Сохранить как...", "saveAll": "Сохранить все", "saveAllInGroup": "Сохранить все в группе", - "saveFiles": "Сохранить файлы с изменениями", "revert": "Отменить изменения в файле", "focusOpenEditors": "Фокус на представлении открытых редакторов", "focusFilesExplorer": "Фокус на проводнике", diff --git a/i18n/rus/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/rus/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index 5eb9bd6927b..5c9b67b2669 100644 --- a/i18n/rus/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,6 @@ { "noWorkspace": "Нет открытой папки", "explorerSection": "Раздел проводника", - "noWorkspaceHelp": "Вы еще не открыли папку.", + "noFolderHelp": "Вы еще не открыли папку.", "openFolder": "Открыть папку" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..1ffd1cf8897 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Проблемы" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 71bf804e800..ef1380536bf 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Укажите параметры здесь, чтобы перезаписать параметры по умолчанию.", - "errorInvalidConfiguration": "Не удается записать параметры. Устраните ошибки и предупреждения в файле и повторите попытку.", "emptyWorkspaceSettingsHeader": "Укажите параметры здесь, чтобы перезаписать параметры пользователей.", "emptyFolderSettingsHeader": "Укажите параметры папок здесь, чтобы перезаписать параметры рабочих областей.", "defaultFolderSettingsTitle": "Параметры папок по умолчанию", diff --git a/i18n/rus/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/rus/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index 631ee068c6b..a7528085d74 100644 --- a/i18n/rus/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "Команда {0} не разрешена в текущем контексте.", "recentlyUsed": "недавно использованные", "morecCommands": "другие команды", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "Нет соответствующих команд" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index f26e342d6b3..6d0870f5800 100644 --- a/i18n/rus/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,6 @@ "exclude": "Настройте стандартные маски для исключения файлов и папок при поиске. Все стандартные маски наследуются от параметра file.exclude.", "exclude.boolean": "Стандартная маска, соответствующая путям к файлам. Задайте значение true или false, чтобы включить или отключить маску.", "exclude.when": "Дополнительная проверка элементов того же уровня соответствующего файла. Используйте $(basename) в качестве переменной для соответствующего имени файла.", - "useRipgrep": "Определяет, использовать ли ripgrep в текстовом поиске", "useIgnoreFilesByDefault": "Определяет, следует ли использовать GITIGNORE- и IGNORE-файлы по умолчанию при поиске в новой рабочей области.", "search.quickOpen.includeSymbols": "Настройте для включения результатов поиска глобальных символов в файлы по запросу для Quick Open." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json index a60edb8ea77..969c020706c 100644 --- a/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Очистить результаты поиска", "FocusNextSearchResult.label": "Перейти к следующему результату поиска.", "FocusPreviousSearchResult.label": "Перейти к предыдущему результату поиска.", - "RemoveAction.label": "Удалить", "file.replaceAll.label": "Заменить все", "match.replace.label": "Заменить" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 8f0ce17a110..d771b1fdbdc 100644 --- a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Добавляет фрагменты.", "vscode.extension.contributes.snippets-language": "Идентификатор языка, для которого добавляется этот фрагмент.", "vscode.extension.contributes.snippets-path": "Путь к файлу фрагментов. Путь указывается относительно папки расширения и обычно начинается с \"./snippets/\".", - "badFile": "Не удалось прочитать файл фрагмента \"{0}\".", "badVariableUse": "Похоже, во фрагменте \"{0}\" перепутаны переменные и заполнители. Дополнительные сведения см. на странице https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax.", + "badFile": "Не удалось прочитать файл фрагмента \"{0}\".", "source.snippet": "Фрагмент кода пользователя", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 05cb39eed74..18331d6a712 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Новый терминал", "workbench.action.terminal.focus": "Фокус на терминале", "workbench.action.terminal.focusNext": "Фокус на следующем терминале", - "workbench.action.terminal.focusAtIndex": "Фокус на терминале {0}", "workbench.action.terminal.focusPrevious": "Фокус на предыдущем терминале", "workbench.action.terminal.paste": "Вставить в активный терминал", "workbench.action.terminal.DefaultShell": "Выбрать оболочку по умолчанию", diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 92eaeea4fb9..80ae6596199 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Копировать", - "createNewTerminal": "Новый терминал", "paste": "Вставить", "selectAll": "Выбрать все", "clear": "Очистить" diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 77b64a5be2d..440d374ef82 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "ОК. Больше не показывать", "terminal.integrated.chooseWindowsShell": "Выберите предпочитаемую оболочку терминала. Ее можно позже изменить в параметрах", "terminalService.terminalCloseConfirmationSingular": "Есть активный сеанс терминала, завершить его?", - "terminalService.terminalCloseConfirmationPlural": "Есть несколько активных сеансов терминала ({0}), завершить их?", - "yes": "Да" + "terminalService.terminalCloseConfirmationPlural": "Есть несколько активных сеансов терминала ({0}), завершить их?" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..42442e0f21a --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Краткая сводка параметров. Эта метка будет использоваться в файле параметров в качестве разделяющего комментария.", + "vscode.extension.contributes.configuration.properties": "Описание свойств конфигурации.", + "scope.window.description": "Конфигурация окна, которая может быть задана в параметрах пользователя или рабочей области.", + "scope.resource.description": "Конфигурации ресурсов, которые могут быть заданы в параметрах пользователей, рабочих областей или папок.", + "scope.description": "Область, в которой применяется конфигурация. Доступные области — 'window' и 'resource'.", + "vscode.extension.contributes.configuration": "Добавляет параметры конфигурации.", + "invalid.title": "configuration.title должно быть строкой", + "vscode.extension.contributes.defaultConfiguration": "Предоставляет параметры конфигурации редактора по умолчанию в соответствии с языком.", + "invalid.properties": "configuration.properties должно быть объектом", + "invalid.allOf": "Параметр 'configuration.allOf' является устаревшим, и использовать его не рекомендуется. Вместо этого передайте несколько параметров в виде массива в точку вклада 'configuration'.", + "workspaceConfig.folders.description": "Список папок, которые будут загружены в рабочую область.", + "workspaceConfig.path.description": "Путь к файлу, например, \"/root/folderA\" или \"./folderA\" для пути по отношению к файлу рабочей области.", + "workspaceConfig.name.description": "Необязательное имя папки.", + "workspaceConfig.extensions.description": "Расширения рабочей области", + "unknownWorkspaceProperty": "Неизвестное свойство рабочей области" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/rus/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/rus/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..c91d95429ee --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Contributes textmate color themes.", + "vscode.extension.contributes.themes.id": "Идентификатор темы значка, как используется в параметрах пользователя.", + "vscode.extension.contributes.themes.label": "Метка цветовой схемы, отображаемая в пользовательском интерфейсе.", + "vscode.extension.contributes.themes.uiTheme": "Базовая тема, определяющая цвета оформления редактора: \"vs\" — светлая цветовая тема, \"vs-dark\" — темная цветовая тема. \"hc-black\" — темная высококонтрастная тема.", + "vscode.extension.contributes.themes.path": "Путь к файлу tmTheme. Путь указывается относительно папки расширения и имеет вид \"./themes/themeFile.tmTheme\".", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "В contributes.{0}.path требуется строка. Указанное значение: {1}", + "invalid.path.1": "contributes.{0}.path ({1}) должен был быть включен в папку расширения ({2}). Это может сделать расширение непереносимым." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..b0f9faf6b52 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Problems parsing file icons file: {0}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..d03dc07b9a9 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", + "vscode.extension.contributes.iconThemes.id": "Идентификатор темы значка, как используется в параметрах пользователя.", + "vscode.extension.contributes.iconThemes.label": "Метка темы значка, как отображается в пользовательском интерфейсе.", + "vscode.extension.contributes.iconThemes.path": "Путь к файлу определения темы значка. Путь задается относительно папки расширения и, как правило, имеет следующий вид: \"./icons/awesome-icon-theme.json\".", + "reqarray": "Extension point `{0}` must be an array.", + "reqpath": "В contributes.{0}.path требуется строка. Указанное значение: {1}", + "reqid": "Ожидалась строка в \"contributes.{0}.id\". Указанное значение: {1}", + "invalid.path.1": "contributes.{0}.path ({1}) должен был быть включен в папку расширения ({2}). Это может сделать расширение непереносимым." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 8caee5d0eae..e2aef412ef5 100644 --- a/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Contributes textmate color themes.", - "vscode.extension.contributes.themes.id": "Идентификатор темы значка, как используется в параметрах пользователя.", - "vscode.extension.contributes.themes.label": "Метка цветовой схемы, отображаемая в пользовательском интерфейсе.", - "vscode.extension.contributes.themes.uiTheme": "Базовая тема, определяющая цвета оформления редактора: \"vs\" — светлая цветовая тема, \"vs-dark\" — темная цветовая тема. \"hc-black\" — темная высококонтрастная тема.", - "vscode.extension.contributes.themes.path": "Путь к файлу tmTheme. Путь указывается относительно папки расширения и имеет вид \"./themes/themeFile.tmTheme\".", - "vscode.extension.contributes.iconThemes": "Contributes file icon themes.", - "vscode.extension.contributes.iconThemes.id": "Идентификатор темы значка, как используется в параметрах пользователя.", - "vscode.extension.contributes.iconThemes.label": "Метка темы значка, как отображается в пользовательском интерфейсе.", - "vscode.extension.contributes.iconThemes.path": "Путь к файлу определения темы значка. Путь задается относительно папки расширения и, как правило, имеет следующий вид: \"./icons/awesome-icon-theme.json\".", "migration.completed": "В параметры пользователя были добавлены новые параметры темы. Резервная копия доступна в {0}.", "error.cannotloadtheme": "Unable to load {0}: {1}", - "reqarray": "Extension point `{0}` must be an array.", - "reqpath": "В contributes.{0}.path требуется строка. Указанное значение: {1}", - "invalid.path.1": "contributes.{0}.path ({1}) должен был быть включен в папку расширения ({2}). Это может сделать расширение непереносимым.", - "reqid": "Ожидалась строка в \"contributes.{0}.id\". Указанное значение: {1}", "error.cannotloadicontheme": "Unable to load {0}", - "error.cannotparseicontheme": "Problems parsing file icons file: {0}", "colorTheme": "Specifies the color theme used in the workbench.", "colorThemeError": "Theme is unknown or not installed.", "iconTheme": "Указывает тему значков, используемую в рабочей области. Чтобы значки файлов не отображались, используйте значение 'null'.", "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Переопределяет цвета из выбранной цветовой темы.", - "workbenchColors.deprecated": "Параметр больше не является экспериментальным и был переименован в 'workbench.colorCustomizations'", - "workbenchColors.deprecatedDescription": "Используйте параметр 'workbench.colorCustomizations'", "editorColors": "Переопределяет цвета редактора и стиль шрифта из текущей выбранной цветовой темы.", "editorColors.comments": "Задает цвета и стили для комментариев", "editorColors.strings": "Задает цвета и стили для строковых литералов.", diff --git a/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..585cdb62fd6 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Открыть файл конфигурации рабочей области", + "close": "Закрыть" +} \ No newline at end of file diff --git a/i18n/trk/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/trk/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index cffb38fa05c..4f4f8629e96 100644 --- a/i18n/trk/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/trk/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -4,13 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "activeEditorShort": "ör. myFile.txt", - "activeEditorMedium": "ör. myFolder/myFile.txt", - "activeEditorLong": "ör. /Users/Development/myProject/myFolder/myFile.txt", - "rootName": "ör: myFolder1, myFolder2, myFolder3", - "rootPath": "ör. /Users/Development/myProject", - "folderName": "ör: myFolder", - "folderPath": "ör: /Users/Development/myFolder", "appName": "ör. VS Code", "dirty": "değişiklik göstergesi, aktif düzenleyici kaydedilmemiş değişiklikler içeriyorsa", "separator": "koşullu ayırıcı ('-') sadece değişkenler tarafından değerlerle çevrildiğinde gösterir", diff --git a/i18n/trk/extensions/emmet/package.i18n.json b/i18n/trk/extensions/emmet/package.i18n.json index e1f898b22d3..d22e3044f1e 100644 --- a/i18n/trk/extensions/emmet/package.i18n.json +++ b/i18n/trk/extensions/emmet/package.i18n.json @@ -28,13 +28,6 @@ "command.incrementNumberByTen": "10 Arttır", "command.decrementNumberByTen": "10 Azalt", "emmetSyntaxProfiles": "Belirtilen sentaks için profil tanımlayın veya kendi profilinizi belirli kurallarla kullanın.", - "emmetExclude": "Emmet kısaltmalarının genişletilmeyeceği bir diller dizisi.", - "emmetExtensionsPath": "Emmet profileri ve parçacıklarını içeren bir klasör yolu.'", - "emmetShowExpandedAbbreviation": "Genişletilmiş emmet kısaltmalarını öneriler olarak gösterir.\n\"inMarkupAndStylesheetFilesOnly\" seçeneği\" html, haml, jade, xml, xsl, css, scss, sass, less ve stylus'a uygulanır.\n\"always\" seçeneği işaretleme/css'den bağımsız olarak dosyanın tüm bölümlerine uygulanır.", - "emmetShowAbbreviationSuggestions": "Olası emmet kısaltmalarını öneriler olarak gösterir. Stil dosyalarında veya emmet.showExpandedAbbreviation, \"never\" olarak ayarlandığında uygulanamaz.", - "emmetIncludeLanguages": "Varsayılan olarak desteklenmeyen dillerde emmet kısaltmalarını etkinleştirin. Burada dil ile desteklenen emmet destekli dil arasında eşleme ekleyin.", - "emmetVariables": "Emmet parçacıklarında kullanılacak değişkenler", - "emmetTriggerExpansionOnTab": "Etkinleştirildiğinde, emmet kısaltmaları TAB tuşuna basıldığında genişletilir.", "emmetPreferences": "Emmet'in bazı eylemleri ve çözümleyicilerinin davranışını değiştirmek için kullanılacak tercihler.", "emmetPreferencesIntUnit": "Tam sayı değerleri için varsayılan birim", "emmetPreferencesFloatUnit": "Ondalık sayı değerleri için varsayılan birim", @@ -43,6 +36,5 @@ "emmetPreferencesStylusAfter": "Stylus dosyalarında CSS kısaltmaları genişletilirken CSS özelliğinin sonuna koyulacak sembol", "emmetPreferencesCssBetween": "CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol", "emmetPreferencesSassBetween": "Sass dosyalarında CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol", - "emmetPreferencesStylusBetween": "Stylus dosyalarında CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol", - "emmetShowSuggestionsAsSnippets": "Doğru ise, emmet önerileri, editor.snippetSuggestions ayarı ile sıralayabilmenizi sağlayan parçacıklar olarak gösterilir." + "emmetPreferencesStylusBetween": "Stylus dosyalarında CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol" } \ No newline at end of file diff --git a/i18n/trk/extensions/git/out/commands.i18n.json b/i18n/trk/extensions/git/out/commands.i18n.json index 062e690a02d..324d93134ea 100644 --- a/i18n/trk/extensions/git/out/commands.i18n.json +++ b/i18n/trk/extensions/git/out/commands.i18n.json @@ -12,8 +12,8 @@ "cloning": "Git deposu kopyalanıyor...", "openrepo": "Depoyu Aç", "proposeopen": "Kopyalanan depoyu açmak ister misiniz?", - "path to init": "Klasör yolu", - "provide path": "Git deposu oluşturmak için lütfen bir klasör yolu belirtin", + "init repo": "Depo Oluştur", + "create repo": "Depo Oluştur", "HEAD not available": "'{0}'e ait HEAD sürümü mevcut değil.", "confirm stage files with merge conflicts": "Birleştirme çakışmaları bulunan {0} dosyayı hazırlamak istediğinizden emin misiniz?", "confirm stage file with merge conflicts": "Birleştirme çakışmaları bulunan {0} klasörünü hazırlamak istediğinizden emin misiniz?", diff --git a/i18n/trk/extensions/git/out/repository.i18n.json b/i18n/trk/extensions/git/out/repository.i18n.json index 4f0f8a1a395..77b9fa01352 100644 --- a/i18n/trk/extensions/git/out/repository.i18n.json +++ b/i18n/trk/extensions/git/out/repository.i18n.json @@ -21,6 +21,8 @@ "deleted by us": "Bizim Tarafımızdan Silindi", "both added": "Her İkimiz de Ekledik", "both modified": "Her İkimiz de Değiştirdik", + "untracked, short": "Z", + "modified, short": "D", "commit": "Commit'le", "merge changes": "Değişiklikleri Birleştir", "staged changes": "Hazırlanmış Değişiklikler", diff --git a/i18n/trk/extensions/typescript/package.i18n.json b/i18n/trk/extensions/typescript/package.i18n.json index 6a51d6c3ed7..a4900ef3eea 100644 --- a/i18n/trk/extensions/typescript/package.i18n.json +++ b/i18n/trk/extensions/typescript/package.i18n.json @@ -44,7 +44,6 @@ "typescript.npm": "Otomatik Tür Kazanımı için kullanılacak NPM yürütülebilir dosyasının yolunu belirtir. TypeScript >= 2.3.4 gerektirir.", "typescript.check.npmIsInstalled": "Otomatik Tür Kazanımı için NPM'in yüklü olup olmadığını kontrol et.", "javascript.nameSuggestions": "JavaScript öneri listelerindeki dosyadan benzersiz adları eklemeyi etkinleştir veya devre dışı bırak.", - "typescript.tsc.autoDetect": "Tsc görevlerinin otomatik olarak algılanıp algılanmayacağını denetler. Varsayılan olarak açıktır.", "typescript.problemMatchers.tsc.label": "TypeScript sorunları", "typescript.problemMatchers.tscWatch.label": "TypeScript sorunları (izleme modu)" } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/find/browser/findWidget.i18n.json b/i18n/trk/src/vs/editor/contrib/find/browser/findWidget.i18n.json index e483c295f19..52b4e3de03f 100644 --- a/i18n/trk/src/vs/editor/contrib/find/browser/findWidget.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/find/browser/findWidget.i18n.json @@ -15,7 +15,6 @@ "label.replaceButton": "Değiştir", "label.replaceAllButton": "Tümünü Değiştir", "label.toggleReplaceButton": "Değiştirme modunu değiştir", - "title.matchesCountLimit": "Yalnızca ilk 999 sonuç vurgulandı, ancak tüm bulma işlemleri metnin tamamı üzerinde çalışıyor.", "label.matchesLocation": "{0}/{1}", "label.noResults": "Sonuç Yok" } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/find/common/findController.i18n.json b/i18n/trk/src/vs/editor/contrib/find/common/findController.i18n.json index e30fbb8a6d5..d6d3fc6ccf3 100644 --- a/i18n/trk/src/vs/editor/contrib/find/common/findController.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/find/common/findController.i18n.json @@ -10,12 +10,6 @@ "nextSelectionMatchFindAction": "Sonraki Seçimi Bul", "previousSelectionMatchFindAction": "Önceki Seçimi Bul", "startReplace": "Değiştir", - "addSelectionToNextFindMatch": "Seçimi Sonraki Bulunan Eşleşmeye Ekle", - "addSelectionToPreviousFindMatch": "Seçimi Önceki Bulunan Eşleşmeye Ekle", - "moveSelectionToNextFindMatch": "Son Seçimi Sonraki Bulunan Eşleşmeye Taşı", - "moveSelectionToPreviousFindMatch": "Son Seçimi Önceki Bulunan Eşleşmeye Taşı", - "selectAllOccurrencesOfFindMatch": "Bulunan Eşleşmenin Tüm Tekrarlamalarını Seç", - "changeAll.label": "Tüm Tekrarlamaları Değiştir", "showNextFindTermAction": "Sonraki Arama Terimini Göster", "showPreviousFindTermAction": "Önceki Arama Terimini Göster" } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json b/i18n/trk/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json index f3fa18b4184..899e10e4b02 100644 --- a/i18n/trk/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/multicursor/common/multicursor.i18n.json @@ -6,5 +6,11 @@ { "mutlicursor.insertAbove": "Yukarıya İmleç Ekle", "mutlicursor.insertBelow": "Aşağıya İmleç Ekle", - "mutlicursor.insertAtEndOfEachLineSelected": "Satır Sonlarına İmleç Ekle" + "mutlicursor.insertAtEndOfEachLineSelected": "Satır Sonlarına İmleç Ekle", + "addSelectionToNextFindMatch": "Seçimi Sonraki Bulunan Eşleşmeye Ekle", + "addSelectionToPreviousFindMatch": "Seçimi Önceki Bulunan Eşleşmeye Ekle", + "moveSelectionToNextFindMatch": "Son Seçimi Sonraki Bulunan Eşleşmeye Taşı", + "moveSelectionToPreviousFindMatch": "Son Seçimi Önceki Bulunan Eşleşmeye Taşı", + "selectAllOccurrencesOfFindMatch": "Bulunan Eşleşmenin Tüm Tekrarlamalarını Seç", + "changeAll.label": "Tüm Tekrarlamaları Değiştir" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json index 690e08f5f05..4a14af64319 100644 --- a/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.color": "Geçersiz renk biçimi. #RGB, #RGBA, #RRGGBB veya #RRGGBBAA kullanın", "schema.colors": "Çalışma ekranında kullanılan renkler.", "foreground": "Genel ön plan rengi. Bu renk, bir bileşen tarafından geçersiz kılınmadıkça kullanılır.", "errorForeground": "Hata mesajları için genel ön plan rengi. Bu renk, bir bileşen tarafından geçersiz kılınmadıkça kullanılır.", diff --git a/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json index ed0caa5b58f..006f3eee320 100644 --- a/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -9,10 +9,12 @@ "addFolderToWorkspace": "Çalışma Alanına Klasör Ekle...", "add": "&&Ekle", "addFolderToWorkspaceTitle": "Çalışma Alanına Klasör Ekle", + "globalRemoveFolderFromWorkspace": "Çalışma Alanından Klasör Kaldır...", "newWorkspace": "Yeni Çalışma Alanı...", "select": "&&Seç", "selectWorkspace": "Çalışma Alanı İçin Klasörleri Seçin", "removeFolderFromWorkspace": "Çalışma Alanından Klasör Kaldır", + "openFolderSettings": "Klasör Ayarlarını Aç", "saveWorkspaceAsAction": "Çalışma Alanını Farklı Kaydet...", "save": "&&Kaydet", "saveWorkspace": "Çalışma Alanını Kaydet", diff --git a/i18n/trk/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json index 32c2c08ce4c..832ee472cb0 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/activitybar/activitybarPart.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "hideActivitBar": "Etkinlik Çubuğunu Gizle", - "activityBarAriaLabel": "Aktif Görünüm Değiştirici", "globalActions": "Global Eylemler" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json new file mode 100644 index 00000000000..99a95a1980c --- /dev/null +++ b/i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBar.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "activityBarAriaLabel": "Aktif Görünüm Değiştirici" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json new file mode 100644 index 00000000000..fcbc6260597 --- /dev/null +++ b/i18n/trk/src/vs/workbench/browser/parts/compositebar/compositeBarActions.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "badgeTitle": "{0} - {1}", + "additionalViews": "Ek Görünümler", + "numberBadge": "{0} ({1})", + "manageExtension": "Eklentiyi Yönet", + "titleKeybinding": "{0} ({1})", + "toggle": "Görünüm Sabitlemeyi Aç/Kapat" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 9059d7f92c9..5ff77e04882 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -12,5 +12,6 @@ "groupTwoPicker": "İkinci Gruptaki Düzenleyicileri Göster", "groupThreePicker": "Üçüncü Gruptaki Düzenleyicileri Göster", "allEditorsPicker": "Açık Tüm Düzenleyicileri Göster", - "view": "Görüntüle" + "view": "Görüntüle", + "file": "Dosya" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json index ea87cdb6229..38591433f64 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/statusbar/statusbarPart.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "canNotRun": "'{0}' komutu şu an etkin değildir ve çalıştırılamaz.", "manageExtension": "Eklentiyi Yönet" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json index efdf40af46b..947272ee097 100644 --- a/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -10,18 +10,14 @@ "workspaces": "Çalışma Alanları", "developer": "Geliştirici", "showEditorTabs": "Açık düzenleyicilerin sekmelerde gösterilip gösterilmeyeceğini denetler", - "workbench.editor.labelFormat.default": "Dosyanın adını göster. Sekmeler etkinleştirilmiş ve bir grupta iki dosya aynı ada sahiplerse, her dosyanın yolundaki ayırt edici bölümler eklenir. Sekmeler devre dışı ve düzenleyici aktifse, çalışma alanı kök klasörüne göreli yol gösterilir.", "workbench.editor.labelFormat.short": "Dosyanın adını ve ardından dizin adını göster.", - "workbench.editor.labelFormat.medium": "Dosyanın adını ve ardından çalışma alanı kök klasörüne göreli yolunu göster.", "workbench.editor.labelFormat.long": "Dosyanın adını ve ardından mutlak yolunu göster.", "tabDescription": "Bir düzenleyici için etiketin biçimini denetler. Bu ayarı değiştirmek; örneğin, bir dosyanın konumunun daha kolay anlaşılmasını sağlar:\n- short: 'ustklasor'\n- medium: 'calismaalani/src/ustklasor'\n- long: '/home/user/calismaalani/src/ustklasor'\n- default: diğer bir sekme aynı başlığı paylaşıyorsa '.../ustklasor' veya sekmeler devre dışı ise göreli çalışma alanı yolu", "editorTabCloseButton": "Düzenleyici sekmelerinin kapat butonlarının konumunu denetler veya 'off' olarak ayarlandığında devre dışı bırakır.", "showIcons": "Açık düzenleyicilerin bir simge ile gösterilip gösterilmemelerini denetler. Bu, bir simge temasının etkinleştirilmesini de gerektirir.", "enablePreview": "Açık düzenleyicilerin önizleme olarak gösterilip gösterilmeyeceğini denetler. Önizleme düzenleyicileri kalıcı olarak açılana kadar (ör. çift tıklama veya düzenleme ile) tekrar kullanılırlar ve italik yazı tipiyle gösterilirler.", "enablePreviewFromQuickOpen": "Hızlı Aç'taki açık düzenleyicilerin önizleme olarak gösterilip gösterilmeyeceğini denetler. Önizleme düzenleyicileri kalıcı olarak açılana kadar (ör. çift tıklama veya düzenleme ile) tekrar kullanılırlar.", - "editorOpenPositioning": "Düzenleyicilerin nerede açılacağını denetler. Düzenleyicileri, geçerli olanın soluna veya sağına açmak için 'left' veya 'right' seçeneklerinden birini seçin. Düzenleyicileri, geçerli olandan bağımsız bir şekilde açmak için 'first' veya 'last' seçeneklerinden birini seçin.", "revealIfOpen": "Düzenleyicinin görünen gruplardan herhangi birinde açıldıysa ortaya çıkarılıp çıkarılmayacağını denetler. Devre dışı bırakılırsa; bir düzenleyici, o an aktif düzenleyici grubunda açılmayı tercih edecektir. Etkinleştirilirse; o an aktif düzenleyici grubunda tekrar açılmak yerine, zaten açık olan düzenleyici ortaya çıkarılacaktır. Bu ayarın yok sayılacağı bazı durumların olduğunu unutmayın, ör. bir düzenleyiciyi, belirli bir grupta veya o an aktif grubun yanına açmaya zorladığınızda. ", - "commandHistory": "Komut paleti geçmişinde tutulacak son kullanılan komutların sayısını denetler. Komut geçmişini kapatmak için 0 olarak ayarlayın.", "preserveInput": "Komut paletine son girilen girdinin, bir sonraki açılışta tekrar yer alıp almayacağını denetler.", "closeOnFocusLost": "Hızlı Aç'ın odağını kaybettiğinde otomatik olarak kapanıp kapanmayacağını denetler.", "openDefaultSettings": "Ayarları açmanın ayrıca tüm varsayılan ayarları gösteren bir düzenleyici açıp açmayacağını denetler.", @@ -50,7 +46,6 @@ "restoreWindows": "Pencerelerin, bir yeniden başlatma sonrası nasıl yeniden açılacağını denetler. Her zaman boş bir çalışma alanı ile başlamak için 'none', üzerinde çalıştığınız son pencereyi yeniden açmak için 'one', açık klasör bulunduran tüm pencereleri yeniden açmak için 'folders' veya son oturumunuzdaki tüm pencereleri yeniden açmak için 'all' seçeneğini seçin.", "restoreFullscreen": "Bir pencere tam ekran modundayken çıkıldıysa, bu pencerenin tam ekran moduna geri dönüp dönmeyeceğini denetler.", "zoomLevel": "Pencerenin yakınlaştırma düzeyini ayarlayın. Orijinal boyut 0'dır ve üstündeki (ör. 1) veya altındaki (ör. -1) her artırma 20% daha fazla veya az yakınlaştırmayı temsil eder. Yakınlaştırma düzeyini daha ince ayrıntılarla ayarlamak için ondalık değerler de girebilirsiniz.", - "title": "Pencere başlığını aktif düzenleyiciye bağlı olarak denetler. Değişkenler, bağlama göre değiştirilir:\n${activeEditorShort}: ör. myFile.txt\n${activeEditorMedium}: ör. myFolder/myFile.txt\n${activeEditorLong}: ör. /Users/Development/myProject/myFolder/myFile.txt\n${folderName}: ör. myFolder\n${folderPath}: ör. /Users/Development/myFolder\n${rootName}: ör. myFolder1, myFolder2, myFolder3\n${rootPath}: ör. /Users/Development/myWorkspace\n${appName}: ör. VS Code\n${dirty}: etkin düzenleyici kaydedilmemiş değişiklikler içeriyorsa, değişiklik göstergesi\n${separator}: şartlı ayırıcı (\" - \") yalnızca değer içeren değişkenlerle çevrili olduğunda gösterilir", "window.newWindowDimensions.default": "Yeni pencereleri ekranın ortasında açın.", "window.newWindowDimensions.inherit": "Yeni pencereleri son aktif pencere ile aynı ölçülerde açın.", "window.newWindowDimensions.maximized": "Yeni pencereleri ekranı kapla modunda açın.", diff --git a/i18n/trk/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index 6a22d71e97d..480910c4883 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,6 +6,8 @@ { "entryAriaLabel": "{0}, hata ayıklama", "debugAriaLabel": "Çalıştırılacak bir başlatma yapılandırması adı girin.", + "addConfigTo": "Yapılandırma Ekle ({0})...", + "addConfiguration": "Yapı&&landırma Ekle...", "noConfigurationsMatching": "Eşleyen hata ayıklama yapılandırması yok", "noConfigurationsFound": "Hiçbir hata ayıklama yapılandırması bulunamadı. Lütfen bir 'launch.json' dosyası oluşturun." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json new file mode 100644 index 00000000000..5319c1251cb --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/debug/browser/debugStatus.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "debug": "Hata Ayıklama" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/debug/browser/debugViewlet.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 0fbc09f8cc1..ea94460b89a 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -15,7 +15,6 @@ "vscode.extension.contributes.debuggers.initialConfigurations": "İlk 'launch.json' dosyasının üretimi için yapılandırmalar.", "vscode.extension.contributes.debuggers.languages": "Hata ayıklama eklentisinin, \"varsayılan hata ayıklayıcı\" olarak değerlendirilebileceği diller listesi.", "vscode.extension.contributes.debuggers.adapterExecutableCommand": "Belirtilirse; VS Code, hata ayıklama bağdaştırıcısı yürütülebilir dosyasının yolunu ve ona gönderilecek argümanları belirlemek için bu komutu çağırır.", - "vscode.extension.contributes.debuggers.startSessionCommand": "Belirtilirse; VS Code, bu eklenti için hedeflenen \"hata ayıklama\" ve \"çalıştır\" eylemleri için bu komutu çağırır.", "vscode.extension.contributes.debuggers.configurationSnippets": "'launch.json' dosyasına yeni yapılandırmalar ekleme parçacıkları.", "vscode.extension.contributes.debuggers.configurationAttributes": "'launch.json' dosyasını doğrulayacak JSON şema yapılandırmaları.", "vscode.extension.contributes.debuggers.windows": "Windows'a özel ayarlar.", diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 25a3a60a2ae..8d0432122a3 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -12,10 +12,10 @@ "breakpointRemoved": "Kesme noktası kaldırıldı, {0}. satır, {1} dosyası", "compoundMustHaveConfigurations": "Bileşik, birden çok yapılandırmayı başlatmak için \"configurations\" özniteliği bulundurmalıdır.", "configMissing": "'launch.json' dosyasında '{0}' yapılandırması eksik.", - "debugRequestNotSupported": "Seçilen hata ayıklama yapılandırması desteklenmeyen öznitelik değeri `{0}` içeriyor: '{1}'.", - "debugRequesMissing": "'{0}' özniteliği seçilen hata ayıklama yapılandırılmasında eksik.", + "debugRequestNotSupported": "Seçilen hata ayıklama yapılandırılmasındaki `{0}` özniteliği desteklenmeyen `{1}` değeri içeriyor.", + "debugRequesMissing": "`{0}` özniteliği seçilen hata ayıklama yapılandırılmasında eksik.", "debugTypeNotSupported": "Yapılandırılan hata ayıklama türü '{0}', desteklenmiyor.", - "debugTypeMissing": "Seçilen başlatma yapılandırması için 'type' özelliği eksik.", + "debugTypeMissing": "Seçilen başlatma yapılandırmasında `type` özelliği eksik.", "preLaunchTaskErrors": "'{0}' ön başlatma görevi sırasında derleme hataları algılandı.", "preLaunchTaskError": "'{0}' ön başlatma görevi sırasında derleme hatası algılandı.", "preLaunchTaskExitCode": "'{0}' ön başlatma görevi {1} çıkış koduyla sonlandı.", diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json index 3ee7a241566..59b7c7fc1a3 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/replViewer.i18n.json @@ -7,6 +7,5 @@ "stateCapture": "Nesne durumu ilk değerlendirmeden alındı", "replVariableAriaLabel": "{0} değişkeni, {1} değerine sahip, oku değerlendir yaz döngüsü, hata ayıklama", "replExpressionAriaLabel": "{0} ifadesi, {1} değerine sahip, oku değerlendir yaz döngüsü, hata ayıklama", - "replValueOutputAriaLabel": "{0}, oku değerlendir yaz döngüsü, hata ayıklama", - "replKeyValueOutputAriaLabel": "{0} çıktı değişkeni, {1} değerine sahip, oku değerlendir yaz döngüsü, hata ayıklama" + "replValueOutputAriaLabel": "{0}, oku değerlendir yaz döngüsü, hata ayıklama" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json index c907a874d19..09b50f5c819 100644 --- a/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.contribution.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "filesCategory": "Dosyalar", + "filesCategory": "Dosya", "revealInSideBar": "Kenar Çubuğunda Ortaya Çıkar", "acceptLocalChanges": "Değişikliklerinizi kullanın ve diskteki içeriklerin üzerine yazın", "revertLocalChanges": "Değişikliklerinizi göz ardı edin ve diskteki içeriğe geri dönün" diff --git a/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.i18n.json b/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.i18n.json index 84098dc8d04..36b6a59d2b2 100644 --- a/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/browser/fileActions.i18n.json @@ -37,8 +37,6 @@ "openToSide": "Yana Aç", "compareSource": "Karşılaştırma İçin Seç", "globalCompareFile": "Aktif Dosyayı Karşılaştır...", - "pickHistory": "Karşılaştırmak için daha önce açılan bir dosyayı seçin", - "unableToFileToCompare": "Seçtiğiniz dosya, '{0}' ile karşılaştırılamaz.", "openFileToCompare": "Bir başka dosya ile karşılaştırmak için ilk olarak bir dosya açın.", "compareWith": "'{0}' dosyasını '{1}' ile karşılaştır", "compareFiles": "Dosyaları Karşılaştır", @@ -47,7 +45,6 @@ "saveAs": "Farklı Kaydet...", "saveAll": "Tümünü Kaydet", "saveAllInGroup": "Gruptaki Tümünü Kadet", - "saveFiles": "Kaydedilmemiş Değişiklikler İçeren Dosyaları Kaydet", "revert": "Dosyayı Geri Döndür", "focusOpenEditors": "Açık Düzenleyiciler Görünümüne Odakla", "focusFilesExplorer": "Dosya Gezginine Odakla", diff --git a/i18n/trk/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json b/i18n/trk/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json index d14973027f7..21fd7b44865 100644 --- a/i18n/trk/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/browser/views/emptyView.i18n.json @@ -6,6 +6,6 @@ { "noWorkspace": "Açık Klasör Yok", "explorerSection": "Dosya Gezgini Bölümü", - "noWorkspaceHelp": "Henüz bir klasör açmadınız.", + "noFolderHelp": "Henüz bir klasör açmadınız.", "openFolder": "Klasör Aç" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json new file mode 100644 index 00000000000..706a42a2e0d --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/browser/markersFileDecorations.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "label": "Sorunlar" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 5992f38bfb5..f7b1f83c99e 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "emptyUserSettingsHeader": "Varsayılan ayarların üzerine yazmak için ayarlarınızı buraya yerleştirin.", - "errorInvalidConfiguration": "Ayarlara yazılamıyor. Lütfen dosyadaki hataları/uyarıları düzeltin ve tekrar deneyin.", "emptyWorkspaceSettingsHeader": "Varsayılan kullanıcı ayarlarının üzerine yazmak için ayarlarınızı buraya yerleştirin.", "emptyFolderSettingsHeader": "Çalışma alanı ayarlarındakilerin üzerine yazmak için klasör ayarlarınızı buraya yerleştirin.", "defaultFolderSettingsTitle": "Varsayılan Klasör Ayarları", diff --git a/i18n/trk/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json b/i18n/trk/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json index bef4db281ad..3164aed2f83 100644 --- a/i18n/trk/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/quickopen/browser/commandsHandler.i18n.json @@ -13,7 +13,6 @@ "actionNotEnabled": "'{0}' komutu geçerli bağlamda etkin değil.", "recentlyUsed": "yakınlarda kullanıldı", "morecCommands": "diğer komutlar", - "commandLabel": "{0}: {1}", "cat.title": "{0}: {1}", "noCommandsMatching": "Eşleşen komut yok" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/search/browser/search.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/search/browser/search.contribution.i18n.json index 803061b0af7..7c4f78fe197 100644 --- a/i18n/trk/src/vs/workbench/parts/search/browser/search.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/search/browser/search.contribution.i18n.json @@ -17,7 +17,6 @@ "exclude": "Aramalarda dosyaları ve klasörleri hariç tutmak için glob desenlerini yapılandırın. files.exclude ayarından, tüm glob desenlerini devralır.", "exclude.boolean": "Dosya yollarının eşleştirileceği glob deseni. Deseni etkinleştirmek veya devre dışı bırakmak için true veya false olarak ayarlayın.", "exclude.when": "Eşleşen bir dosyanın eşdüzey dosyalarında ek denetim. Eşleşen dosya adı için değişken olarak $(basename) kullanın.", - "useRipgrep": "Metin aramasında Ripgrep kullanılıp kullanılmayacağını denetler", "useIgnoreFilesByDefault": "Yeni bir çalışma alanında arama yaparken .gitignore ve .ignore dosyalarının varsayılan olarak kullanılıp kullanılmayacağını denetler.", "search.quickOpen.includeSymbols": "Dosya sonuçlarındaki bir global sembol aramasının sonuçlarının Hızlı Aç'a dahil edilip edilmeyeceğini yapılandırın." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 0af6fe9976d..fb6486c2e36 100644 --- a/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -19,7 +19,6 @@ "ClearSearchResultsAction.label": "Arama Sonuçlarını Temizle", "FocusNextSearchResult.label": "Sonraki Arama Sonucuna Odakla", "FocusPreviousSearchResult.label": "Önceki Arama Sonucuna Odakla", - "RemoveAction.label": "Kaldır", "file.replaceAll.label": "Tümünü Değiştir", "match.replace.label": "Değiştir" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 52c84a18c00..2f0e0bda449 100644 --- a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -10,8 +10,8 @@ "vscode.extension.contributes.snippets": "Parçacıklara ekleme yapar.", "vscode.extension.contributes.snippets-language": "Bu parçacığın ekleneceği dilin tanımlayıcısı.", "vscode.extension.contributes.snippets-path": "Parçacıklar dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './snippets/' ile başlar.", - "badFile": "Parçacık dosyası \"{0}\" okunamadı.", "badVariableUse": "\"{0}\"-parçacığı yüksek olasılıkla parçacık değişkenleri ile parçacık yer tutucularını karıştırıyor. Daha fazla bilgi için https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax adresini ziyaret edin.", + "badFile": "Parçacık dosyası \"{0}\" okunamadı.", "source.snippet": "Kullanıcı Parçacığı", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 8d8d4cb77d3..539713491df 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -16,7 +16,6 @@ "workbench.action.terminal.new.short": "Yeni Terminal", "workbench.action.terminal.focus": "Terminale Odakla", "workbench.action.terminal.focusNext": "Sonraki Terminale Odakla", - "workbench.action.terminal.focusAtIndex": "{0}. Terminale Odakla", "workbench.action.terminal.focusPrevious": "Önceki Terminale Odakla", "workbench.action.terminal.paste": "Aktif Terminale Yapıştır", "workbench.action.terminal.DefaultShell": "Varsayılan Kabuğu Seç", diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index be9f370adec..92d6df37712 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "copy": "Kopyala", - "createNewTerminal": "Yeni Terminal", "paste": "Yapıştır", "selectAll": "Tümünü Seç", "clear": "Temizle" diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 28fa93d323a..a30794054e1 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -10,6 +10,5 @@ "never again": "Tamam, Tekrar Gösterme", "terminal.integrated.chooseWindowsShell": "Tercih ettiğiniz terminal kabuğunu seçin, bunu daha sonra ayarlarınızdan değiştirebilirsiniz", "terminalService.terminalCloseConfirmationSingular": "Aktif bir terminal oturumu var, sonlandırmak istiyor musunuz?", - "terminalService.terminalCloseConfirmationPlural": "{0} aktif terminal oturumu var, bunları sonlandırmak istiyor musunuz?", - "yes": "Evet" + "terminalService.terminalCloseConfirmationPlural": "{0} aktif terminal oturumu var, bunları sonlandırmak istiyor musunuz?" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json new file mode 100644 index 00000000000..4c2ceda75b6 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.configuration.title": "Ayarların bir özeti. Bu etiket ayar dosyasında ayırıcı yorum olarak kullanılacaktır.", + "vscode.extension.contributes.configuration.properties": "Yapılandırma özelliklerinin açıklaması.", + "scope.window.description": "Kullanıcı veya çalışma alanında yapılandırılabilen Windows'a özel yapılandırma.", + "scope.resource.description": "Kullanıcı veya çalışma alanında yapılandırılabilen kaynağa özel yapılandırma.", + "scope.description": "Yapılandırmanın uygulanabilir olduğu kapsam. Mevcut kapsamlar 'window' ve 'resource'tır.", + "vscode.extension.contributes.configuration": "Yapılandırma ayarlarına ekleme yapar.", + "invalid.title": "'configuration.title' bir dize olmalıdır", + "vscode.extension.contributes.defaultConfiguration": "Varsayılan düzenleyici yapılandırma ayarlarına dil bazında ekleme yapar.", + "invalid.properties": "'configuration.properties' bir nesne olmalıdır", + "invalid.allOf": "'configuration.allOf' kullanım dışıdır ve artık kullanılmamalıdır. Bunun yerine, birden çok yapılandırma bölümlerini bir dizi olarak 'configuration' ekleme noktasına geçirin.", + "workspaceConfig.folders.description": "Çalışma alanına yüklenecek klasörler listesi.", + "workspaceConfig.path.description": "Bir dosya yolu. ör. `/root/folderA` veya çalışma alanı dosyasının konumuna karşı çözümlenecek göreceli bir yol için `./folderA`.", + "workspaceConfig.name.description": "Klasör için isteğe bağlı bir ad.", + "workspaceConfig.uri.description": "Klasörün URI'si", + "workspaceConfig.settings.description": "Çalışma alanı ayarları", + "workspaceConfig.extensions.description": "Çalışma alanı eklentileri", + "unknownWorkspaceProperty": "Bilinmeyen çalışma alanı yapılandırması özelliği" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/editor/common/editorService.i18n.json b/i18n/trk/src/vs/workbench/services/editor/common/editorService.i18n.json new file mode 100644 index 00000000000..50e968f8ee3 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/editor/common/editorService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "compareLabels": "{0} ↔ {1}" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/trk/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json new file mode 100644 index 00000000000..ab403ef3493 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.themes": "Textmate renk temalarına ekleme yapar.", + "vscode.extension.contributes.themes.id": "Kullanıcı ayarlarında kullanılan simge teması Id'si.", + "vscode.extension.contributes.themes.label": "Kullanıcı arayüzünde görünen renk temasının etiketi.", + "vscode.extension.contributes.themes.uiTheme": "Editördeki renkleri tanımlayan temel tema: 'vs' açık renk temasıdır, 'vs-dark' koyu renk temasıdır. 'hc-black' ise yüksek kontrast temasıdır.", + "vscode.extension.contributes.themes.path": "tmLanguage dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './themes/themeFile.tmTheme'dir.", + "reqarray": "Eklenti noktası `{0}` bir dizi olmalıdır.", + "reqpath": "`contributes.{0}.path` ögesinde dize bekleniyor. Sağlanan değer: {1}", + "invalid.path.1": "`contributes.{0}.path` ögesinin ({1}) eklentinin klasöründe ({2}) yer alması bekleniyor. Bu, eklentiyi taşınamaz yapabilir." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json b/i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json new file mode 100644 index 00000000000..c7286a77b94 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "error.cannotparseicontheme": "Dosya simgeleri dosyasını ayrıştırma sorunları: {0}" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json new file mode 100644 index 00000000000..65e81b3fdbf --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "vscode.extension.contributes.iconThemes": "Dosya simgesi temalarına ekleme yapar.", + "vscode.extension.contributes.iconThemes.id": "Kullanıcı ayarlarında kullanılan simge teması Id'si.", + "vscode.extension.contributes.iconThemes.label": "Kullanıcı arayüzünde görünen simge temasının etiketi.", + "vscode.extension.contributes.iconThemes.path": "Simge teması tanımlama dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './icons/awesome-icon-theme.json'dur.", + "reqarray": "Eklenti noktası `{0}` bir dizi olmalıdır.", + "reqpath": "`contributes.{0}.path` ögesinde dize bekleniyor. Sağlanan değer: {1}", + "reqid": "`contributes.{0}.id` ögesinde dize bekleniyordu. Belirtilen değer: {1}", + "invalid.path.1": "`contributes.{0}.path` ögesinin ({1}) eklentinin klasöründe ({2}) yer alması bekleniyor. Bu, eklentiyi taşınamaz yapabilir." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 44429da31b5..6715de58332 100644 --- a/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -4,31 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "vscode.extension.contributes.themes": "Textmate renk temalarına ekleme yapar.", - "vscode.extension.contributes.themes.id": "Kullanıcı ayarlarında kullanılan simge teması Id'si.", - "vscode.extension.contributes.themes.label": "Kullanıcı arayüzünde görünen renk temasının etiketi.", - "vscode.extension.contributes.themes.uiTheme": "Editördeki renkleri tanımlayan temel tema: 'vs' açık renk temasıdır, 'vs-dark' koyu renk temasıdır. 'hc-black' ise yüksek kontrast temasıdır.", - "vscode.extension.contributes.themes.path": "tmLanguage dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './themes/themeFile.tmTheme'dir.", - "vscode.extension.contributes.iconThemes": "Dosya simgesi temalarına ekleme yapar.", - "vscode.extension.contributes.iconThemes.id": "Kullanıcı ayarlarında kullanılan simge teması Id'si.", - "vscode.extension.contributes.iconThemes.label": "Kullanıcı arayüzünde görünen simge temasının etiketi.", - "vscode.extension.contributes.iconThemes.path": "Simge teması tanımlama dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './icons/awesome-icon-theme.json'dur.", "migration.completed": "Yeni tema ayarları kullanıcı ayarlarına eklendi. Yedek, {0} konumunda mevcuttur.", "error.cannotloadtheme": "{0} yüklenemedi: {1}", - "reqarray": "Eklenti noktası `{0}` bir dizi olmalıdır.", - "reqpath": "`contributes.{0}.path` ögesinde dize bekleniyor. Sağlanan değer: {1}", - "invalid.path.1": "`contributes.{0}.path` ögesinin ({1}) eklentinin klasöründe ({2}) yer alması bekleniyor. Bu, eklentiyi taşınamaz yapabilir.", - "reqid": "`contributes.{0}.id` ögesinde dize bekleniyordu. Belirtilen değer: {1}", "error.cannotloadicontheme": "{0} yüklenemedi", - "error.cannotparseicontheme": "Dosya simgeleri dosyasını ayrıştırma sorunları: {0}", "colorTheme": "Çalışma ekranında kullanılan renk temasını belirtir.", "colorThemeError": "Tema bilinmiyor veya yüklenmemiş.", "iconTheme": "Çalışma ekranında kullanılan simge temasını veya hiçbir dosya simgesi göstermemek için 'null' belirtir.", "noIconThemeDesc": "Dosya simgesi yok", "iconThemeError": "Dosya simgesi teması bilinmiyor veya yüklenmemiş.", "workbenchColors": "Şu an seçili renk temasındaki renkleri geçersiz kılar.", - "workbenchColors.deprecated": "Ayar, artık deneysel değildir ve 'workbench.colorCustomizations' olarak yeniden adlandırılmıştır", - "workbenchColors.deprecatedDescription": "Bunun yerine 'workbench.colorCustomizations' kullanın", "editorColors": "Şu an seçili renk temasındaki düzenleyici renklerini ve yazı tipi stilini geçersiz kılar.", "editorColors.comments": "Yorumların rengini ve stillerini ayarlar", "editorColors.strings": "Dizelerin rengini ve stillerini ayarlar.", diff --git a/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json new file mode 100644 index 00000000000..776050fe34c --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openWorkspaceConfigurationFile": "Çalışma Alanı Yapılandırma Dosyasını Aç", + "close": "Kapat" +} \ No newline at end of file From 83db0069f198fe88b2fd3144390f0ff86d440d9b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 23 Oct 2017 11:55:54 -0700 Subject: [PATCH 394/394] Add some extra logging for TSServer start --- extensions/typescript/src/typescriptServiceClient.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index 8163808609d..3224a1f64b5 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -231,6 +231,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient if (this.servicePromise) { this.servicePromise = this.servicePromise.then(cp => { if (cp) { + this.info('Killing TS Server'); this.isRestarting = true; cp.kill(); } @@ -401,7 +402,10 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient this.logTelemetry('error', { message: err.message }); return; } + + this.info('Started TSServer'); this.lastStart = Date.now(); + childProcess.on('error', (err: Error) => { this.lastError = err; this.error('TSServer errored with error.', err); @@ -416,7 +420,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient }); childProcess.on('exit', (code: any) => { if (code === null || typeof code === 'undefined') { - this.info(`TSServer exited`); + this.info('TSServer exited'); } else { this.error(`TSServer exited with code: ${code}`); /* __GDPR__